Merge branch 'ref' into 'master'

fix video size

See merge request alzheimer-gaming/publishhelperbot!4
This commit is contained in:
Kirill Poletaev 2023-02-27 19:39:41 +00:00
commit ce1ff5f94b
6 changed files with 107 additions and 42 deletions

View File

@ -2,7 +2,7 @@ module PublishHelperBot.Environment
open System
open System.IO
open Newtonsoft.Json
open System.Text.Json
open Serilog
[<RequireQualifiedAccess>]
@ -20,7 +20,7 @@ type public BotConfig = {
}
let private readConfig =
File.ReadAllText >> JsonConvert.DeserializeObject<BotConfig>
File.ReadAllText >> JsonSerializer.Deserialize<BotConfig>
let public createConfig (name: string) =
match Environment.GetEnvironmentVariable(name) with

View File

@ -7,6 +7,7 @@
<ItemGroup>
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="System.Text.Json" Version="7.0.2" />
<PackageReference Include="Telegram.Bot" Version="18.0.0" />
</ItemGroup>

View File

@ -123,7 +123,7 @@ module BotUpdateType =
module TgService =
type private Msg =
| Ping
| PostVideo of url: string * savePath: string * externalId: Guid
| PostVideo of PostVideoArgs
| PostRelay of RelayArgs
| PostMessageToAdminChat of text: string
@ -198,32 +198,55 @@ module TgService =
return! loop ()
| PostVideo (url, savePath, externalId) ->
| PostVideo args ->
try
Logging.logger.Information("Reading file path = {path}", savePath)
use file = File.OpenRead(savePath)
Logging.logger.Information("PostVideo args = {args}", args)
Logging.logger.Information("Reading file path = {path}", args.SavePath)
use file = File.OpenRead(args.SavePath)
if (file.Length / 1024L / 1024L) < 50L then
let input = InputOnlineFile(file, Path.GetRandomFileName())
let caption = $"Source: {url}"
let caption = $"Source: {args.Url}"
Logging.logger.Information(
"Sending video to channel, channelId = {channelId}, caption = {caption}",
config.ChannelId,
caption)
do! config.Client.SendVideoAsync(
let dimensions =
args.Width
|> Option.bind (fun w ->
args.Height
|> Option.map (fun h -> (w, h))
)
let sendVideo =
match dimensions with
| Some (width, height) ->
config.Client.SendVideoAsync(
config.ChannelId,
input,
caption = caption,
width = width,
height = height
)
| None ->
config.Client.SendVideoAsync(
config.ChannelId,
input,
caption = caption
)
do! sendVideo
|> Async.AwaitTask
|> Async.Catch
|> Async.Ignore
else
inbox.Post(PostMessageToAdminChat($"Да блять, видео вышло больше 50мб: {externalId}"))
inbox.Post(PostMessageToAdminChat($"Да блять, видео вышло больше 50мб: {args.ExternalId}"))
finally
Logging.logger.Information("Deleting file path = {path}", savePath)
File.Delete(savePath)
Logging.logger.Information("Deleting file path = {path}", args.SavePath)
File.Delete(args.SavePath)
match! config.YoutubeDlClient.CleanJob(externalId) with
match! config.YoutubeDlClient.CleanJob(args.ExternalId) with
| Ok _ -> ()
| Error _ -> ()
return! loop ()
@ -243,8 +266,8 @@ module TgService =
member this.PostMessageToAdminChat(text) =
inbox.Post(PostMessageToAdminChat(text))
member this.PostVideo(url, savePath, externalId) =
inbox.Post(PostVideo(url, savePath, externalId)) }
member this.PostVideo(args) =
inbox.Post(PostVideo(args)) }
[<RequireQualifiedAccess>]
module TgUpdateHandler =

View File

@ -1,26 +1,48 @@
module PublishHelperBot.Types
open System
open System.Text.Json.Serialization
open Telegram.Bot
open Telegram.Bot.Types
type ConfigChatId = int64
type CreateYoutubeDlJob = {
url: string
savePath: string
[<JsonPropertyName("url")>]
Url: string
[<JsonPropertyName("savePath")>]
SavePath: string
}
type CreateYoutubeDlJobSuccess = {
task: Guid
[<JsonPropertyName("task")>]
Task: Guid
}
type YoutubeDlInfoDict = {
[<JsonPropertyName("title")>]
Title: string option
[<JsonPropertyName("height")>]
Height: int option
[<JsonPropertyName("width")>]
Width: int option
}
type YoutubeDlStateInfo = {
[<JsonPropertyName("info_dict")>]
InfoDict: YoutubeDlInfoDict option
}
type YoutubeDlStateResponse = {
state: string
[<JsonPropertyName("state")>]
State: string
[<JsonPropertyName("_youtube-dl_")>]
VideoInfo: YoutubeDlStateInfo option
}
type YoutubeDlError = {
message: string
[<JsonPropertyName("message")>]
Message: string
}
type CreateJobResult = Result<CreateYoutubeDlJobSuccess, YoutubeDlError>
@ -70,8 +92,17 @@ type BotUpdateType =
type ITgUpdateHandler =
abstract member PostUpdate: Update -> unit
type PostVideoArgs = {
Url: string
SavePath: string
ExternalId: Guid
Title: string option
Width: int option
Height: int option
}
type ITgService =
abstract member PostRelay: args: RelayArgs -> unit
abstract member PostMessageToAdminChat: text: string -> unit
abstract member Ping: unit -> unit
abstract member PostVideo: url: string * savePath: string * externalId: Guid -> unit
abstract member PostVideo: PostVideoArgs -> unit

View File

@ -5,9 +5,9 @@ open System.Collections.Generic
open System.IO
open System.Net.Http
open System.Text
open System.Text.Json
open System.Threading.Tasks
open Microsoft.FSharp.Core
open Newtonsoft.Json
open PublishHelperBot.Environment
open PublishHelperBot.Types
@ -57,13 +57,13 @@ module YoutubeDlClient =
match res.IsSuccessStatusCode with
| true ->
Logging.logger.Information("Response OK")
Ok (JsonConvert.DeserializeObject<'TRes>(content))
Ok (JsonSerializer.Deserialize<'TRes>(content))
| false ->
Logging.logger.Error("Response network error")
Error { message = "Unknown network error" }
Error { Message = "Unknown network error" }
with ex ->
Logging.logger.Error(ex, "Youtube api error")
return Error { message = ex.Message }
return Error { Message = ex.Message }
} |> Async.AwaitTask
let private createInbox(config: YoutubeDlClientConfig) = MailboxProcessor.Start(fun inbox ->
@ -74,7 +74,7 @@ module YoutubeDlClient =
Logging.logger.Information("Received youtube api create job")
async {
try
let json = args |> JsonConvert.SerializeObject
let json = args |> JsonSerializer.Serialize
Logging.logger.Information("Sending create job = {Job}", json)
use content = new StringContent(json, Encoding.UTF8, "application/json")
let! result =
@ -86,7 +86,7 @@ module YoutubeDlClient =
with ex ->
Logging.logger.Error(ex, "Failed to create youtube api job")
tcs.SetResult(Error {
message = ex.Message
Message = ex.Message
})
} |> Async.Start
@ -110,7 +110,7 @@ module YoutubeDlClient =
with ex ->
Logging.logger.Error(ex, "Failed to check youtube api job")
tcs.SetResult(Error {
message = ex.Message
Message = ex.Message
})
} |> Async.Start
@ -133,7 +133,7 @@ module YoutubeDlClient =
with ex ->
Logging.logger.Error(ex, "Failed to clean youtube api job")
tcs.SetResult(Error {
message = ex.Message
Message = ex.Message
})
} |> Async.Start
@ -182,18 +182,18 @@ module YoutubeDlService =
Logging.logger.Information("Sending create job to youtube client, job = {job}", job.InternalId)
let! result =
client.CreateJob {
url = job.Url
savePath = job.SavePath
Url = job.Url
SavePath = job.SavePath
}
match result with
| Ok task ->
Logging.logger.Information(
"Created job on youtube client = {job}, externalId = {externalId}",
job.InternalId,
task.task)
task.Task)
let updated = {
job with
State = JobState.Awaiting task.task
State = JobState.Awaiting task.Task
}
return Some updated
@ -201,7 +201,7 @@ module YoutubeDlService =
Logging.logger.Error(
"Failed to create job on client = {job}, message = {message}",
job.InternalId,
e.message)
e.Message)
return None
}
@ -275,11 +275,21 @@ module YoutubeDlService =
| Awaiting externalId ->
Logging.logger.Information("Checking job = {job}", externalId)
let! task = youtubeDlClient.CheckJob(externalId)
match task with
| Ok x when x.state.Equals("Finished", StringComparison.OrdinalIgnoreCase) ->
let! checkResult = youtubeDlClient.CheckJob(externalId)
match checkResult with
| Ok x when x.State.Equals("Finished", StringComparison.OrdinalIgnoreCase) ->
Logging.logger.Information("Sending post video from job = {job}", externalId)
tgService.PostVideo(job.Url, job.SavePath, externalId)
let infoDict =
x.VideoInfo |> Option.bind (fun v -> v.InfoDict)
let args = {
Url = job.Url
SavePath = job.SavePath
ExternalId = externalId
Title = infoDict |> Option.bind (fun i -> i.Title)
Width = infoDict |> Option.bind (fun i -> i.Width)
Height = infoDict |> Option.bind (fun i -> i.Height)
}
tgService.PostVideo(args)
postCheck()
return! loop jobQueue None
@ -287,7 +297,7 @@ module YoutubeDlService =
Logging.logger.Error(
"Failed to receive video from youtube client, job = {job}, message = {message}",
externalId,
e.message)
e.Message)
Logging.logger.Information("Deleting file path = {path}", job.SavePath)
File.Delete(job.SavePath)
return! loop jobQueue None

View File

@ -22,7 +22,7 @@ def report_state(id: str):
def load_video(url: str, file_path: str, id: str):
try:
opts = {
"format": 'best[height<=480][ext=mp4]/best[ext=mp4]',
"format": 'best[filesize<=50M][ext=mp4]/best[height<=480][ext=mp4]/best[ext=mp4]',
"quiet": True,
"outtmpl": file_path,
"progress_hooks": [report_state(id)]