Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use UserId for unban command #14

Merged
merged 2 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 29 additions & 34 deletions src/Grinder/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module Parser =
open FParsec

type Usernames = Usernames of string list
type UserIds = UserIds of int64 list

[<Measure>] type private parserError
type ParserError = string<parserError>
Expand Down Expand Up @@ -58,6 +59,7 @@ module Parser =

type Command =
| UserCommand of Usernames * CommandAction
| UserCommandWithIds of UserIds * CommandAction
| Ping

let str s = pstring s
Expand All @@ -83,6 +85,9 @@ module Parser =
let many1Usernames: Parser<string list, unit> =
many1 (pusername .>> spaces)

let many1UserId: Parser<int64 list, unit> =
many1 (pint64 .>> spaces)

let sumTimedFractions (fractions: TimeFraction list) =
let summator = TimeFractionSummator()
for fraction in fractions do
Expand Down Expand Up @@ -118,13 +123,14 @@ module Parser =

let pping: Parser<Command, unit> =
str "ping" >>% Ping

let pcommandAction: Parser<CommandAction, unit> =
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<Command, unit> =
run (parseCommand botUsername) str
Expand Down Expand Up @@ -279,7 +285,7 @@ module Processing =
From: UserUsername
MessageId: TelegramMessageId
ChatId: TelegramChatId
Usernames: UserUsername seq
UserIds: TelegramUserId seq
}

type PingContext = {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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<CommandMessage option> = async {
let getErrors results =
Expand Down Expand Up @@ -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
Expand All @@ -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)]

Expand All @@ -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)
Expand Down
44 changes: 18 additions & 26 deletions src/Grinder/Funogram.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
14 changes: 7 additions & 7 deletions src/Grinder/Program.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Grinder
namespace Grinder

open System.IO
open System.Net
Expand Down Expand Up @@ -79,10 +79,10 @@ module Program =
|> logInfo
ApiExt.banUserByUserId config %chatUsername %userId until

member __.UnbanUser chatUsername username: Async<Result<unit, string>> =
sprintf "Unbanning user %A in chat %A" username chatUsername
member __.UnbanUser chatUsername userId: Async<Result<unit, string>> =
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<unit> =
sprintf "Sending {%s} into chat %A" text chatId
Expand All @@ -96,10 +96,10 @@ module Program =
|> logExn e
)

member __.UnrestrictUser chatUsername username: Async<Result<unit, string>> =
sprintf "Unrestricting user %A in chat %A"username chatUsername
member __.UnrestrictUser chatUsername userId: Async<Result<unit, string>> =
sprintf "Unrestricting user %d in chat %A"userId chatUsername
|> logInfo
ApiExt.unrestrictUserByUsername config %chatUsername %username
ApiExt.unrestrictUserByUserId config %chatUsername %userId

member __.SendTextToChannel text: Async<unit> =
sprintf "Sending {%s} into special channel %A" text settings.ChannelId
Expand Down
4 changes: 2 additions & 2 deletions src/Grinder/Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ type IBotApi =
abstract member DeleteMessage: TelegramChatId -> TelegramMessageId -> Async<unit>
abstract member BanUserByUsername: ChatUsername -> UserUsername -> DateTime -> Async<Result<unit, string>>
abstract member BanUserByUserId: ChatUsername -> TelegramUserId -> DateTime -> Async<Result<unit, string>>
abstract member UnbanUser: ChatUsername -> UserUsername -> Async<Result<unit, string>>
abstract member UnrestrictUser: ChatUsername -> UserUsername -> Async<Result<unit, string>>
abstract member UnbanUser: ChatUsername -> TelegramUserId -> Async<Result<unit, string>>
abstract member UnrestrictUser: ChatUsername -> TelegramUserId -> Async<Result<unit, string>>
abstract member SendTextToChannel: string -> Async<unit>
abstract member SendTextMessage: TelegramChatId -> string -> Async<unit>
abstract member PrepareAndDownloadFile: string -> Async<Result<Stream, string>>
12 changes: 6 additions & 6 deletions tests/Grinder.Tests/CommandsTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,10 @@ let ``BanMessage FormatAsString returns correct message when date is more than a

[<Fact>]
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"]
}

Expand Down Expand Up @@ -378,11 +378,11 @@ let ``formatMessage returns correct message for ban on reply message without err
[<Fact>]
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, [||])

Expand All @@ -392,11 +392,11 @@ let ``formatMessage returns correct message for unban``() = async {
[<Fact>]
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, [||])

Expand Down
Loading