Merge branch 'ref' into 'master'
fix video size See merge request alzheimer-gaming/publishhelperbot!4
This commit is contained in:
commit
ce1ff5f94b
@ -2,7 +2,7 @@ module PublishHelperBot.Environment
|
|||||||
|
|
||||||
open System
|
open System
|
||||||
open System.IO
|
open System.IO
|
||||||
open Newtonsoft.Json
|
open System.Text.Json
|
||||||
open Serilog
|
open Serilog
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
@ -20,7 +20,7 @@ type public BotConfig = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let private readConfig =
|
let private readConfig =
|
||||||
File.ReadAllText >> JsonConvert.DeserializeObject<BotConfig>
|
File.ReadAllText >> JsonSerializer.Deserialize<BotConfig>
|
||||||
|
|
||||||
let public createConfig (name: string) =
|
let public createConfig (name: string) =
|
||||||
match Environment.GetEnvironmentVariable(name) with
|
match Environment.GetEnvironmentVariable(name) with
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
<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" />
|
<PackageReference Include="Telegram.Bot" Version="18.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ module BotUpdateType =
|
|||||||
module TgService =
|
module TgService =
|
||||||
type private Msg =
|
type private Msg =
|
||||||
| Ping
|
| Ping
|
||||||
| PostVideo of url: string * savePath: string * externalId: Guid
|
| PostVideo of PostVideoArgs
|
||||||
| PostRelay of RelayArgs
|
| PostRelay of RelayArgs
|
||||||
| PostMessageToAdminChat of text: string
|
| PostMessageToAdminChat of text: string
|
||||||
|
|
||||||
@ -198,32 +198,55 @@ module TgService =
|
|||||||
|
|
||||||
return! loop ()
|
return! loop ()
|
||||||
|
|
||||||
| PostVideo (url, savePath, externalId) ->
|
| PostVideo args ->
|
||||||
try
|
try
|
||||||
Logging.logger.Information("Reading file path = {path}", savePath)
|
Logging.logger.Information("PostVideo args = {args}", args)
|
||||||
use file = File.OpenRead(savePath)
|
Logging.logger.Information("Reading file path = {path}", args.SavePath)
|
||||||
|
use file = File.OpenRead(args.SavePath)
|
||||||
if (file.Length / 1024L / 1024L) < 50L then
|
if (file.Length / 1024L / 1024L) < 50L then
|
||||||
let input = InputOnlineFile(file, Path.GetRandomFileName())
|
let input = InputOnlineFile(file, Path.GetRandomFileName())
|
||||||
let caption = $"Source: {url}"
|
let caption = $"Source: {args.Url}"
|
||||||
Logging.logger.Information(
|
Logging.logger.Information(
|
||||||
"Sending video to channel, channelId = {channelId}, caption = {caption}",
|
"Sending video to channel, channelId = {channelId}, caption = {caption}",
|
||||||
config.ChannelId,
|
config.ChannelId,
|
||||||
caption)
|
caption)
|
||||||
do! config.Client.SendVideoAsync(
|
|
||||||
config.ChannelId,
|
let dimensions =
|
||||||
input,
|
args.Width
|
||||||
caption = caption
|
|> 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.AwaitTask
|
||||||
|> Async.Catch
|
|> Async.Catch
|
||||||
|> Async.Ignore
|
|> Async.Ignore
|
||||||
else
|
else
|
||||||
inbox.Post(PostMessageToAdminChat($"Да блять, видео вышло больше 50мб: {externalId}"))
|
inbox.Post(PostMessageToAdminChat($"Да блять, видео вышло больше 50мб: {args.ExternalId}"))
|
||||||
finally
|
finally
|
||||||
Logging.logger.Information("Deleting file path = {path}", savePath)
|
Logging.logger.Information("Deleting file path = {path}", args.SavePath)
|
||||||
File.Delete(savePath)
|
File.Delete(args.SavePath)
|
||||||
|
|
||||||
match! config.YoutubeDlClient.CleanJob(externalId) with
|
match! config.YoutubeDlClient.CleanJob(args.ExternalId) with
|
||||||
| Ok _ -> ()
|
| Ok _ -> ()
|
||||||
| Error _ -> ()
|
| Error _ -> ()
|
||||||
return! loop ()
|
return! loop ()
|
||||||
@ -243,8 +266,8 @@ module TgService =
|
|||||||
member this.PostMessageToAdminChat(text) =
|
member this.PostMessageToAdminChat(text) =
|
||||||
inbox.Post(PostMessageToAdminChat(text))
|
inbox.Post(PostMessageToAdminChat(text))
|
||||||
|
|
||||||
member this.PostVideo(url, savePath, externalId) =
|
member this.PostVideo(args) =
|
||||||
inbox.Post(PostVideo(url, savePath, externalId)) }
|
inbox.Post(PostVideo(args)) }
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module TgUpdateHandler =
|
module TgUpdateHandler =
|
||||||
|
@ -1,26 +1,48 @@
|
|||||||
module PublishHelperBot.Types
|
module PublishHelperBot.Types
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
open System.Text.Json.Serialization
|
||||||
open Telegram.Bot
|
open Telegram.Bot
|
||||||
open Telegram.Bot.Types
|
open Telegram.Bot.Types
|
||||||
|
|
||||||
type ConfigChatId = int64
|
type ConfigChatId = int64
|
||||||
|
|
||||||
type CreateYoutubeDlJob = {
|
type CreateYoutubeDlJob = {
|
||||||
url: string
|
[<JsonPropertyName("url")>]
|
||||||
savePath: string
|
Url: string
|
||||||
|
[<JsonPropertyName("savePath")>]
|
||||||
|
SavePath: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateYoutubeDlJobSuccess = {
|
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 = {
|
type YoutubeDlStateResponse = {
|
||||||
state: string
|
[<JsonPropertyName("state")>]
|
||||||
|
State: string
|
||||||
|
[<JsonPropertyName("_youtube-dl_")>]
|
||||||
|
VideoInfo: YoutubeDlStateInfo option
|
||||||
}
|
}
|
||||||
|
|
||||||
type YoutubeDlError = {
|
type YoutubeDlError = {
|
||||||
message: string
|
[<JsonPropertyName("message")>]
|
||||||
|
Message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateJobResult = Result<CreateYoutubeDlJobSuccess, YoutubeDlError>
|
type CreateJobResult = Result<CreateYoutubeDlJobSuccess, YoutubeDlError>
|
||||||
@ -70,8 +92,17 @@ type BotUpdateType =
|
|||||||
type ITgUpdateHandler =
|
type ITgUpdateHandler =
|
||||||
abstract member PostUpdate: Update -> unit
|
abstract member PostUpdate: Update -> unit
|
||||||
|
|
||||||
|
type PostVideoArgs = {
|
||||||
|
Url: string
|
||||||
|
SavePath: string
|
||||||
|
ExternalId: Guid
|
||||||
|
Title: string option
|
||||||
|
Width: int option
|
||||||
|
Height: int option
|
||||||
|
}
|
||||||
|
|
||||||
type ITgService =
|
type ITgService =
|
||||||
abstract member PostRelay: args: RelayArgs -> unit
|
abstract member PostRelay: args: RelayArgs -> unit
|
||||||
abstract member PostMessageToAdminChat: text: string -> unit
|
abstract member PostMessageToAdminChat: text: string -> unit
|
||||||
abstract member Ping: unit -> unit
|
abstract member Ping: unit -> unit
|
||||||
abstract member PostVideo: url: string * savePath: string * externalId: Guid -> unit
|
abstract member PostVideo: PostVideoArgs -> unit
|
@ -5,9 +5,9 @@ open System.Collections.Generic
|
|||||||
open System.IO
|
open System.IO
|
||||||
open System.Net.Http
|
open System.Net.Http
|
||||||
open System.Text
|
open System.Text
|
||||||
|
open System.Text.Json
|
||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open Microsoft.FSharp.Core
|
open Microsoft.FSharp.Core
|
||||||
open Newtonsoft.Json
|
|
||||||
open PublishHelperBot.Environment
|
open PublishHelperBot.Environment
|
||||||
open PublishHelperBot.Types
|
open PublishHelperBot.Types
|
||||||
|
|
||||||
@ -57,13 +57,13 @@ module YoutubeDlClient =
|
|||||||
match res.IsSuccessStatusCode with
|
match res.IsSuccessStatusCode with
|
||||||
| true ->
|
| true ->
|
||||||
Logging.logger.Information("Response OK")
|
Logging.logger.Information("Response OK")
|
||||||
Ok (JsonConvert.DeserializeObject<'TRes>(content))
|
Ok (JsonSerializer.Deserialize<'TRes>(content))
|
||||||
| false ->
|
| false ->
|
||||||
Logging.logger.Error("Response network error")
|
Logging.logger.Error("Response network error")
|
||||||
Error { message = "Unknown network error" }
|
Error { Message = "Unknown network error" }
|
||||||
with ex ->
|
with ex ->
|
||||||
Logging.logger.Error(ex, "Youtube api error")
|
Logging.logger.Error(ex, "Youtube api error")
|
||||||
return Error { message = ex.Message }
|
return Error { Message = ex.Message }
|
||||||
} |> Async.AwaitTask
|
} |> Async.AwaitTask
|
||||||
|
|
||||||
let private createInbox(config: YoutubeDlClientConfig) = MailboxProcessor.Start(fun inbox ->
|
let private createInbox(config: YoutubeDlClientConfig) = MailboxProcessor.Start(fun inbox ->
|
||||||
@ -74,7 +74,7 @@ module YoutubeDlClient =
|
|||||||
Logging.logger.Information("Received youtube api create job")
|
Logging.logger.Information("Received youtube api create job")
|
||||||
async {
|
async {
|
||||||
try
|
try
|
||||||
let json = args |> JsonConvert.SerializeObject
|
let json = args |> JsonSerializer.Serialize
|
||||||
Logging.logger.Information("Sending create job = {Job}", json)
|
Logging.logger.Information("Sending create job = {Job}", json)
|
||||||
use content = new StringContent(json, Encoding.UTF8, "application/json")
|
use content = new StringContent(json, Encoding.UTF8, "application/json")
|
||||||
let! result =
|
let! result =
|
||||||
@ -86,7 +86,7 @@ module YoutubeDlClient =
|
|||||||
with ex ->
|
with ex ->
|
||||||
Logging.logger.Error(ex, "Failed to create youtube api job")
|
Logging.logger.Error(ex, "Failed to create youtube api job")
|
||||||
tcs.SetResult(Error {
|
tcs.SetResult(Error {
|
||||||
message = ex.Message
|
Message = ex.Message
|
||||||
})
|
})
|
||||||
|
|
||||||
} |> Async.Start
|
} |> Async.Start
|
||||||
@ -110,7 +110,7 @@ module YoutubeDlClient =
|
|||||||
with ex ->
|
with ex ->
|
||||||
Logging.logger.Error(ex, "Failed to check youtube api job")
|
Logging.logger.Error(ex, "Failed to check youtube api job")
|
||||||
tcs.SetResult(Error {
|
tcs.SetResult(Error {
|
||||||
message = ex.Message
|
Message = ex.Message
|
||||||
})
|
})
|
||||||
} |> Async.Start
|
} |> Async.Start
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ module YoutubeDlClient =
|
|||||||
with ex ->
|
with ex ->
|
||||||
Logging.logger.Error(ex, "Failed to clean youtube api job")
|
Logging.logger.Error(ex, "Failed to clean youtube api job")
|
||||||
tcs.SetResult(Error {
|
tcs.SetResult(Error {
|
||||||
message = ex.Message
|
Message = ex.Message
|
||||||
})
|
})
|
||||||
} |> Async.Start
|
} |> Async.Start
|
||||||
|
|
||||||
@ -182,18 +182,18 @@ module YoutubeDlService =
|
|||||||
Logging.logger.Information("Sending create job to youtube client, job = {job}", job.InternalId)
|
Logging.logger.Information("Sending create job to youtube client, job = {job}", job.InternalId)
|
||||||
let! result =
|
let! result =
|
||||||
client.CreateJob {
|
client.CreateJob {
|
||||||
url = job.Url
|
Url = job.Url
|
||||||
savePath = job.SavePath
|
SavePath = job.SavePath
|
||||||
}
|
}
|
||||||
match result with
|
match result with
|
||||||
| Ok task ->
|
| Ok task ->
|
||||||
Logging.logger.Information(
|
Logging.logger.Information(
|
||||||
"Created job on youtube client = {job}, externalId = {externalId}",
|
"Created job on youtube client = {job}, externalId = {externalId}",
|
||||||
job.InternalId,
|
job.InternalId,
|
||||||
task.task)
|
task.Task)
|
||||||
let updated = {
|
let updated = {
|
||||||
job with
|
job with
|
||||||
State = JobState.Awaiting task.task
|
State = JobState.Awaiting task.Task
|
||||||
}
|
}
|
||||||
return Some updated
|
return Some updated
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ module YoutubeDlService =
|
|||||||
Logging.logger.Error(
|
Logging.logger.Error(
|
||||||
"Failed to create job on client = {job}, message = {message}",
|
"Failed to create job on client = {job}, message = {message}",
|
||||||
job.InternalId,
|
job.InternalId,
|
||||||
e.message)
|
e.Message)
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,11 +275,21 @@ module YoutubeDlService =
|
|||||||
|
|
||||||
| Awaiting externalId ->
|
| Awaiting externalId ->
|
||||||
Logging.logger.Information("Checking job = {job}", externalId)
|
Logging.logger.Information("Checking job = {job}", externalId)
|
||||||
let! task = youtubeDlClient.CheckJob(externalId)
|
let! checkResult = youtubeDlClient.CheckJob(externalId)
|
||||||
match task with
|
match checkResult with
|
||||||
| Ok x when x.state.Equals("Finished", StringComparison.OrdinalIgnoreCase) ->
|
| Ok x when x.State.Equals("Finished", StringComparison.OrdinalIgnoreCase) ->
|
||||||
Logging.logger.Information("Sending post video from job = {job}", externalId)
|
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()
|
postCheck()
|
||||||
return! loop jobQueue None
|
return! loop jobQueue None
|
||||||
|
|
||||||
@ -287,7 +297,7 @@ module YoutubeDlService =
|
|||||||
Logging.logger.Error(
|
Logging.logger.Error(
|
||||||
"Failed to receive video from youtube client, job = {job}, message = {message}",
|
"Failed to receive video from youtube client, job = {job}, message = {message}",
|
||||||
externalId,
|
externalId,
|
||||||
e.message)
|
e.Message)
|
||||||
Logging.logger.Information("Deleting file path = {path}", job.SavePath)
|
Logging.logger.Information("Deleting file path = {path}", job.SavePath)
|
||||||
File.Delete(job.SavePath)
|
File.Delete(job.SavePath)
|
||||||
return! loop jobQueue None
|
return! loop jobQueue None
|
||||||
|
@ -22,7 +22,7 @@ def report_state(id: str):
|
|||||||
def load_video(url: str, file_path: str, id: str):
|
def load_video(url: str, file_path: str, id: str):
|
||||||
try:
|
try:
|
||||||
opts = {
|
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,
|
"quiet": True,
|
||||||
"outtmpl": file_path,
|
"outtmpl": file_path,
|
||||||
"progress_hooks": [report_state(id)]
|
"progress_hooks": [report_state(id)]
|
||||||
|
Loading…
Reference in New Issue
Block a user