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

fix code flow #5

Merged
merged 36 commits into from
Dec 11, 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
7 changes: 6 additions & 1 deletion .github/workflows/docker-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ name: CI/CD Pipline
on:
pull_request:
branches:
- master
- master
types:
- closed
check_suite:
types:
- completed

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["SerfBot/SerfBot.fsproj", "SerfBot/"]
RUN dotnet restore "SerfBot/SerfBot.fsproj"
Expand Down
19 changes: 16 additions & 3 deletions SerfBot/Commands.fs
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
module SerfBot.Commands

open ExtCore.Control.Collections
open System
open SerfBot.OpenAiApi;
open SerfBot.Types
open SerfBot.Configuration

let commandDescriptions =
"!ping - команда проверки связи\n" +
"!context - команда изменения контекста\n" +
"!vision - команда анализа присланной картинки\n" +
"!help - команда вывода списка команд\n" +
"!uptime - команда показа количества дней работы бота\n" +
"погода - команда получения погоды\n" +
"гпт - команда для вопроса в ChatGpt\n";

let commandHandler command =
try
match command with
| Ping -> "pong"
| Vision (userText, base64Img) ->
descriptionAnalyzedImage userText base64Img
| Vision (userText, photo) ->
let base64img = TelegramApi.base64FromFileId (Array.last photo.Value).FileId
descriptionAnalyzedImage userText base64img
|> Async.RunSynchronously
| Context userText ->
setupContext userText
Expand All @@ -18,10 +29,12 @@ let commandHandler command =
| Question userText ->
gptAnswer userText
|> Async.RunSynchronously
| Uptime -> $"Bot active is {(DateTime.Now.Date - startTime.Date).Days} days"
| Weather city ->
let weather = WeatherApi.getWeatherAsync city
|> Async.RunSynchronously
$"Погода в %s{city}: %s{weather}"
| HelpCommands -> commandDescriptions
| _ -> "Некорректная команда"
with
| ex -> sprintf "Ошибка: %s" ex.Message
7 changes: 5 additions & 2 deletions SerfBot/Configuration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

open Funogram.Telegram
open Microsoft.Extensions.Configuration
open Types;
open Types
open System

module Configuration =
let mutable configBuilder =
Expand All @@ -12,5 +13,7 @@ module Configuration =
let config =
configBuilder
.Build()
.Get<ApplicationConfiguration>();
.Get<ApplicationConfiguration>()

let mutable startTime = DateTime.Now

4 changes: 2 additions & 2 deletions SerfBot/OpenAiApi.fs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
module SerfBot.OpenAiApi

open OpenAI
open OpenAI.Chat
open OpenAI.Managers
open OpenAI.ObjectModels
open OpenAI.ObjectModels.RequestModels
open SerfBot.Types
open OpenAI.Chat
open System
open Log

Expand Down Expand Up @@ -77,7 +77,7 @@ let descriptionAnalyzedImage userText base64Img =
async {
try
let api = OpenAIClient(Configuration.config.OpenAiApiToken)
let userText2 = if userText == null then "Что на фото?" else userText
let userText2 = if String.IsNullOrEmpty(userText) then "Что на фото?" else userText
let messages =
[
Message(Role.System, Option.get currentContext)
Expand Down
2 changes: 1 addition & 1 deletion SerfBot/Program.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace SerfBot

open System
open Funogram.Api
open Funogram.Telegram
open Funogram.Telegram.Bot
Expand All @@ -21,7 +22,6 @@ module Program =

let telegramBotConfig = {Config.defaultConfig with Token = Configuration.config.TelegramBotToken }
let! _ = Api.deleteWebhookBase () |> api telegramBotConfig

logInfo "SerfBot start"
return! startBot telegramBotConfig updateArrivedMessage None
} |> Async.RunSynchronously
Expand Down
4 changes: 2 additions & 2 deletions SerfBot/SerfBot.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand All @@ -11,8 +11,8 @@
</Content>
<Compile Include="Log.fs" />
<Compile Include="Types.fs" />
<Compile Include="TelegramApi.fs" />
<Compile Include="Configuration.fs" />
<Compile Include="TelegramApi.fs" />
<Compile Include="WeatherApi.fs" />
<Compile Include="OpenAiApi.fs" />
<Compile Include="Commands.fs" />
Expand Down
30 changes: 30 additions & 0 deletions SerfBot/TelegramApi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,40 @@

open Funogram.Telegram
open Funogram.Telegram.Types
open System
open System.IO
open System.Net.Http
open Funogram.Api
open Funogram.Telegram.Bot
open SerfBot.Types
open ExtCore.Control.Collections

let public sendMessageFormatted text parseMode config bot chatId =
Req.SendMessage.Make(ChatId.Int chatId, text, parseMode = parseMode) |> bot config

let public sendReplayMessageFormatted text parseMode config bot chatId replyToMessageId =
Req.SendMessage.Make(ChatId.Int chatId, text, replyToMessageId = replyToMessageId, parseMode = parseMode) |> bot config

let streamToBase64 (stream: Stream) =
use ms = new MemoryStream()
stream.CopyTo(ms)
let buffer = ms.ToArray()
Convert.ToBase64String(buffer)

let extractBase64File fileResult =
match fileResult with
| Ok file ->
let filePath = Option.get file.FilePath
let apiUrl = $"https://api.telegram.org/file/bot{Configuration.config.TelegramBotToken}/{filePath}"
use httpStream = new HttpClient()
httpStream.GetStreamAsync(apiUrl)
|> Async.AwaitTask
|> Async.RunSynchronously
|> streamToBase64
| _ -> failwith "Error when getting file"

let base64FromFileId fileId =
Req.GetFile.Make fileId
|> api {Config.defaultConfig with Token = Configuration.config.TelegramBotToken }
|> Async.RunSynchronously
|> extractBase64File
46 changes: 9 additions & 37 deletions SerfBot/TelegramBot.fs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
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
Expand All @@ -26,39 +22,12 @@ let isValidUser (userId: int64) =
let processCommand (ctx: UpdateContext, command: MessageReplayCommand) =
sendReplayMessageFormatted command.ReplayText ParseMode.Markdown ctx.Config api command.Chat.Id command.MessageId
|> Async.RunSynchronously
|> ignore

let streamToBase64 (stream: Stream) =
use ms = new MemoryStream()
stream.CopyTo(ms)
let buffer = ms.ToArray()
Convert.ToBase64String(buffer)

let extractFileDataAsBase64 (fileResult: Result<File,Funogram.Types.ApiResponseError>) =
match fileResult with
| Ok(file) ->
let filePath = Option.get file.FilePath
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

|> ignore

let updateArrivedMessage (ctx: UpdateContext) =
match ctx.Update.Message with
| 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 (Array.last photo.Value).FileId ctx else ""
| Some { MessageId = messageId; Chat = chat; Text = text; Photo = photo; Caption = caption; From = from } ->
let user = from.Value;
let message = if text.IsSome then text.Value elif caption.IsSome then caption.Value else ""
match isValidUser user.Id with
| Some () ->
Expand All @@ -67,14 +36,17 @@ let updateArrivedMessage (ctx: UpdateContext) =
let commandType =
match command with
| "!ping" -> Ping
| "погода" -> Weather userMessage
| "!context" -> Context userMessage
| "!vision" -> Vision (userMessage, base64Img)
| "!vision" -> Vision (userMessage, photo)
| "!help" -> HelpCommands
| "!uptime" -> Uptime
| "погода" -> Weather userMessage
| "гпт" -> Question userMessage
| _ -> Other userMessage

let replyText = Commands.commandHandler commandType
processCommand(ctx, { Chat = chat; MessageId = messageId; Text = text; ReplayText = replyText })
| None -> sprintf "Authorize error." |> logInfo
| _ -> ()
| None -> sprintf "Authorize error." |> logInfo
| None -> sprintf "Error." |> logInfo
| _ -> ()
9 changes: 8 additions & 1 deletion SerfBot/Types.fs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
module SerfBot.Types

open System
open Funogram.Telegram
open Funogram.Telegram.Types

let mutable internal startTime = DateTime

type CityCoordinates =
{ CityName: string
Expand Down Expand Up @@ -29,13 +33,16 @@ type ApplicationConfiguration = {
TelegramBotToken: string
OpenAiApiToken: string
UserIds: int64[]
StarBotDatetime: DateTime
}

type Command =
| Ping
| Question of string
| Context of string
| Vision of string * string
| Vision of string * PhotoSize array option
| Weather of string
| Uptime
| HelpCommands
| Other of string

Loading