Skip to content

Commit

Permalink
refactoring + fix workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
boogiedk committed Dec 11, 2023
1 parent dfff8a3 commit 5463196
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 51 deletions.
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

0 comments on commit 5463196

Please sign in to comment.