From 66349fbf55be1715fcd0014a2335ecab0a708e71 Mon Sep 17 00:00:00 2001 From: Keroosha Date: Tue, 15 Aug 2023 20:33:33 +0300 Subject: [PATCH] Use UserId instead of Username for unban command --- src/Grinder/Commands.fs | 63 +++++++++++++--------------- src/Grinder/Funogram.fs | 44 ++++++++----------- src/Grinder/Program.fs | 14 +++---- src/Grinder/Types.fs | 4 +- tests/Grinder.Tests/CommandsTests.fs | 12 +++--- 5 files changed, 62 insertions(+), 75 deletions(-) diff --git a/src/Grinder/Commands.fs b/src/Grinder/Commands.fs index 157b016..9e13438 100644 --- a/src/Grinder/Commands.fs +++ b/src/Grinder/Commands.fs @@ -10,6 +10,7 @@ module Parser = open FParsec type Usernames = Usernames of string list + type UserIds = UserIds of int64 list [] type private parserError type ParserError = string @@ -58,6 +59,7 @@ module Parser = type Command = | UserCommand of Usernames * CommandAction + | UserCommandWithIds of UserIds * CommandAction | Ping let str s = pstring s @@ -83,6 +85,9 @@ module Parser = let many1Usernames: Parser = many1 (pusername .>> spaces) + let many1UserId: Parser = + many1 (pint64 .>> spaces) + let sumTimedFractions (fractions: TimeFraction list) = let summator = TimeFractionSummator() for fraction in fractions do @@ -118,13 +123,14 @@ module Parser = let pping: Parser = str "ping" >>% Ping - - let pcommandAction: Parser = - pban <|> punban let parseCommand botUsername = pbotUsername botUsername >>. - (pping <|> pipe2 many1Usernames pcommandAction (fun usernames command -> UserCommand(Usernames(usernames), command))) + ( + pping + <|> pipe2 many1Usernames pban (fun usernames command -> UserCommand(Usernames(usernames), command)) + <|> pipe2 many1UserId punban (fun userIds command -> UserCommandWithIds(UserIds(userIds), command)) + ) let runCommandParser botUsername str: ParserResult = run (parseCommand botUsername) str @@ -279,7 +285,7 @@ module Processing = From: UserUsername MessageId: TelegramMessageId ChatId: TelegramChatId - Usernames: UserUsername seq + UserIds: TelegramUserId seq } type PingContext = { @@ -339,20 +345,20 @@ module Processing = sprintf "Banned %s in chats %s %s" usernamesText chatsText durationText type UnbanMessage = - { Usernames: UserUsername seq + { UserIds: TelegramUserId seq Chats: ChatUsername seq } interface IMessage with member __.FormatAsString() = - let usernamesText = - __.Usernames - |> Seq.map ^ fun username -> %username + let userIds = + __.UserIds + |> Seq.map ^ fun x -> $"{x}" |> String.join ", " let chatsText = __.Chats |> Seq.map ^ fun chat -> %chat |> String.join ", " - sprintf "Unbanned %s in chats %s" usernamesText chatsText + sprintf "Unbanned %s in chats %s" userIds chatsText type CommandMessage = | BanMessage of UserUsername * BanMessage * CommandError array @@ -384,7 +390,7 @@ module Processing = | _ -> DoNothingCommand let parseTextMessage (context: TextMessageContext): Command = - match Parser.parse %context.BotUsername context.MessageText with + match parse %context.BotUsername context.MessageText with | BotCommand(UserCommand((Usernames usernames), Ban(duration))) -> let usernames = usernames @@ -398,22 +404,22 @@ module Processing = Until = duration } BanCommand context - | BotCommand(UserCommand((Usernames usernames), Unban)) -> - let usernames = - usernames - |> Seq.map ^ fun username -> %username - + | BotCommand(UserCommandWithIds(UserIds userIds, Unban)) -> + let userIds = userIds |> Seq.map ^ fun x -> %x let context = { From = %context.FromUsername MessageId = %context.Message.MessageId ChatId = %context.Message.Chat.Id - Usernames = usernames + UserIds = userIds } UnbanCommand context | BotCommand(Ping) -> PingCommand { ChatId = %context.Message.Chat.Id } | InvalidCommand _ -> DoNothingCommand + // Any miss-matched commands goes to "do nothing club" + | BotCommand command -> + DoNothingCommand let executeCommand (botSettings: BotSettings) (botApi: IBotApi) (dataApi: IDataAccessApi) command: Async = async { let getErrors results = @@ -519,7 +525,7 @@ module Processing = do! botApi.DeleteMessage context.ChatId context.MessageId let requests = - [for user in context.Usernames do + [for user in context.UserIds do for chat in botSettings.ChatsToMonitor.Set do yield botApi.UnbanUser chat user |> Async.Map ^ Result.mapError @@ -542,31 +548,20 @@ module Processing = let message = { Chats = botSettings.ChatsToMonitor.Set - Usernames = context.Usernames + UserIds = context.UserIds } return Some <| UnbanMessage(context.From, message, errors) | UnbanOnReplyCommand context -> - let! username = async { - match context.Username with - | Some username -> - do! dataApi.UpsertUsers [DataAccess.User(UserId = %context.UserId, Username = %username)] - return username - | None -> - let! username = dataApi.GetUsernameByUserId context.UserId - return username - |> Option.map ^ fun name -> %(sprintf "@%s" %name) - |> Option.defaultValue %"unknown user" - } - + let userId = context.UserId do! botApi.DeleteMessage context.ChatId context.MessageId let requests = [for chat in botSettings.ChatsToMonitor.Set do - yield botApi.UnbanUser chat username + yield botApi.UnbanUser chat userId |> Async.Map ^ Result.mapError (sprintf "Error on unban user %A in chat %A. %s" - username + userId chat >> ApiError)] @@ -579,7 +574,7 @@ module Processing = let message = { Chats = botSettings.ChatsToMonitor.Set - Usernames = Set.empty.Add username + UserIds = Set.empty.Add userId } return Some <| UnbanOnReplyMessage(context.From, message, errors) diff --git a/src/Grinder/Funogram.fs b/src/Grinder/Funogram.fs index 2674c2a..c1d6358 100644 --- a/src/Grinder/Funogram.fs +++ b/src/Grinder/Funogram.fs @@ -93,34 +93,26 @@ module ApiExt = return Error <| sprintf "Failed to ban %i in chat %s. Description: %s" userId chat e.Description } - let unbanUserByUsername context chat username onlyIfBanned = async { - match! Datastore.findUserIdByUsername username with - | UserIdFound userId -> - let! unbanResult = - unbanChatMemberByChatNameExt chat userId onlyIfBanned - |> callApiWithDefaultRetry context - match unbanResult with - | Ok _ -> - return Ok () - | Error e -> - return Error <| sprintf "Failed to unban %s in chat %s. Description: %s" username chat e.Description - | UserIdNotFound -> - return Error <| sprintf "Couldn't resolve username %s" username + let unbanUserByUserId context chat userId onlyIfBanned = async { + let! unbanResult = + unbanChatMemberByChatNameExt chat userId onlyIfBanned + |> callApiWithDefaultRetry context + match unbanResult with + | Ok _ -> + return Ok () + | Error e -> + return Error <| sprintf "Failed to unban %d in chat %s. Description: %s" userId chat e.Description } - let unrestrictUserByUsername context chat username = async { - match! Datastore.findUserIdByUsername username with - | UserIdFound userId -> - let! restrictResult = - restrictChatMemberBase (Funogram.Types.String(chat)) userId None (Some true) (Some true) (Some true) (Some true) - |> callApiWithDefaultRetry context - match restrictResult with - | Ok _ -> - return Ok () - | Error e -> - return Error <| sprintf "Failed to unrestrict %s in chat %s. Description: %s" username chat e.Description - | UserIdNotFound -> - return Error <| sprintf "Couldn't resolve username %s" username + let unrestrictUserByUserId context chat userId = async { + let! restrictResult = + restrictChatMemberBase (String(chat)) userId None (Some true) (Some true) (Some true) (Some true) + |> callApiWithDefaultRetry context + match restrictResult with + | Ok _ -> + return Ok () + | Error e -> + return Error <| sprintf "Failed to unrestrict %d in chat %s. Description: %s" userId chat e.Description } let sendMessage (chatId: TelegramChatId) context text = diff --git a/src/Grinder/Program.fs b/src/Grinder/Program.fs index 3edf391..6e1154e 100644 --- a/src/Grinder/Program.fs +++ b/src/Grinder/Program.fs @@ -1,4 +1,4 @@ -namespace Grinder +namespace Grinder open System.IO open System.Net @@ -79,10 +79,10 @@ module Program = |> logInfo ApiExt.banUserByUserId config %chatUsername %userId until - member __.UnbanUser chatUsername username: Async> = - sprintf "Unbanning user %A in chat %A" username chatUsername + member __.UnbanUser chatUsername userId: Async> = + sprintf "Unbanning user %d in chat %A" userId chatUsername |> logInfo - ApiExt.unbanUserByUsername config %chatUsername %username true // Do nothing if user not banned + ApiExt.unbanUserByUserId config %chatUsername %userId true // Do nothing if user not banned member __.SendTextMessage chatId text: Async = sprintf "Sending {%s} into chat %A" text chatId @@ -96,10 +96,10 @@ module Program = |> logExn e ) - member __.UnrestrictUser chatUsername username: Async> = - sprintf "Unrestricting user %A in chat %A"username chatUsername + member __.UnrestrictUser chatUsername userId: Async> = + sprintf "Unrestricting user %d in chat %A"userId chatUsername |> logInfo - ApiExt.unrestrictUserByUsername config %chatUsername %username + ApiExt.unrestrictUserByUserId config %chatUsername %userId member __.SendTextToChannel text: Async = sprintf "Sending {%s} into special channel %A" text settings.ChannelId diff --git a/src/Grinder/Types.fs b/src/Grinder/Types.fs index 8d0aa38..3a7b1d5 100644 --- a/src/Grinder/Types.fs +++ b/src/Grinder/Types.fs @@ -103,8 +103,8 @@ type IBotApi = abstract member DeleteMessage: TelegramChatId -> TelegramMessageId -> Async abstract member BanUserByUsername: ChatUsername -> UserUsername -> DateTime -> Async> abstract member BanUserByUserId: ChatUsername -> TelegramUserId -> DateTime -> Async> - abstract member UnbanUser: ChatUsername -> UserUsername -> Async> - abstract member UnrestrictUser: ChatUsername -> UserUsername -> Async> + abstract member UnbanUser: ChatUsername -> TelegramUserId -> Async> + abstract member UnrestrictUser: ChatUsername -> TelegramUserId -> Async> abstract member SendTextToChannel: string -> Async abstract member SendTextMessage: TelegramChatId -> string -> Async abstract member PrepareAndDownloadFile: string -> Async> \ No newline at end of file diff --git a/tests/Grinder.Tests/CommandsTests.fs b/tests/Grinder.Tests/CommandsTests.fs index 879b428..23240f4 100644 --- a/tests/Grinder.Tests/CommandsTests.fs +++ b/tests/Grinder.Tests/CommandsTests.fs @@ -319,10 +319,10 @@ let ``BanMessage FormatAsString returns correct message when date is more than a [] let ``UnbanMessage FormatAsString returns correct message``() = - let expected = """Unbanned @user1, @user2 in chats @chat1, @chat2""" + let expected = """Unbanned 123, 321 in chats @chat1, @chat2""" let message = { - Usernames = [%"@user1"; %"@user2"] + UserIds = [%int64 123; %int64 321] Chats = [%"@chat1"; %"@chat2"] } @@ -378,11 +378,11 @@ let ``formatMessage returns correct message for ban on reply message without err [] let ``formatMessage returns correct message for unban``() = async { let message = { - Usernames = [%"@user1"; %"@user2"] + UserIds = [%int64 123; %int64 321] Chats = [%"@chat1"; %"@chat2"] } - let expected = "Unban command from: @user\n\nUnbanned @user1, @user2 in chats @chat1, @chat2" + let expected = "Unban command from: @user\n\nUnbanned 123, 321 in chats @chat1, @chat2" let commandMessage = UnbanMessage(%"user", message, [||]) @@ -392,11 +392,11 @@ let ``formatMessage returns correct message for unban``() = async { [] let ``formatMessage returns correct message for unban on reply``() = async { let message = { - Usernames = [%"@user1"; %"@user2"] + UserIds = [%int64 123; %int64 321] Chats = [%"@chat1"; %"@chat2"] } - let expected = "Unban on reply command from: @user\n\nUnbanned @user1, @user2 in chats @chat1, @chat2" + let expected = "Unban on reply command from: @user\n\nUnbanned 123, 321 in chats @chat1, @chat2" let commandMessage = UnbanOnReplyMessage(%"user", message, [||])