diff --git a/src/CasaBot/AutoScan/AutoScan.csproj b/src/CasaBot/AutoScan/AutoScan.csproj index d9c04b1..aa345e3 100644 --- a/src/CasaBot/AutoScan/AutoScan.csproj +++ b/src/CasaBot/AutoScan/AutoScan.csproj @@ -8,6 +8,9 @@ + + + diff --git a/src/CasaBot/AutoScan/AutoScanApp.cs b/src/CasaBot/AutoScan/AutoScanApp.cs index 24e00da..a27edb4 100644 --- a/src/CasaBot/AutoScan/AutoScanApp.cs +++ b/src/CasaBot/AutoScan/AutoScanApp.cs @@ -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 _logger; + private readonly IScheduler _scheduler; - public AutoScanApp(AutoScanOptions options, ILogger logger) + public AutoScanApp(IOptions options, ILogger 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() + .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]} * * ?"; + } + } \ No newline at end of file diff --git a/src/CasaBot/CasaBotApp/DVRScanner.cs b/src/CasaBot/AutoScan/DVRScanner.cs similarity index 100% rename from src/CasaBot/CasaBotApp/DVRScanner.cs rename to src/CasaBot/AutoScan/DVRScanner.cs diff --git a/src/CasaBot/AutoScan/DependencyInjectionExtensions.cs b/src/CasaBot/AutoScan/DependencyInjectionExtensions.cs new file mode 100644 index 0000000..0e398d3 --- /dev/null +++ b/src/CasaBot/AutoScan/DependencyInjectionExtensions.cs @@ -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(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddQuartz(q => + { + q.UseMicrosoftDependencyInjectionJobFactory(); + }); + + services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true); + + services.AddSingleton(sp => + { + var schedulerFactory = sp.GetRequiredService(); + var tsk = schedulerFactory.GetScheduler(); + tsk.Wait(); + return tsk.Result; + }); + + } +} \ No newline at end of file diff --git a/src/CasaBot/CasaBotApp/FFMPEGWrapper.cs b/src/CasaBot/AutoScan/FFMPEGWrapper.cs similarity index 100% rename from src/CasaBot/CasaBotApp/FFMPEGWrapper.cs rename to src/CasaBot/AutoScan/FFMPEGWrapper.cs diff --git a/src/CasaBot/AutoScan/Options/AutoScanOptions.cs b/src/CasaBot/AutoScan/Options/AutoScanOptions.cs index f48efa2..8888461 100644 --- a/src/CasaBot/AutoScan/Options/AutoScanOptions.cs +++ b/src/CasaBot/AutoScan/Options/AutoScanOptions.cs @@ -1,6 +1,6 @@ namespace AutoScan.Options; -public class AutoScanOptions +public record AutoScanOptions { public bool Enabled { get; set; } public string? At { get; set; } diff --git a/src/CasaBot/AutoScan/ScanJob.cs b/src/CasaBot/AutoScan/ScanJob.cs new file mode 100644 index 0000000..cfaefca --- /dev/null +++ b/src/CasaBot/AutoScan/ScanJob.cs @@ -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 _logger; + private readonly AutoScanOptions _options; + + public ScanJob(ILogger logger, IOptionsSnapshot options) + { + _logger = logger; + _options = options.Value; + } + + public Task Execute(IJobExecutionContext context) + { + _logger.LogWarning("Scheduled scan executed with ops: {Options}", _options); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/CasaBot/CasaBotApp/ShinobiConnector.cs b/src/CasaBot/AutoScan/ShinobiConnector.cs similarity index 87% rename from src/CasaBot/CasaBotApp/ShinobiConnector.cs rename to src/CasaBot/AutoScan/ShinobiConnector.cs index 5b221fb..bbcd386 100644 --- a/src/CasaBot/CasaBotApp/ShinobiConnector.cs +++ b/src/CasaBot/AutoScan/ShinobiConnector.cs @@ -6,10 +6,10 @@ public class ShinobiConnector { //TODO move class to auto scan library private readonly ILogger _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 logger, HttpClient httpClient) diff --git a/src/CasaBot/CasaBotApp/BotConfiguration.cs b/src/CasaBot/CasaBotApp/BotConfiguration.cs deleted file mode 100644 index ae2b2ff..0000000 --- a/src/CasaBot/CasaBotApp/BotConfiguration.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace CasaBotApp; - -public class BotConfiguration -{ - public required string Token { get; set; } -} \ No newline at end of file diff --git a/src/CasaBot/CasaBotApp/BotHandler.cs b/src/CasaBot/CasaBotApp/BotHandler.cs index 6f2d724..4115069 100644 --- a/src/CasaBot/CasaBotApp/BotHandler.cs +++ b/src/CasaBot/CasaBotApp/BotHandler.cs @@ -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 _logger; - private readonly BotConfiguration _botConfiguration; + private readonly TelegramOptions _telegramOptions; private readonly List _subscribers = []; private TelegramBotClient? _bot; - public BotHandler(BotConfiguration botConfiguration, ILogger logger) + public BotHandler(IOptions telegramConfiguration, ILogger 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; diff --git a/src/CasaBot/CasaBotApp/Program.cs b/src/CasaBot/CasaBotApp/Program.cs index 9e94acb..8092b4a 100644 --- a/src/CasaBot/CasaBotApp/Program.cs +++ b/src/CasaBot/CasaBotApp/Program.cs @@ -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("TelegramToken") ?? "" -}); -serviceCollection.Configure(configuration.GetSection("AutoScan")); -serviceCollection.AddSingleton(); -serviceCollection.AddSingleton(); -serviceCollection.AddSingleton(); -serviceCollection.AddSingleton(); -serviceCollection.AddSingleton(); -serviceCollection.AddHttpClient(); +services.Configure(configuration.GetSection("Telegram")); +services.Configure(configuration.GetSection("AutoScan")); -var serviceProvider = serviceCollection.BuildServiceProvider(); +services.AddSingleton(); + +services.AddAutoScan(); +services.AddHttpClient(); + +var serviceProvider = services.BuildServiceProvider(); var logger = serviceProvider.GetService>()!; var botHandler = serviceProvider.GetService()!; +var autoScanApp = serviceProvider.GetService()!; using var cts = new CancellationTokenSource(); -botHandler.Start(cts.Token); +autoScanApp.Run(cts.Token); +// botHandler.Start(cts.Token); _ = SendMessageToSubscribers(cts.Token); -var videoFileName = configuration.GetValue("VideoFileName") ?? "video.mp4"; -if (configuration.GetValue("Fetch")) -{ - var shinobiConnector = serviceProvider.GetService()!; - await shinobiConnector.FetchLastVideo(videoFileName); -} - -if (configuration.GetValue("Scan")) -{ - var dvrScanner = serviceProvider.GetService()!; - await dvrScanner.ScanVideos(cts.Token); -} - -if(configuration.GetValue("Screenshot")) -{ - var detected = "2025-02-12T07-00-02.DSME_0001.avi"; - var ffmpegWrapper = serviceProvider.GetService()!; - 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("VideoFileName") ?? "video.mp4"; +// if (configuration.GetValue("Fetch")) +// { +// var shinobiConnector = serviceProvider.GetService()!; +// await shinobiConnector.FetchLastVideo(videoFileName); +// } +// +// if (configuration.GetValue("Scan")) +// { +// var dvrScanner = serviceProvider.GetService()!; +// await dvrScanner.ScanVideos(cts.Token); +// } +// +// if(configuration.GetValue("Screenshot")) +// { +// var detected = "2025-02-12T07-00-02.DSME_0001.avi"; +// var ffmpegWrapper = serviceProvider.GetService()!; +// 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; diff --git a/src/CasaBot/CasaBotApp/TelegramOptions.cs b/src/CasaBot/CasaBotApp/TelegramOptions.cs new file mode 100644 index 0000000..085f411 --- /dev/null +++ b/src/CasaBot/CasaBotApp/TelegramOptions.cs @@ -0,0 +1,7 @@ +namespace CasaBotApp; + +public class TelegramOptions +{ + public string? BotToken { get; set; } + public long[] SubscribedChatIds { get; set; } = []; +} \ No newline at end of file diff --git a/src/CasaBot/CasaBotApp/appsettings.json b/src/CasaBot/CasaBotApp/appsettings.json index d1fac61..5039a3a 100644 --- a/src/CasaBot/CasaBotApp/appsettings.json +++ b/src/CasaBot/CasaBotApp/appsettings.json @@ -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",