diff --git a/SerfBot/Commands.fs b/SerfBot/Commands.fs index 4386cea..938ad62 100644 --- a/SerfBot/Commands.fs +++ b/SerfBot/Commands.fs @@ -8,8 +8,8 @@ let commandHandler command = try match command with | Ping -> "pong" - | Vision (imageLink, userText) -> - descriptionAnalyzedImage imageLink + | Vision (userText, base64Img) -> + descriptionAnalyzedImage userText base64Img |> Async.RunSynchronously | Context userText -> setupContext userText @@ -19,8 +19,9 @@ let commandHandler command = gptAnswer userText |> Async.RunSynchronously | Weather city -> - let weather = WeatherApi.getWeatherAsync city |> Async.RunSynchronously + let weather = WeatherApi.getWeatherAsync city + |> Async.RunSynchronously $"Погода в %s{city}: %s{weather}" - | _ -> "Некорректная команда для GPT" + | _ -> "Некорректная команда" with | ex -> sprintf "Ошибка: %s" ex.Message \ No newline at end of file diff --git a/SerfBot/OpenAiApi.fs b/SerfBot/OpenAiApi.fs index c92385b..72792ed 100644 --- a/SerfBot/OpenAiApi.fs +++ b/SerfBot/OpenAiApi.fs @@ -69,18 +69,18 @@ let gptAnswer userQuestion = return ex.Message } -let descriptionAnalyzedImage imageLink = +let descriptionAnalyzedImage userText base64Img = async { try let api = OpenAIClient(Configuration.config.OpenAiApiToken) - + let userText2 = if userText == null then "Что на фото?" else userText let messages = [ Message(Role.System, Option.get currentContext) Message(Role.User, [ - Content(ContentType.Text, "Что на этой картинке?") - Content(ContentType.ImageUrl, imageLink) + Content(ContentType.Text, userText2) + Content(ContentType.ImageUrl, $"data:image/jpeg;base64,{base64Img}") ]) ] diff --git a/SerfBot/TelegramBot.fs b/SerfBot/TelegramBot.fs index 283570d..b5b0a4e 100644 --- a/SerfBot/TelegramBot.fs +++ b/SerfBot/TelegramBot.fs @@ -1,8 +1,11 @@ module SerfBot.TelegramBot open System +open System.IO +open System.Net.Http open ExtCore.Control.Collections open Funogram.Api +open Funogram.Telegram open Funogram.Telegram.Bot open Funogram.Telegram.Types open SerfBot.Log @@ -25,39 +28,49 @@ let processCommand (ctx: UpdateContext, command: MessageReplayCommand) = |> Async.RunSynchronously |> ignore -// obsolet -//let updateArrived (ctx: UpdateContext) = -// match ctx.Update.Message with -// | Some { MessageId = messageId; Chat = chat; Text = text; Photo = photo; Voice = voice } -> -// let user = ctx.Update.Message.Value.From.Value -// match isValidUser user.Id with -// | Some () -> -// logInfo $"Message from user {Option.get user.Username} received: {Option.get text}" -// let command, userMessage = extractCommand text.Value -// match Commands.commandHandlers.TryGetValue command with -// | true, handler -> -// let replyText = handler userMessage -// processCommand(ctx, { Chat = chat; MessageId = messageId; Text = text; ReplayText = replyText; }) -// | _ -> () -// | None -> -// sprintf "Authorize error." |> logInfo -// | _ -> () +let streamToBase64 (stream: Stream) = + use ms = new MemoryStream() + stream.CopyTo(ms) + let buffer = ms.ToArray() + Convert.ToBase64String(buffer) +let extractFileDataAsBase64 (fileResult: Result) = + match fileResult with + | Ok(file) -> + let filePath = Option.get file.FilePath // предполагается, что у вас есть свойство "Path" в типе "File" + let apiUrl = $"https://api.telegram.org/file/bot{Configuration.config.TelegramBotToken}/{filePath}" + use httpStream = new HttpClient() + let f = httpStream.GetStreamAsync(apiUrl) |> Async.AwaitTask |> Async.RunSynchronously + let base64 = streamToBase64 f + base64 + + +let handleFiles fileId ctx = + let file = Req.GetFile.Make fileId + |> api ctx.Config + |> Async.RunSynchronously + let base64Img = extractFileDataAsBase64 file + base64Img + + let updateArrivedMessage (ctx: UpdateContext) = match ctx.Update.Message with - | Some { MessageId = messageId; Chat = chat; Text = text; Photo = photo } -> + | Some { MessageId = messageId; Chat = chat; Text = text; Photo = photo; Caption = caption } -> let user = ctx.Update.Message.Value.From.Value + + let base64Img = if photo.IsSome then handleFiles photo.Value[0].FileId ctx else "" + let message = if text.IsSome then text.Value elif caption.IsSome then caption.Value else "" match isValidUser user.Id with | Some () -> - logInfo $"Message from user {Option.get user.Username} received: {Option.get text}" - let command, userMessage = extractCommand text.Value + logInfo $"Message from user {Option.get user.Username} received: " //{Option.get text} + let command, userMessage = extractCommand message let commandType = match command with | "!ping" -> Ping | "погода" -> Weather userMessage | "!context" -> Context userMessage - | "!vision" -> Vision (userMessage, "test") + | "!vision" -> Vision (userMessage, base64Img) | "гпт" -> Question userMessage | _ -> Other userMessage diff --git a/SerfBot/Types.fs b/SerfBot/Types.fs index 3a5b704..9d56f26 100644 --- a/SerfBot/Types.fs +++ b/SerfBot/Types.fs @@ -31,13 +31,6 @@ type ApplicationConfiguration = { UserIds: int64[] } -type CommandHandler = string -> string - -type Commands = { - Name: string - Handler: CommandHandler -} - type Command = | Ping | Question of string