Skip to content

Commit

Permalink
(#170) Funogram: enable message thread filtering and sending
Browse files Browse the repository at this point in the history
  • Loading branch information
ForNeVeR committed Nov 15, 2022
1 parent f21f325 commit cb35568
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 10 deletions.
3 changes: 3 additions & 0 deletions Emulsion.Settings/Settings.fs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type XmppSettings = {
type TelegramSettings = {
Token: string
GroupId: int64
MessageThreadId: int64 option
}

type LogSettings = {
Expand Down Expand Up @@ -63,6 +64,7 @@ let private readTimeSpan defaultVal key section =
|> Option.defaultValue defaultVal

let read (config : IConfiguration) : EmulsionSettings =
let int64Opt: string -> int64 option = Option.ofObj >> Option.map int64
let uint64OrDefault value ``default`` =
value
|> Option.ofObj
Expand All @@ -83,6 +85,7 @@ let read (config : IConfiguration) : EmulsionSettings =
let readTelegram (section : IConfigurationSection) = {
Token = section["token"]
GroupId = int64 section["groupId"]
MessageThreadId = int64Opt section["messageThreadId"]
}
let readLog(section: IConfigurationSection) = {
Directory = section["directory"]
Expand Down
32 changes: 25 additions & 7 deletions Emulsion.Telegram/Funogram.fs
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,15 @@ module MessageConverter =
let messageText = text.Substring messageTextOffset
Authored { author = authorName; text = messageText }

let (|ForumTopicCreatedMessage|_|) (m: FunogramMessage option) =
match m with
| Some m when Option.isSome m.ForumTopicCreated -> Some m
| _ -> None

let internal read (selfUserId: int64) (message: FunogramMessage, links: TelegramThreadLinks): ThreadMessage =
let mainMessage = extractMessageContent message links.ContentLinks
match message.ReplyToMessage with
| None -> { main = mainMessage; replyTo = None }
| None | ForumTopicCreatedMessage _ -> { main = mainMessage; replyTo = None }
| Some replyTo ->
let replyToMessage =
if isSelfMessage selfUserId replyTo
Expand All @@ -310,9 +315,14 @@ let private extractLinkData logger databaseSettings hostingSettings message =
let internal processMessage (logger: ILogger)
(databaseSettings: DatabaseSettings option)
(hostingSettings: HostingSettings option)
(context: {| SelfUserId: int64; GroupId: int64 |})
(context: {| SelfUserId: int64; GroupId: int64; MessageThreadId: int64 option |})
(message: FunogramMessage): Message option =
if context.GroupId = message.Chat.Id
let correctGroup = context.GroupId = message.Chat.Id
let correctThread =
match context.MessageThreadId with
| None -> true
| _ -> message.MessageThreadId = context.MessageThreadId
if correctGroup && correctThread
then
message
|> extractLinkData logger databaseSettings hostingSettings
Expand All @@ -324,12 +334,14 @@ let internal processMessage (logger: ILogger)
let private updateArrived databaseSettings
hostingSettings
groupId
messageThreadId
(logger: ILogger)
onMessage
(ctx: Bot.UpdateContext) =
let readContext = {|
SelfUserId = ctx.Me.Id
GroupId = groupId
MessageThreadId = messageThreadId
|}
Bot.processCommands ctx [
fun ctx ->
Expand All @@ -338,7 +350,7 @@ let private updateArrived databaseSettings
logger.Information("Incoming Telegram message: {Message}", msg)
match processMessage logger databaseSettings hostingSettings readContext msg with
| Some m -> onMessage(TelegramMessage m)
| None -> logger.Warning "Message from unidentified source ignored"
| None -> ()
true
| _ -> false
] |> ignore
Expand All @@ -355,10 +367,11 @@ let sendGetFile (botConfig: BotConfig) (fileId: string): Async<File> = async {
}

let sendMessage (settings: TelegramSettings) (botConfig: BotConfig) (OutgoingMessage content): Async<unit> =
let groupId = Int(int64 settings.GroupId)
let threadId = settings.MessageThreadId
let sendHtmlMessage (groupId: ChatId) text =
Req.SendMessage.Make(chatId = groupId, text = text, parseMode = ParseMode.HTML)
Req.SendMessage.Make(chatId = groupId, text = text, ?messageThreadId = threadId, parseMode = ParseMode.HTML)

let groupId = Int(int64 settings.GroupId)
let message = prepareHtmlMessage content
async {
let! result = send botConfig (sendHtmlMessage groupId message)
Expand All @@ -373,5 +386,10 @@ let run (logger: ILogger)
(botConfig: BotConfig)
(onMessage: IncomingMessage -> unit): Async<unit> =
Bot.startBot botConfig
(updateArrived databaseSettings hostingSettings telegramSettings.GroupId logger onMessage)
(updateArrived databaseSettings
hostingSettings
telegramSettings.GroupId
telegramSettings.MessageThreadId
logger
onMessage)
None
1 change: 1 addition & 0 deletions Emulsion.Tests/SettingsTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ let private testConfiguration = {
Telegram = {
Token = "token"
GroupId = testGroupId
MessageThreadId = None
}
Log = {
Directory = "/tmp/"
Expand Down
74 changes: 72 additions & 2 deletions Emulsion.Tests/Telegram/FunogramTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -547,19 +547,89 @@ module ReadMessageTests =
readMessage reply
)

[<Fact>]
let ``Reply to forum topic creation shouldn't be taken into account``(): unit =
let originalMessage = {
defaultMessage with
ForumTopicCreated = Some <| ForumTopicCreated.Create("Topic", 0L)
}
let replyMessage = createReplyMessage (Some replyingUser) (Some "text") originalMessage
Assert.Equal(
authoredTelegramMessage "@replyingUser" "text",
readMessage replyMessage
)

module ProcessMessageTests =
let private processMessageOpt o =
processMessage Logger.None None None o

let private processMessage =
Funogram.processMessage Logger.None None None {| SelfUserId = selfUserId; GroupId = groupId |}
processMessageOpt {| SelfUserId = selfUserId; GroupId = groupId; MessageThreadId = None |}

[<Fact>]
let ``Message with correct group is not ignored``(): unit =
let message = {
createMessage (Some originalUser) (Some "test") with
Chat = Chat.Create(
id = groupId,
``type`` = ChatType.SuperGroup
)
}
Assert.True(Option.isSome <| processMessage message)

[<Fact>]
let messageFromOtherChatShouldBeIgnored(): unit =
let ``Message from other chat is ignored``(): unit =
let message = { createMessage (Some originalUser) (Some "test") with
Chat = Chat.Create(
id = 0L,
``type`` = ChatType.SuperGroup
) }
Assert.Equal(None, processMessage message)

[<Fact>]
let ``Message from incorrect thread is ignored``(): unit =
let message = {
createMessage (Some originalUser) (Some "test") with
Chat = Chat.Create(
id = groupId,
``type`` = ChatType.SuperGroup
)
MessageThreadId = Some 123L

}
Assert.Equal(None, processMessageOpt {|
SelfUserId = selfUserId
GroupId = groupId
MessageThreadId = Some 234L
|} message)

let ``Message with any thread id is not ignored if thread id is not set``(): unit =
let message = {
createMessage (Some originalUser) (Some "test") with
Chat = Chat.Create(
id = groupId,
``type`` = ChatType.SuperGroup
)
MessageThreadId = Some 123L
}
Assert.True(Option.isSome <| processMessage message)

let ``Message with correct thread id is not ignored``(): unit =
let threadId = 236L
let message = {
createMessage (Some originalUser) (Some "test") with
Chat = Chat.Create(
id = groupId,
``type`` = ChatType.SuperGroup
)
MessageThreadId = Some threadId
}
Assert.True(Option.isSome <| processMessageOpt {|
SelfUserId = selfUserId
GroupId = groupId
MessageThreadId = Some threadId
|} message)

module ProcessSendResultTests =
[<Fact>]
let processResultShouldDoNothingOnOk(): unit =
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ All the other settings are required, except the `database`, `hosting` and `fileC

Note that `pingInterval` of `null` disables XMPP ping support.

`telegram.messageThreadId` allows to connect the bot to a particular message thread: any messages from the other threads will be ignored, and the bot will send its messages to the selected thread only.

### Telegram Content Proxy

There's Telegram content proxy support, for XMPP users to access Telegram content without directly opening links on t.me.
Expand Down
3 changes: 2 additions & 1 deletion emulsion.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
},
"telegram": {
"token": "999999999:aaaaaaaaaaaaaaaaaaaaaaaaa_777777777",
"groupId": 12312312312
"groupId": 12312312312,
"messageThreadId": 123456
},
"log": {
"directory": "./logs/"
Expand Down

0 comments on commit cb35568

Please sign in to comment.