Compare commits
No commits in common. "66aa064e2f147e9d096bb7a77de4f43e2bb02cc4" and "ea4c3bb64c0242bd6907accfa7e29fa326265a2d" have entirely different histories.
66aa064e2f
...
ea4c3bb64c
@ -66,10 +66,9 @@ public class Snapshoter : ISnapshoter
|
||||
try
|
||||
{
|
||||
await process.WaitForExitAsync(timeoutSignal.Token);
|
||||
} catch (OperationCanceledException ex)
|
||||
} catch (OperationCanceledException)
|
||||
{
|
||||
timer.Stop();
|
||||
_logger.LogError("Taking snapshot timed out after {Elapsed} ms", timer.ElapsedMilliseconds);
|
||||
_logger.LogError("Taking snapshot timed out");
|
||||
process.Kill();
|
||||
return null;
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
using AutoScan;
|
||||
using CasaBotApp.TelegramBot;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CasaBotApp.Controllers;
|
||||
|
||||
public class AutoScanController : IController
|
||||
{
|
||||
private readonly BotHandler _botHandler;
|
||||
private readonly AutoScanApp _autoScanApp;
|
||||
private readonly ILogger<AutoScanController> _logger;
|
||||
|
||||
public AutoScanController(BotHandler botHandler, AutoScanApp autoScanApp, ILogger<AutoScanController> logger)
|
||||
{
|
||||
_botHandler = botHandler;
|
||||
_autoScanApp = autoScanApp;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Register()
|
||||
{
|
||||
_autoScanApp.OnScanCompleted = async () =>
|
||||
{
|
||||
_logger.LogInformation("Scan completed at {At}", DateTime.Now);
|
||||
try
|
||||
{
|
||||
var images = _autoScanApp.GetLastScanPictures();
|
||||
if (images.Length == 0)
|
||||
{
|
||||
await _botHandler.UpdateText("No images found");
|
||||
return;
|
||||
}
|
||||
await _botHandler.UpdateText($"Scan completed, found {images.Length} images");
|
||||
await _botHandler.UpdatePhotos(images);
|
||||
}catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while sending message");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
using AutoScan;
|
||||
using AutoScan.Interfaces;
|
||||
using CasaBotApp.TelegramBot;
|
||||
using ControlServer;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Diagnostics;
|
||||
using Telegram.Bots.Types;
|
||||
using BotCommand = CasaBotApp.TelegramBot.BotCommand;
|
||||
|
||||
namespace CasaBotApp.Controllers;
|
||||
|
||||
public class BotController : IController
|
||||
{
|
||||
private readonly BotHandler _botHandler;
|
||||
private readonly ILogger<BotController> _logger;
|
||||
private readonly AutoScanApp _autoScanApp;
|
||||
private readonly ISnapshoter _snapshoter;
|
||||
private readonly IControlServer _controlServer;
|
||||
|
||||
|
||||
public BotController(BotHandler botHandler, ILogger<BotController> logger, AutoScanApp autoScanApp, ISnapshoter snapshoter, IControlServer controlServer)
|
||||
{
|
||||
_botHandler = botHandler;
|
||||
_logger = logger;
|
||||
_autoScanApp = autoScanApp;
|
||||
_snapshoter = snapshoter;
|
||||
_controlServer = controlServer;
|
||||
}
|
||||
|
||||
public void Register()
|
||||
{
|
||||
_logger.LogInformation("Registering bot commands");
|
||||
var methods = GetType().GetMethods()
|
||||
.Where(m => m.GetCustomAttributes(typeof(BotCommandAttribute), false).Length > 0)
|
||||
.ToArray();
|
||||
foreach (var method in methods)
|
||||
{
|
||||
try
|
||||
{
|
||||
var attribute = (BotCommandAttribute)method.GetCustomAttributes(typeof(BotCommandAttribute), false)[0];
|
||||
var command = new BotCommand
|
||||
{
|
||||
Command = attribute.Command,
|
||||
Description = attribute.Description,
|
||||
Action = method.CreateDelegate<Func<TextMessage, BotCommand, Task>>(this),
|
||||
};
|
||||
_botHandler.RegisterCommand(command);
|
||||
|
||||
_logger.LogInformation("Registered command: {Command} - {Description}", command.Command, command.Description);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "Error registering command {Command}", method.Name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HandleReply();
|
||||
}
|
||||
|
||||
[BotCommand("/soyandre", "Soy Andre")]
|
||||
public async Task HiAndre(TextMessage msg, BotCommand ctx)
|
||||
{
|
||||
_logger.LogInformation("Andre stoped by");
|
||||
await ctx.Responder(msg, "Hola vida, te amo mucho ❤️");
|
||||
}
|
||||
|
||||
[BotCommand("/startScan", "Start a scan of last night images")]
|
||||
public async Task StartScan(TextMessage msg, BotCommand ctx)
|
||||
{
|
||||
await ctx.Responder(msg, "Starting scan 🔍📼");
|
||||
await _autoScanApp.StartNewScan();
|
||||
}
|
||||
|
||||
[BotCommand("/lastscan", "Send the images from the last scan")]
|
||||
public async Task LastScan(TextMessage msg, BotCommand ctx)
|
||||
{
|
||||
var images = _autoScanApp.GetLastScanPictures();
|
||||
if (images.Length == 0)
|
||||
{
|
||||
await ctx.Responder(msg, "No images found");
|
||||
return;
|
||||
}
|
||||
await _botHandler.SendPhotos(msg.Chat.Id, images);
|
||||
|
||||
}
|
||||
|
||||
[BotCommand("/now", "Get the current snapshot")]
|
||||
public async Task CurrentSnapshot(TextMessage msg, BotCommand ctx)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
stopwatch.Start();
|
||||
var outputPath = await _snapshoter.TakeSnapshot();
|
||||
stopwatch.Stop();
|
||||
if (string.IsNullOrEmpty(outputPath))
|
||||
{
|
||||
await ctx.Responder(msg, "Error taking snapshot, try later");
|
||||
return;
|
||||
}
|
||||
_ = _botHandler.SendPhoto(msg.Chat.Id, outputPath, $"Snapshot: {DateTime.Now:g} ({stopwatch.ElapsedMilliseconds} ms)");
|
||||
}
|
||||
|
||||
[BotCommand("/disarm", "Disarm the Door Sensor")]
|
||||
public async Task Disarm(TextMessage msg, BotCommand ctx)
|
||||
{
|
||||
await ctx.Responder(msg, "Disarming the door sensor");
|
||||
_controlServer.RequestDisarm();
|
||||
}
|
||||
|
||||
private void HandleReply()
|
||||
{
|
||||
_botHandler.OnReply = async msg =>
|
||||
{
|
||||
var originalMsg = msg.ReplyToMessage;
|
||||
|
||||
// Check if the original message is a photo and has a caption
|
||||
if (originalMsg is not PhotoMessage photoMessage || photoMessage.Caption is null)
|
||||
return;
|
||||
|
||||
var videoPath = _autoScanApp.GetVideoPath(photoMessage.Caption);
|
||||
if (string.IsNullOrEmpty(videoPath))
|
||||
{
|
||||
await _botHandler.SendText(msg.Chat.Id, "No video found for this image");
|
||||
return;
|
||||
}
|
||||
|
||||
await _botHandler.SendVideo(msg.Chat.Id, videoPath);
|
||||
};
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
private class BotCommandAttribute : Attribute
|
||||
{
|
||||
public string Command { get; }
|
||||
public string Description { get; }
|
||||
|
||||
public BotCommandAttribute(string command, string description)
|
||||
{
|
||||
Command = command;
|
||||
Description = description;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
namespace CasaBotApp.Controllers;
|
||||
|
||||
public class CasaBotOrchestrator
|
||||
{
|
||||
private readonly IEnumerable<IController> _controllers;
|
||||
|
||||
public CasaBotOrchestrator(IEnumerable<IController> controllers)
|
||||
{
|
||||
_controllers = controllers;
|
||||
}
|
||||
|
||||
public void RegisterControllers()
|
||||
{
|
||||
foreach (var controller in _controllers)
|
||||
{
|
||||
controller.Register();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
namespace CasaBotApp.Controllers;
|
||||
|
||||
public interface IController
|
||||
{
|
||||
void Register();
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
using AutoScan.Interfaces;
|
||||
using CasaBotApp.TelegramBot;
|
||||
using ControlServer;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CasaBotApp.Controllers;
|
||||
|
||||
public class ServerController : IController
|
||||
{
|
||||
private readonly IControlServer _controlServer;
|
||||
private readonly BotHandler _botHandler;
|
||||
private readonly ISnapshoter _snapshoter;
|
||||
private readonly ILogger<ServerController> _logger;
|
||||
private readonly IShinobiLinkFactory _shinobiLinkFactory;
|
||||
|
||||
public ServerController(IControlServer controlServer, ISnapshoter snapshoter, ILogger<ServerController> logger, IShinobiLinkFactory shinobiLinkFactory, BotHandler botHandler)
|
||||
{
|
||||
_controlServer = controlServer;
|
||||
_snapshoter = snapshoter;
|
||||
_logger = logger;
|
||||
_shinobiLinkFactory = shinobiLinkFactory;
|
||||
_botHandler = botHandler;
|
||||
}
|
||||
|
||||
public void Register()
|
||||
{
|
||||
_controlServer.OnEvent(async sensorEvent =>
|
||||
{
|
||||
var mediaPath = await _snapshoter.TakeSnapshot();
|
||||
if (string.IsNullOrEmpty(mediaPath))
|
||||
{
|
||||
await _botHandler.AlertText("Unauthorized access detected 🚨🚨🚨, but no media available");
|
||||
return;
|
||||
}
|
||||
if (sensorEvent.Type == EventType.Fired)
|
||||
{
|
||||
await _botHandler.AlertPhoto(mediaPath,
|
||||
"Unauthorized access detected 🚨 🚨 🚨",
|
||||
[
|
||||
new(OptionType.Url, "Camera Feed", _shinobiLinkFactory.BuildFeedLink()),
|
||||
new(OptionType.Action, "Authorize", $"authorize-{sensorEvent.EventId}", (_, _ ) =>
|
||||
{
|
||||
_logger.LogWarning("Authorizing event {EventId}", sensorEvent.EventId);
|
||||
_controlServer.AuthorizeEvent(sensorEvent.EventId);
|
||||
return Task.FromResult("Entrance authorized");
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
if (sensorEvent.Type == EventType.DisarmedEntrance)
|
||||
{
|
||||
await _botHandler.UpdateText("Authorize access");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
|
||||
using CasaBotApp.Controllers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace CasaBotApp.Extensions;
|
||||
|
||||
public static class AlarmBotOrchestration
|
||||
{
|
||||
public static void AddCasaBotOrchestration(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<CasaBotOrchestrator>();
|
||||
services.AddTransient<IController, AutoScanController>();
|
||||
services.AddTransient<IController, BotController>();
|
||||
services.AddTransient<IController, ServerController>();
|
||||
}
|
||||
|
||||
}
|
172
src/CasaBot/CasaBotApp/Extensions/AlarmBotOrquestrator.cs
Normal file
172
src/CasaBot/CasaBotApp/Extensions/AlarmBotOrquestrator.cs
Normal file
@ -0,0 +1,172 @@
|
||||
using AutoScan;
|
||||
using AutoScan.Interfaces;
|
||||
using CasaBotApp.TelegramBot;
|
||||
using ControlServer;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Diagnostics;
|
||||
using Telegram.Bots.Types;
|
||||
using BotCommand = CasaBotApp.TelegramBot.BotCommand;
|
||||
|
||||
namespace CasaBotApp.Extensions;
|
||||
|
||||
public class AlarmBotOrquestrator
|
||||
{
|
||||
private readonly ILogger<AlarmBotOrquestrator> _logger;
|
||||
private readonly BotHandler _botHandler;
|
||||
private readonly AutoScanApp _autoScanApp;
|
||||
private readonly IControlServer _controlServer;
|
||||
private readonly IShinobiLinkFactory _shinobiLinkFactory;
|
||||
private ISnapshoter _snapshoter;
|
||||
|
||||
public AlarmBotOrquestrator(ILogger<AlarmBotOrquestrator> logger, BotHandler botHandler, AutoScanApp autoScanApp,
|
||||
IControlServer controlServer, IShinobiLinkFactory shinobiLinkFactory, ISnapshoter snapshoter)
|
||||
{
|
||||
_logger = logger;
|
||||
_botHandler = botHandler;
|
||||
_autoScanApp = autoScanApp;
|
||||
_controlServer = controlServer;
|
||||
_shinobiLinkFactory = shinobiLinkFactory;
|
||||
_snapshoter = snapshoter;
|
||||
}
|
||||
|
||||
public void RegisterCommands()
|
||||
{
|
||||
_botHandler.RegisterCommand(new BotCommand
|
||||
{
|
||||
Command = "/soyandre",
|
||||
Description = "Soy Andre",
|
||||
Action = async (message, ctx) =>
|
||||
{
|
||||
await ctx.Responder(message, "Hola vida, te amo mucho ❤️");
|
||||
}
|
||||
});
|
||||
_botHandler.RegisterCommand(new BotCommand
|
||||
{
|
||||
Command = "/startScan",
|
||||
Description = "Start a scan of last night images",
|
||||
Action = async (message, ctx) =>
|
||||
{
|
||||
await ctx.Responder(message, "Starting scan 🔍📼");
|
||||
await _autoScanApp.StartNewScan();
|
||||
}
|
||||
});
|
||||
_botHandler.RegisterCommand(new BotCommand
|
||||
{
|
||||
Command = "/lastscan",
|
||||
Description = "Send the images from the last scan",
|
||||
Action = async (message, ctx) =>
|
||||
{
|
||||
var images = _autoScanApp.GetLastScanPictures();
|
||||
if (images.Length == 0)
|
||||
{
|
||||
await ctx.Responder(message, "No images found");
|
||||
return;
|
||||
}
|
||||
await _botHandler.SendPhotos(message.Chat.Id, images);
|
||||
}
|
||||
});
|
||||
|
||||
_botHandler.RegisterCommand(new BotCommand()
|
||||
{
|
||||
Command = "/now",
|
||||
Description = "Send the current snapshot",
|
||||
Action = async (msg, ctx) =>
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
stopwatch.Start();
|
||||
var outputPath = await _snapshoter.TakeSnapshot();
|
||||
stopwatch.Stop();
|
||||
if (string.IsNullOrEmpty(outputPath))
|
||||
{
|
||||
await ctx.Responder(msg, "Error taking snapshot");
|
||||
return;
|
||||
}
|
||||
_ = _botHandler.SendPhoto(msg.Chat.Id, outputPath, "Current snapshot");
|
||||
_ = _botHandler.SendText(msg.Chat.Id, $"It took {stopwatch.ElapsedMilliseconds} ms to take the picture");
|
||||
}
|
||||
});
|
||||
_botHandler.RegisterCommand(new BotCommand()
|
||||
{
|
||||
Command = "/disarm",
|
||||
Description = "Disarm the Door Sensor",
|
||||
Action = async (msg, ctx) =>
|
||||
{
|
||||
await ctx.Responder(msg, "Disarming the door sensor");
|
||||
_controlServer.RequestDisarm();
|
||||
}
|
||||
});
|
||||
|
||||
_botHandler.OnReply = async msg =>
|
||||
{
|
||||
var originalMsg = msg.ReplyToMessage;
|
||||
|
||||
// Check if the original message is a photo and has a caption
|
||||
if (originalMsg is not PhotoMessage photoMessage || photoMessage.Caption is null)
|
||||
return;
|
||||
|
||||
var videoPath = _autoScanApp.GetVideoPath(photoMessage.Caption);
|
||||
if (string.IsNullOrEmpty(videoPath))
|
||||
{
|
||||
await _botHandler.SendText(msg.Chat.Id, "No video found for this image");
|
||||
return;
|
||||
}
|
||||
|
||||
await _botHandler.SendVideo(msg.Chat.Id, videoPath);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public void RegisterAutoScanApp()
|
||||
{
|
||||
_autoScanApp.OnScanCompleted = async () =>
|
||||
{
|
||||
_logger.LogInformation("Scan completed at {At}", DateTime.Now);
|
||||
try
|
||||
{
|
||||
var images = _autoScanApp.GetLastScanPictures();
|
||||
if (images.Length == 0)
|
||||
{
|
||||
await _botHandler.UpdateText("No images found");
|
||||
return;
|
||||
}
|
||||
await _botHandler.UpdateText($"Scan completed, found {images.Length} images");
|
||||
await _botHandler.UpdatePhotos(images);
|
||||
}catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while sending message");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void RegisterControlServer()
|
||||
{
|
||||
_controlServer.OnEvent(async sensorEvent =>
|
||||
{
|
||||
var mediaPath = await _snapshoter.TakeSnapshot();
|
||||
if (string.IsNullOrEmpty(mediaPath))
|
||||
{
|
||||
await _botHandler.AlertText("Unauthorized access detected 🚨🚨🚨, but no media available");
|
||||
return;
|
||||
}
|
||||
if (sensorEvent.Type == EventType.Fired)
|
||||
{
|
||||
await _botHandler.AlertPhoto(mediaPath,
|
||||
"Unauthorized access detected 🚨 🚨 🚨",
|
||||
[
|
||||
new(OptionType.Url, "Camera Feed", _shinobiLinkFactory.BuildFeedLink()),
|
||||
new(OptionType.Action, "Authorize", $"authorize-{sensorEvent.EventId}", (_, _ ) =>
|
||||
{
|
||||
_logger.LogWarning("Authorizing event {EventId}", sensorEvent.EventId);
|
||||
_controlServer.AuthorizeEvent(sensorEvent.EventId);
|
||||
return Task.FromResult("Entrance authorized");
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
if (sensorEvent.Type == EventType.DisarmedEntrance)
|
||||
{
|
||||
await _botHandler.UpdateText("Authorize access");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
using AutoScan;
|
||||
using AutoScan.Options;
|
||||
using CasaBotApp.Controllers;
|
||||
using CasaBotApp.Extensions;
|
||||
using CasaBotApp.TelegramBot;
|
||||
using ControlServer;
|
||||
@ -41,7 +40,7 @@ hostBuilder.ConfigureServices((_, services) =>
|
||||
services.AddPolling<BotHandler>();
|
||||
services.AddSingleton<IUpdateHandler>(sp => sp.GetService<BotHandler>()!);
|
||||
|
||||
services.AddCasaBotOrchestration();
|
||||
services.AddTransient<AlarmBotOrquestrator>();
|
||||
|
||||
// To get notifications when a retry is performed
|
||||
|
||||
@ -66,14 +65,16 @@ var host = hostBuilder.Build();
|
||||
var logger = host.Services.GetService<ILogger<Program>>()!;
|
||||
var autoScanApp = host.Services.GetService<AutoScanApp>()!;
|
||||
|
||||
var orchestrator = host.Services.GetRequiredService<CasaBotOrchestrator>();
|
||||
var commandRegister = host.Services.GetRequiredService<AlarmBotOrquestrator>();
|
||||
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
|
||||
_ = autoScanApp.Run(cts.Token);
|
||||
|
||||
orchestrator.RegisterControllers();
|
||||
commandRegister.RegisterAutoScanApp();
|
||||
commandRegister.RegisterCommands();
|
||||
commandRegister.RegisterControlServer();
|
||||
|
||||
logger.LogInformation("Bot started");
|
||||
await host.RunAsync(cts.Token);
|
||||
|
@ -16,21 +16,22 @@ namespace CasaBotApp.TelegramBot;
|
||||
public class BotHandler : IUpdateHandler
|
||||
{
|
||||
private readonly ILogger<BotHandler> _logger;
|
||||
private readonly TelegramOptions _telegramOptions;
|
||||
private readonly List<Chat> _subscribers = [];
|
||||
private readonly List<Chat> _subscribersAlarm = [];
|
||||
private readonly Dictionary<string, BotCommand> _commands;
|
||||
|
||||
//TODO hacerlo mejor.
|
||||
private readonly Dictionary<string, CallbackQueueItem> _callbackFunctions = new();
|
||||
private record CallbackQueueItem(DateTime inserted, Func<string, long, Task<string>> callback);
|
||||
|
||||
public Func<TextMessage, Task>? OnReply { get; set; }
|
||||
public Func<TextMessage, Task>? OnReply { get; set; } = null;
|
||||
|
||||
private readonly IBotClient _bot;
|
||||
|
||||
public BotHandler(IBotClient bot, IOptions<TelegramOptions> telegramConfiguration, ILogger<BotHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
var telegramOptions = telegramConfiguration.Value;
|
||||
_telegramOptions = telegramConfiguration.Value;
|
||||
_bot = bot;
|
||||
_commands = [];
|
||||
RegisterCommand(new()
|
||||
@ -40,6 +41,7 @@ public class BotHandler : IUpdateHandler
|
||||
Action = RegisterUser,
|
||||
Responder = Respond
|
||||
});
|
||||
{
|
||||
RegisterCommand(new()
|
||||
{
|
||||
Command = "/registeralarm",
|
||||
@ -47,12 +49,20 @@ public class BotHandler : IUpdateHandler
|
||||
Action = RegisterUserAlarm,
|
||||
Responder = Respond
|
||||
});
|
||||
}
|
||||
RegisterCommand(new()
|
||||
{
|
||||
Command = "/photo",
|
||||
Description = "Get a photo",
|
||||
Action = SendImageTest,
|
||||
Responder = Respond
|
||||
});
|
||||
|
||||
foreach (var subs in telegramOptions.SubscribedChatIds)
|
||||
foreach (var subs in _telegramOptions.SubscribedChatIds)
|
||||
{
|
||||
Subscribe(subs);
|
||||
}
|
||||
foreach(var sub in telegramOptions.SubscribedAlarmsChatIds)
|
||||
foreach(var sub in _telegramOptions.SubscribedAlarmsChatIds)
|
||||
{
|
||||
SubscribeAlarm(sub);
|
||||
}
|
||||
@ -95,13 +105,12 @@ public class BotHandler : IUpdateHandler
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a text message to all subscribers
|
||||
/// Send text message to all subscribers
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public Task UpdateText(string message) => UpdateTextInt(_subscribers, message);
|
||||
public Task AlertText(string message) => UpdateTextInt(_subscribersAlarm, message);
|
||||
|
||||
private async Task UpdateTextInt(List<Chat> subscribers,string message)
|
||||
public async Task UpdateTextInt(List<Chat> subscribers,string message)
|
||||
{
|
||||
if (subscribers.Count == 0)
|
||||
{
|
||||
@ -128,7 +137,7 @@ public class BotHandler : IUpdateHandler
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Send a photo to all subscribers
|
||||
/// Send photo to all subscribers
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="caption">Optional message with photo</param>
|
||||
@ -136,13 +145,6 @@ public class BotHandler : IUpdateHandler
|
||||
public Task UpdatePhoto(string path, string? caption = null, IEnumerable<MsgOption>? options = null) =>
|
||||
UpdatePhotoInt(_subscribers, path, caption, options);
|
||||
|
||||
/// <summary>
|
||||
/// Send a photo to all alert subscribers
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="caption"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
public Task AlertPhoto(string path, string? caption = null, IEnumerable<MsgOption>? options = null) =>
|
||||
UpdatePhotoInt(_subscribersAlarm, path, caption, options);
|
||||
|
||||
@ -192,7 +194,7 @@ public class BotHandler : IUpdateHandler
|
||||
}
|
||||
}
|
||||
|
||||
private Task HandleQueueExpiration()
|
||||
private async Task HandleQueueExpiration()
|
||||
{
|
||||
//remove expired items with more than 3 hs
|
||||
var expired = _callbackFunctions.Where(x => x.Value.inserted.AddHours(3) < DateTime.Now).ToArray();
|
||||
@ -201,7 +203,6 @@ public class BotHandler : IUpdateHandler
|
||||
_callbackFunctions.Remove(item.Key);
|
||||
_logger.LogDebug("Removed expired callback function {Key}", item.Key);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
@ -250,8 +251,8 @@ public class BotHandler : IUpdateHandler
|
||||
|
||||
if (_subscribers.Count < 1) return;
|
||||
|
||||
var caches = response.Result.Select(x => (x as PhotoMessage)!.PhotoSet.LastOrDefault()?.Id).ToList();
|
||||
var media = caches.Select(x => new CachedPhoto(x!)).ToList();
|
||||
var caches = response.Result.Select(x => (x as PhotoMessage).PhotoSet.LastOrDefault()?.Id).ToList();
|
||||
var media = caches.Select(x => new CachedPhoto(x)).ToList();
|
||||
|
||||
//send to the rest of the subscribers
|
||||
foreach (var subscriber in _subscribers.Skip(1).ToList())
|
||||
@ -271,6 +272,14 @@ public class BotHandler : IUpdateHandler
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SendImageTest(TextMessage msg, BotCommand _)
|
||||
{
|
||||
await using var stream = File.OpenRead(@"C:\Users\GuillermoMarcel\Pictures\prueba.jpeg");
|
||||
|
||||
var send = new SendPhotoFile(msg.Chat.Id.ToString(), stream);
|
||||
await _bot.HandleAsync(send);
|
||||
}
|
||||
|
||||
public async Task SendPhoto(long chatId, string content, string caption)
|
||||
{
|
||||
await using var stream = File.OpenRead(content);
|
||||
@ -361,15 +370,7 @@ public class BotHandler : IUpdateHandler
|
||||
|
||||
private async Task OnMessage(TextMessage msg)
|
||||
{
|
||||
var cmd = msg.Text;
|
||||
//Deep link support
|
||||
// link format: https://t.me/your_bot?start=command
|
||||
// what we see: "/start command"
|
||||
if (cmd.StartsWith("/start "))
|
||||
{
|
||||
cmd = $"/{cmd[7..]}";
|
||||
}
|
||||
if(!_commands.TryGetValue(cmd, out var command))
|
||||
if(!_commands.TryGetValue(msg.Text, out var command))
|
||||
{
|
||||
if (msg.ReplyToMessage != null && OnReply is not null)
|
||||
{
|
||||
@ -380,12 +381,12 @@ public class BotHandler : IUpdateHandler
|
||||
return;
|
||||
}
|
||||
|
||||
if (command.Action is null)
|
||||
if (command?.Action is null)
|
||||
{
|
||||
_logger.LogError("Command {Command} has no action", msg.Text);
|
||||
}
|
||||
|
||||
await command.Action!(msg, command);
|
||||
await command!.Action!(msg, command);
|
||||
}
|
||||
|
||||
private async Task SendHelp(TextMessage msg)
|
||||
@ -410,7 +411,7 @@ public class BotHandler : IUpdateHandler
|
||||
|
||||
_subscribers.Add(msg.Chat);
|
||||
_logger.LogInformation("User {User} ({id}) registered to receive messages", msg.Chat.FirstName, msg.Chat.Id);
|
||||
await Respond(msg, "You are registered to receive non-alert messages (Nightly scans)");
|
||||
await Respond(msg, "You are registered to receive messages every minute");
|
||||
}
|
||||
private async Task RegisterUserAlarm(TextMessage msg, BotCommand _)
|
||||
{
|
||||
@ -433,13 +434,6 @@ public class BotHandler : IUpdateHandler
|
||||
_bot.HandleAsync(new SendPhotoFile(chat.Id.ToString(), path));
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Entry point for the bot
|
||||
/// </summary>
|
||||
/// <param name="bot">The bot client used to receive and send messages</param>
|
||||
/// <param name="update">Type of update and message info</param>
|
||||
/// <param name="cst"></param>
|
||||
/// <returns></returns>
|
||||
public Task HandleAsync(IBotClient bot, Update update, CancellationToken cst)
|
||||
{
|
||||
try
|
||||
|
@ -76,10 +76,8 @@ public class ControlServer : IControlServer
|
||||
}
|
||||
response.Close();
|
||||
|
||||
if (notify && _onEventRecived is not null)
|
||||
if (notify)
|
||||
{
|
||||
//don't await this, we don't care about the result.
|
||||
//and we don't want to block the server thread.
|
||||
_ = _onEventRecived?.Invoke(sensorEvent);
|
||||
}
|
||||
}
|
||||
@ -108,8 +106,8 @@ public class ControlServer : IControlServer
|
||||
writer.Write(message);
|
||||
}
|
||||
|
||||
private record UpdateResponse(bool disarm, Card[] cards);
|
||||
private record Card(string id, string name);
|
||||
public record UpdateResponse(bool disarm, Card[] cards);
|
||||
public record Card(string id, string name);
|
||||
private bool HandleSensorEvent(SensorEvent se)
|
||||
{
|
||||
if (se.Type == EventType.Update && _disarmRequestPending)
|
||||
@ -120,10 +118,9 @@ public class ControlServer : IControlServer
|
||||
}
|
||||
|
||||
_events.TryGetValue(se.EventId, out var storedEvent);
|
||||
//New One
|
||||
if (storedEvent is null)
|
||||
{
|
||||
//ESP does not send this type of event yet
|
||||
//New One
|
||||
if (se.Type == EventType.DisarmedEntrance)
|
||||
{
|
||||
_disarmRequestPending = false;
|
||||
@ -132,18 +129,11 @@ public class ControlServer : IControlServer
|
||||
return true;
|
||||
}
|
||||
|
||||
//Alarm is armed and fired.
|
||||
if (se.Type == EventType.Fired)
|
||||
{
|
||||
//Check pending disarm request.
|
||||
if (_disarmRequestPending)
|
||||
{
|
||||
se.Authorization = Authorization.Authorized;
|
||||
se.Type = EventType.DisarmedEntrance;
|
||||
//Check pending desarmed.
|
||||
se.Authorization = _disarmRequestPending ? Authorization.Authorized : Authorization.Unauthorized;
|
||||
_disarmRequestPending = false;
|
||||
return true;
|
||||
}
|
||||
se.Authorization = Authorization.Unauthorized;
|
||||
_events.Add(se.EventId, se);
|
||||
return true;
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ namespace ControlServer;
|
||||
public record SensorEvent(long EventId, EventType Type, string Data)
|
||||
{
|
||||
public Authorization Authorization { get; set; }
|
||||
public EventType Type { get; set; } = Type;
|
||||
};
|
||||
|
||||
public enum EventType
|
||||
|
Loading…
Reference in New Issue
Block a user