module PublishHelperBot.Handlers
open System.Threading.Tasks
open Microsoft.FSharp.Core
open PublishHelperBot.Environment
open PublishHelperBot.YoutubeDl
open Telegram.Bot
open Telegram.Bot.Types
open Telegram.Bot.Types.Enums
type BaseHandlerArgs = Update * BotConfig
type HandlerArgs = Update * BotConfig * ITelegramBotClient
type HandlerRequirements = BaseHandlerArgs -> bool
type Handler = HandlerArgs -> Task
type Handler<'deps> = 'deps * HandlerArgs -> Task
// Utils
let UpdateIsAMessage (x: Update) = x.Type = UpdateType.Message
let FromAdminChat (x: Message, c: BotConfig) = x.Chat.Id = c.adminChatId
let HasReply (x: Message) = not(isNull x.ReplyToMessage)
let ExtractPhotoFromMessage (x: Message) = Array.map (fun (p: PhotoSize) -> p.FileId) x.Photo
let HasText (x: Message) = not(isNull x.Text)
let UrlsAsAlbumInputMedia (urls: string[]): IAlbumInputMedia[] =
Array.map (fun (x: string) -> InputMediaPhoto(x)) urls
// Post (Relay) command
type RelayCaptionMode =
| WithAuthor
| Anonymous
| Unknown
let RelaySupportedContent (x: Message) =
match x.Type with
| MessageType.Text -> true
| MessageType.Photo -> true
| MessageType.Video -> true
| _ -> false
let RelayCaptionType (command: string) =
match command with
| _ when command.StartsWith "\\post anon" -> Anonymous
| _ when command.StartsWith "\\post" -> WithAuthor
| _ -> Unknown
let RelayCaption (name: string, url: string) = $"Прислал {name}"
let RelayParseMode = ParseMode.Html;
let RelayResolveCaption (mode: RelayCaptionMode, username: string, linkUrl: string) =
match mode with
| WithAuthor -> RelayCaption(username, linkUrl)
| _ -> null
let public RelayMatch: HandlerRequirements = fun (u, c) ->
UpdateIsAMessage u &&
FromAdminChat <| (u.Message, c) &&
HasReply u.Message &&
HasText u.Message &&
RelaySupportedContent u.Message.ReplyToMessage &&
not (RelayCaptionType u.Message.Text = RelayCaptionMode.Unknown)
let public RelayHandler: Handler = fun (update, config, tg) ->
let reply = update.Message.ReplyToMessage
let channelId = config.chanelId
let author = $"{reply.From.FirstName} {reply.From.LastName}"
let captionMode = RelayCaptionType update.Message.Text
let photoMedia = lazy Array.get (ExtractPhotoFromMessage reply) 0
let caption = lazy RelayResolveCaption(captionMode, author, config.relayUrl)
match reply.Type with
| MessageType.Text -> tg.ForwardMessageAsync(channelId, reply.Chat.Id, reply.MessageId)
| MessageType.Photo -> tg.SendPhotoAsync(channelId, photoMedia.Value, caption = caption.Value,
parseMode = RelayParseMode)
| MessageType.Video -> tg.SendVideoAsync(channelId, reply.Video.FileId, caption = caption.Value,
parseMode = RelayParseMode)
| _ -> Task.CompletedTask
// YoutubeDL repost
let YoutubeRepostMatchCmd = "\\ytdl"
let public YoutubeRepostMatch: HandlerRequirements = fun (u, c) ->
UpdateIsAMessage u &&
FromAdminChat <| (u.Message, c) &&
HasText <| u.Message &&
u.Message.Text.StartsWith YoutubeRepostMatchCmd &&
u.Message.Text.Split(' ').Length = 2
let public YoutubeRepostHandler: Handler = fun (yt, (u, c, tg)) ->
task {
let trim (x: string) = x.Trim()
let! id = YoutubeRepostMatchCmd |> u.Message.Text.Split |> Array.last |> trim |> yt.AddJob
do! tg.SendTextMessageAsync(c.adminChatId, id.ToString()) |> Async.AwaitTask |> Async.Ignore
}