feat: extract scan library classes and add scheduler
This commit is contained in:
parent
57c0bb660c
commit
be89bddf1b
@ -8,6 +8,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.2" />
|
||||
<PackageReference Include="Quartz" Version="3.13.1" />
|
||||
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.13.1" />
|
||||
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.13.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,5 +1,7 @@
|
||||
using AutoScan.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Quartz;
|
||||
|
||||
namespace AutoScan;
|
||||
|
||||
@ -7,16 +9,44 @@ public class AutoScanApp
|
||||
{
|
||||
private readonly AutoScanOptions _options;
|
||||
private readonly ILogger<AutoScanApp> _logger;
|
||||
private readonly IScheduler _scheduler;
|
||||
|
||||
public AutoScanApp(AutoScanOptions options, ILogger<AutoScanApp> logger)
|
||||
public AutoScanApp(IOptions<AutoScanOptions> options, ILogger<AutoScanApp> logger, IScheduler scheduler)
|
||||
{
|
||||
_options = options;
|
||||
_options = options.Value;
|
||||
_logger = logger;
|
||||
_scheduler = scheduler;
|
||||
}
|
||||
|
||||
private void Run()
|
||||
public async Task Run(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("AutoScanApp is running...");
|
||||
_logger.LogInformation("Waiting for next scan at {At}.", _options.At);
|
||||
|
||||
var at = DateTime.Now.AddMinutes(1).ToString("HH:mm");
|
||||
var cron = CronFromAt(at);
|
||||
_logger.LogInformation("Waiting for next scan at {At} [{cron}].", at, cron);
|
||||
|
||||
await _scheduler.Start(cancellationToken);
|
||||
_logger.LogInformation("Scheduler started successfully!");
|
||||
|
||||
// define the job and tie it to our HelloJob class
|
||||
IJobDetail job = JobBuilder.Create<ScanJob>()
|
||||
.WithIdentity("job1", "group1")
|
||||
.Build();
|
||||
|
||||
ITrigger trigger = TriggerBuilder.Create()
|
||||
.WithIdentity("trigger1", "group1")
|
||||
.WithCronSchedule(cron)
|
||||
.Build();
|
||||
|
||||
await _scheduler.ScheduleJob(job, trigger, cancellationToken);
|
||||
_logger.LogInformation("Scheduled job successfully!");
|
||||
}
|
||||
|
||||
private string CronFromAt(string at)
|
||||
{
|
||||
var parts = at.Split(':');
|
||||
return $"0 {parts[1]} {parts[0]} * * ?";
|
||||
}
|
||||
|
||||
}
|
31
src/CasaBot/AutoScan/DependencyInjectionExtensions.cs
Normal file
31
src/CasaBot/AutoScan/DependencyInjectionExtensions.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using CasaBotApp;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Quartz;
|
||||
|
||||
namespace AutoScan;
|
||||
|
||||
public static class DependencyInjectionExtensions
|
||||
{
|
||||
public static void AddAutoScan(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<ShinobiConnector>();
|
||||
services.AddSingleton<DVRScanner>();
|
||||
services.AddSingleton<FfmpegWrapper>();
|
||||
services.AddSingleton<AutoScanApp>();
|
||||
services.AddQuartz(q =>
|
||||
{
|
||||
q.UseMicrosoftDependencyInjectionJobFactory();
|
||||
});
|
||||
|
||||
services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
|
||||
|
||||
services.AddSingleton<IScheduler>(sp =>
|
||||
{
|
||||
var schedulerFactory = sp.GetRequiredService<ISchedulerFactory>();
|
||||
var tsk = schedulerFactory.GetScheduler();
|
||||
tsk.Wait();
|
||||
return tsk.Result;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
namespace AutoScan.Options;
|
||||
|
||||
public class AutoScanOptions
|
||||
public record AutoScanOptions
|
||||
{
|
||||
public bool Enabled { get; set; }
|
||||
public string? At { get; set; }
|
||||
|
24
src/CasaBot/AutoScan/ScanJob.cs
Normal file
24
src/CasaBot/AutoScan/ScanJob.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using AutoScan.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Quartz;
|
||||
|
||||
namespace AutoScan;
|
||||
|
||||
public class ScanJob : IJob
|
||||
{
|
||||
private readonly ILogger<ScanJob> _logger;
|
||||
private readonly AutoScanOptions _options;
|
||||
|
||||
public ScanJob(ILogger<ScanJob> logger, IOptionsSnapshot<AutoScanOptions> options)
|
||||
{
|
||||
_logger = logger;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
_logger.LogWarning("Scheduled scan executed with ops: {Options}", _options);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
@ -6,10 +6,10 @@ public class ShinobiConnector
|
||||
{
|
||||
//TODO move class to auto scan library
|
||||
private readonly ILogger<ShinobiConnector> _logger;
|
||||
private readonly string _shinobivUrl = "https://shinobi.francelsoft.com";
|
||||
private readonly string _apikey = "OGD6nsGGzA1NL48M5Tg7Wbzto62oPl";
|
||||
private readonly string _groupId = "aInxuWCYLI";
|
||||
private readonly string _monitorId = "mQ3kQ5qjKK";
|
||||
private readonly string _shinobivUrl = "";
|
||||
private readonly string _apikey = "";
|
||||
private readonly string _groupId = "";
|
||||
private readonly string _monitorId = "";
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public ShinobiConnector(ILogger<ShinobiConnector> logger, HttpClient httpClient)
|
@ -1,6 +0,0 @@
|
||||
namespace CasaBotApp;
|
||||
|
||||
public class BotConfiguration
|
||||
{
|
||||
public required string Token { get; set; }
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Polling;
|
||||
using Telegram.Bot.Types;
|
||||
@ -10,28 +11,28 @@ namespace CasaBotApp;
|
||||
public class BotHandler
|
||||
{
|
||||
private readonly ILogger<BotHandler> _logger;
|
||||
private readonly BotConfiguration _botConfiguration;
|
||||
private readonly TelegramOptions _telegramOptions;
|
||||
private readonly List<ChatId> _subscribers = [];
|
||||
|
||||
private TelegramBotClient? _bot;
|
||||
|
||||
|
||||
public BotHandler(BotConfiguration botConfiguration, ILogger<BotHandler> logger)
|
||||
public BotHandler(IOptions<TelegramOptions> telegramConfiguration, ILogger<BotHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
if (string.IsNullOrEmpty(botConfiguration.Token))
|
||||
if (string.IsNullOrEmpty(telegramConfiguration.Value.BotToken))
|
||||
{
|
||||
_logger.LogError("Bot token is not provided");
|
||||
throw new ArgumentException("Bot token is required", nameof(botConfiguration));
|
||||
throw new ArgumentException("Bot token is required", nameof(telegramConfiguration));
|
||||
}
|
||||
_botConfiguration = botConfiguration;
|
||||
_telegramOptions = telegramConfiguration.Value;
|
||||
}
|
||||
|
||||
|
||||
public void Start(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Starting bot...");
|
||||
_bot = new TelegramBotClient(_botConfiguration.Token, cancellationToken: cancellationToken);
|
||||
_bot = new TelegramBotClient(_telegramOptions.BotToken, cancellationToken: cancellationToken);
|
||||
|
||||
|
||||
_bot.OnError += OnError;
|
||||
|
@ -13,73 +13,79 @@ IConfigurationRoot configuration = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
var services = new ServiceCollection();
|
||||
|
||||
serviceCollection.AddSingleton(configuration);
|
||||
serviceCollection.AddLogging(builder =>
|
||||
services.AddSingleton(configuration);
|
||||
services.AddLogging(builder =>
|
||||
{
|
||||
builder.AddConfiguration(configuration.GetSection("Logging"));
|
||||
builder.AddConsole();
|
||||
// builder.AddConsole();
|
||||
//add time to logs
|
||||
builder.AddSimpleConsole(options =>
|
||||
{
|
||||
options.IncludeScopes = true;
|
||||
options.SingleLine = true;
|
||||
options.TimestampFormat = "[HH:mm:ss] ";
|
||||
});
|
||||
});
|
||||
serviceCollection.AddSingleton(new BotConfiguration()
|
||||
{
|
||||
Token = configuration.GetValue<string>("TelegramToken") ?? ""
|
||||
});
|
||||
serviceCollection.Configure<AutoScan.Options.AutoScanOptions>(configuration.GetSection("AutoScan"));
|
||||
|
||||
serviceCollection.AddSingleton<BotHandler>();
|
||||
serviceCollection.AddSingleton<ShinobiConnector>();
|
||||
serviceCollection.AddSingleton<DVRScanner>();
|
||||
serviceCollection.AddSingleton<FfmpegWrapper>();
|
||||
serviceCollection.AddSingleton<AutoScanApp>();
|
||||
serviceCollection.AddHttpClient();
|
||||
services.Configure<TelegramOptions>(configuration.GetSection("Telegram"));
|
||||
services.Configure<AutoScan.Options.AutoScanOptions>(configuration.GetSection("AutoScan"));
|
||||
|
||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
services.AddSingleton<BotHandler>();
|
||||
|
||||
services.AddAutoScan();
|
||||
services.AddHttpClient();
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var logger = serviceProvider.GetService<ILogger<Program>>()!;
|
||||
|
||||
var botHandler = serviceProvider.GetService<BotHandler>()!;
|
||||
var autoScanApp = serviceProvider.GetService<AutoScanApp>()!;
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
|
||||
botHandler.Start(cts.Token);
|
||||
autoScanApp.Run(cts.Token);
|
||||
// botHandler.Start(cts.Token);
|
||||
|
||||
_ = SendMessageToSubscribers(cts.Token);
|
||||
|
||||
var videoFileName = configuration.GetValue<string>("VideoFileName") ?? "video.mp4";
|
||||
if (configuration.GetValue<bool>("Fetch"))
|
||||
{
|
||||
var shinobiConnector = serviceProvider.GetService<ShinobiConnector>()!;
|
||||
await shinobiConnector.FetchLastVideo(videoFileName);
|
||||
}
|
||||
|
||||
if (configuration.GetValue<bool>("Scan"))
|
||||
{
|
||||
var dvrScanner = serviceProvider.GetService<DVRScanner>()!;
|
||||
await dvrScanner.ScanVideos(cts.Token);
|
||||
}
|
||||
|
||||
if(configuration.GetValue<bool>("Screenshot"))
|
||||
{
|
||||
var detected = "2025-02-12T07-00-02.DSME_0001.avi";
|
||||
var ffmpegWrapper = serviceProvider.GetService<FfmpegWrapper>()!;
|
||||
var duration = await ffmpegWrapper.GetVideoDuration($@".\media\detected\{detected}");
|
||||
logger.LogInformation("Video duration: {Duration}", duration);
|
||||
var middleTime = (duration / 2).Add(TimeSpan.FromSeconds(0.5));
|
||||
|
||||
//Extract frame at middle time
|
||||
var screenshotPath = $@".\media\detected\{detected}-ss.png";
|
||||
await ffmpegWrapper.ExtractFrame($@".\media\detected\{detected}", screenshotPath, middleTime);
|
||||
logger.LogInformation("Screenshot extracted at {MiddleTime}", middleTime);
|
||||
|
||||
//botHandler.Subscribe(115151151);
|
||||
await botHandler.UpdatePhoto(screenshotPath);
|
||||
}
|
||||
// var videoFileName = configuration.GetValue<string>("VideoFileName") ?? "video.mp4";
|
||||
// if (configuration.GetValue<bool>("Fetch"))
|
||||
// {
|
||||
// var shinobiConnector = serviceProvider.GetService<ShinobiConnector>()!;
|
||||
// await shinobiConnector.FetchLastVideo(videoFileName);
|
||||
// }
|
||||
//
|
||||
// if (configuration.GetValue<bool>("Scan"))
|
||||
// {
|
||||
// var dvrScanner = serviceProvider.GetService<DVRScanner>()!;
|
||||
// await dvrScanner.ScanVideos(cts.Token);
|
||||
// }
|
||||
//
|
||||
// if(configuration.GetValue<bool>("Screenshot"))
|
||||
// {
|
||||
// var detected = "2025-02-12T07-00-02.DSME_0001.avi";
|
||||
// var ffmpegWrapper = serviceProvider.GetService<FfmpegWrapper>()!;
|
||||
// var duration = await ffmpegWrapper.GetVideoDuration($@".\media\detected\{detected}");
|
||||
// logger.LogInformation("Video duration: {Duration}", duration);
|
||||
// var middleTime = (duration / 2).Add(TimeSpan.FromSeconds(0.5));
|
||||
//
|
||||
// //Extract frame at middle time
|
||||
// var screenshotPath = $@".\media\detected\{detected}-ss.png";
|
||||
// await ffmpegWrapper.ExtractFrame($@".\media\detected\{detected}", screenshotPath, middleTime);
|
||||
// logger.LogInformation("Screenshot extracted at {MiddleTime}", middleTime);
|
||||
//
|
||||
// //botHandler.Subscribe(115151151);
|
||||
// await botHandler.UpdatePhoto(screenshotPath);
|
||||
// }
|
||||
|
||||
logger.LogInformation("Bot started");
|
||||
logger.LogInformation("Press any key to stop the bot...");
|
||||
Console.ReadLine();
|
||||
cts.Cancel(); // stop the bot
|
||||
|
||||
return;
|
||||
|
||||
|
||||
|
7
src/CasaBot/CasaBotApp/TelegramOptions.cs
Normal file
7
src/CasaBot/CasaBotApp/TelegramOptions.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace CasaBotApp;
|
||||
|
||||
public class TelegramOptions
|
||||
{
|
||||
public string? BotToken { get; set; }
|
||||
public long[] SubscribedChatIds { get; set; } = [];
|
||||
}
|
@ -3,9 +3,14 @@
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
"Microsoft": "Information",
|
||||
"Quartz": "Information"
|
||||
}
|
||||
},
|
||||
"Telegram":{
|
||||
"BotToken": "__token__",
|
||||
"SubscribedChatIds": []
|
||||
},
|
||||
"AutoScan": {
|
||||
"Enabled": false,
|
||||
"At": "07:00",
|
||||
|
Loading…
Reference in New Issue
Block a user