diff --git a/src/Funogram.Generator/Types/TypesGenerator.fs b/src/Funogram.Generator/Types/TypesGenerator.fs index fc51ca1..e496c54 100644 --- a/src/Funogram.Generator/Types/TypesGenerator.fs +++ b/src/Funogram.Generator/Types/TypesGenerator.fs @@ -44,6 +44,8 @@ type ParseMode = | Markdown /// Html parse syntax | HTML + /// MarkdownV2 parse syntax + | [] MarkdownV2 /// Type of action to broadcast type ChatAction = diff --git a/src/Funogram.Telegram/Directory.Build.props b/src/Funogram.Telegram/Directory.Build.props index 0125c90..13e3b8a 100644 --- a/src/Funogram.Telegram/Directory.Build.props +++ b/src/Funogram.Telegram/Directory.Build.props @@ -1,6 +1,6 @@ - 7.2.0 + 7.2.0.1 Nikolay Matyushin Funogram.Telegram Funogram.Telegram diff --git a/src/Funogram.Telegram/Types.fs b/src/Funogram.Telegram/Types.fs index 3513cce..7936922 100644 --- a/src/Funogram.Telegram/Types.fs +++ b/src/Funogram.Telegram/Types.fs @@ -28,6 +28,8 @@ type ParseMode = | Markdown /// Html parse syntax | HTML + /// MarkdownV2 parse syntax + | [] MarkdownV2 /// Type of action to broadcast type ChatAction = diff --git a/src/Funogram.Tests/Constants.fs b/src/Funogram.Tests/Constants.fs index a2c8cc2..5af26af 100644 --- a/src/Funogram.Tests/Constants.fs +++ b/src/Funogram.Tests/Constants.fs @@ -71,6 +71,9 @@ module Constants = }: Req.ForwardMessage) :> IBotRequest let jsonForwardMessageReq = """{"chat_id":"Dolfik","from_chat_id":10,"message_id":10}""" + let sendMessageReq = Req.SendMessage.Make(ChatId.String "Dolfik", "Hello, world", parseMode = ParseMode.MarkdownV2) :> IBotRequest + let jsonSendMessageReq = """{"chat_id":"Dolfik","text":"Hello, world","parse_mode":"MarkdownV2"}""" + let jsonTestObjChatMember = ChatMemberMember.Create("member", User.Create(600000000L, false, "firstName", "lastName", "userName", "ru")) let jsonTestObjChatMemberResultString = """{"ok":true,"result":{"status":"member","user":{"id":600000000,"is_bot":false,"first_name":"firstName","last_name":"lastName","username":"userName","language_code":"ru"}}}""" \ No newline at end of file diff --git a/src/Funogram.Tests/Json.fs b/src/Funogram.Tests/Json.fs index 98ae223..c95d8e6 100644 --- a/src/Funogram.Tests/Json.fs +++ b/src/Funogram.Tests/Json.fs @@ -115,4 +115,10 @@ let ``JSON deserializing ChatMember``() = |> parseJson |> function | Ok result -> shouldEqual result Constants.jsonTestObjChatMember - | Error error -> failwith error.Description \ No newline at end of file + | Error error -> failwith error.Description + +[] +let ``JSON serializing send message request`` () = + Constants.sendMessageReq + |> toJsonBotRequestString + |> shouldEqual Constants.jsonSendMessageReq \ No newline at end of file diff --git a/src/Funogram/Converters.fs b/src/Funogram/Converters.fs index 0ce3ee3..08ed558 100644 --- a/src/Funogram/Converters.fs +++ b/src/Funogram/Converters.fs @@ -4,7 +4,6 @@ open System open System.Collections.Generic open System.IO open System.Runtime.CompilerServices -open System.Runtime.Serialization open System.Text.Json open System.Text.Json.Serialization open TypeShape.Core @@ -25,8 +24,8 @@ module internal Converters = && (case.Fields[1].Member.Type = typeof || case.Fields[1].Member.Type = typeof) if case.Fields.Length = 0 then + let name = caseName case.CaseInfo fun (writer: Utf8JsonWriter) _ _ -> - let name = toSnakeCase case.CaseInfo.Name writer.WriteStringValue(name) else case.Fields[0].Accept { new IMemberVisitor<'DeclaringType, Utf8JsonWriter -> 'DeclaringType -> JsonSerializerOptions -> unit> with @@ -89,17 +88,7 @@ module internal Converters = union.UnionCases |> Seq.map (fun c -> if c.Fields.Length = 0 then - let dataMember = - c.CaseInfo.GetCustomAttributes(typeof) - |> Seq.cast - |> Seq.filter (fun x -> String.IsNullOrEmpty(x.Name) |> not) - |> Seq.toArray - - let name = - if dataMember.Length > 0 - then dataMember[0].Name - else c.CaseInfo.Name |> toSnakeCase - (Set.ofList [name], None) + (Set.ofList [caseName c.CaseInfo], None) else let tp = c.Fields[0].Member.Type if tp.IsPrimitive then (Set.empty, Some tp) diff --git a/src/Funogram/Funogram.fsproj b/src/Funogram/Funogram.fsproj index 2af75de..b37babf 100644 --- a/src/Funogram/Funogram.fsproj +++ b/src/Funogram/Funogram.fsproj @@ -3,7 +3,7 @@ netstandard2.0 - 3.0.0 + 3.0.1 Nikolay Matyushin Funogram Funogram is a functional Telegram Bot Api library for F# diff --git a/src/Funogram/StringUtils.fs b/src/Funogram/StringUtils.fs index e1668e3..122865e 100644 --- a/src/Funogram/StringUtils.fs +++ b/src/Funogram/StringUtils.fs @@ -3,6 +3,8 @@ module Funogram.StringUtils open System open System.Linq.Expressions open System.Reflection +open System.Runtime.Serialization +open Microsoft.FSharp.Reflection let toSnakeCase = let assembly = Assembly.Load("System.Text.Json") @@ -21,4 +23,15 @@ let toSnakeCase = // not good solution, but fastest let fn = createConvertNameFunc instance - fn.Invoke \ No newline at end of file + fn.Invoke + +let inline caseName (caseInfo: UnionCaseInfo) = + let dataMember = + caseInfo.GetCustomAttributes(typeof) + |> Seq.cast + |> Seq.filter (fun x -> String.IsNullOrEmpty(x.Name) |> not) + |> Seq.toArray + + if dataMember.Length > 0 + then dataMember[0].Name + else caseInfo.Name |> toSnakeCase \ No newline at end of file diff --git a/src/Funogram/Tools.fs b/src/Funogram/Tools.fs index 598be01..00b831e 100644 --- a/src/Funogram/Tools.fs +++ b/src/Funogram/Tools.fs @@ -379,7 +379,7 @@ module Api = else None if isEnum then - let name = StringUtils.toSnakeCase case.CaseInfo.Name + let name = StringUtils.caseName case.CaseInfo fun _ (prop: string) (data: MultipartFormDataContent) -> data.Add(strf "%s" name, prop) $ true else @@ -422,7 +422,7 @@ module Api = use content = new MultipartFormDataContent() let hasData = serialize request content - + let! result = if hasData then client.PostAsync(url, content) |> Async.AwaitTask else client.GetAsync(url) |> Async.AwaitTask diff --git a/src/examples/Funogram.TestBot/Commands/Base.fs b/src/examples/Funogram.TestBot/Commands/Base.fs index cf41c45..1ac9343 100644 --- a/src/examples/Funogram.TestBot/Commands/Base.fs +++ b/src/examples/Funogram.TestBot/Commands/Base.fs @@ -15,6 +15,7 @@ let defaultText = """⭐️Available test commands: /send_message7 - Test inline keyboard /send_message8 - Test multiple media /send_message9 - Test multiple media as bytes + /send_message10 - MarkdownV2 test /send_action - Test action @@ -46,6 +47,7 @@ let updateArrived (ctx: UpdateContext) = cmd "/send_message8" (fun _ -> Files.testUploadAndSendPhotoGroup |> wrap) cmd "/send_message9" (fun _ -> Files.testUploadAndSendPhotoGroupAsBytes |> wrap) + cmd "/send_message10" (fun _ -> TextMessages.testMarkdownV2 |> wrap) cmd "/forward_message" (fun _ -> TextMessages.testForwardMessage ctx |> wrap) diff --git a/src/examples/Funogram.TestBot/Commands/TextMessages.fs b/src/examples/Funogram.TestBot/Commands/TextMessages.fs index eb4a1dd..31265a1 100644 --- a/src/examples/Funogram.TestBot/Commands/TextMessages.fs +++ b/src/examples/Funogram.TestBot/Commands/TextMessages.fs @@ -8,8 +8,62 @@ open Funogram.Telegram.Types let private sendMessageFormatted text parseMode config chatId = Req.SendMessage.Make(ChatId.Int chatId, text, parseMode = parseMode) |> bot config -let testMarkdown = sendMessageFormatted "Test *Markdown*" ParseMode.Markdown -let testHtml = sendMessageFormatted "Test HTML" ParseMode.HTML +[] +let MarkdownExample = """*bold text* +_italic text_ +[inline URL](http://www.example.com/) +[inline mention of a user](tg://user?id=123456789) +`inline fixed-width code` +``` +pre-formatted fixed-width code block +``` +```python +pre-formatted fixed-width code block written in the Python programming language +```""" + +[] +let MarkdownV2Example = """*bold \*text* +_italic \*text_ +__underline__ +~strikethrough~ +||spoiler|| +*bold _italic bold ~italic bold strikethrough ||italic bold strikethrough spoiler||~ __underline italic bold___ bold* +[inline URL](http://www.example.com/) +[inline mention of a user](tg://user?id=123456789) +![👍](tg://emoji?id=5368324170671202286) +`inline fixed-width code` +``` +pre-formatted fixed-width code block +``` +```python +pre-formatted fixed-width code block written in the Python programming language +``` +>Block quotation started +>Block quotation continued +>The last line of the block quotation** +>The second block quotation started right after the previous\r +>The third block quotation started right after the previous""" + +[] +let HtmlExample = """ +bold, bold +italic, italic +underline, underline +strikethrough, strikethrough, strikethrough +spoiler, spoiler +bold italic bold italic bold strikethrough italic bold strikethrough spoiler underline italic bold bold +inline URL +inline mention of a user +👍 +inline fixed-width code +
pre-formatted fixed-width code block
+
pre-formatted fixed-width code block written in the Python programming language
+
Block quotation started\nBlock quotation continued\nThe last line of the block quotation
+""" + +let testMarkdown = sendMessageFormatted MarkdownExample ParseMode.Markdown +let testMarkdownV2 = sendMessageFormatted MarkdownV2Example ParseMode.MarkdownV2 +let testHtml = sendMessageFormatted HtmlExample ParseMode.HTML let testNoWebpageAndNotification config chatId = Req.SendMessage.Make( ChatId.Int chatId,