Files

59 lines
3.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Telegram.Bot.Types;
using Volcanic.AgenticCore.Telegram.Chats;
using Volcanic.AgenticCore.Telegram.Groups;
namespace Volcanic.AgenticCore.Telegram.Triggers;
/// <summary>Everything the Telegram host does for group triggers, kept out of the shared host files.</summary>
public static class TriggersSetup
{
public const string DisabledReply = "Group triggers are off on this bot (no OPENROUTER_API_KEY).";
public const string HelpLines = "\n/triggers – this chat's group triggers (ask me to create, change or snooze them)";
public static readonly BotCommand MenuCommand = new() { Command = "triggers", Description = "Group triggers watching for topics" };
/// <summary>The Jev client, groups, store, engine, delivery, feed and the hosted service. Only when triggers are on.</summary>
public static void Register(IServiceCollection services, TelegramOptions options, string agentDir)
{
ArgumentNullException.ThrowIfNull(services);
ArgumentNullException.ThrowIfNull(options);
var triggers = options.Triggers;
services.TryAddSingleton(TimeProvider.System);
services.AddSingleton(triggers);
// The engine (a singleton) keeps this typed client for the process lifetime: let the handler recycle its pooled
// connections instead, so DNS changes are still picked up.
services.AddHttpClient<IJevClient, JevClient>(client => client.Timeout = TimeSpan.FromSeconds(30))
.ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(5) })
.SetHandlerLifetime(Timeout.InfiniteTimeSpan);
services.AddSingleton(sp => new GroupRegistry(GroupRegistry.DefaultPath(agentDir), sp.GetRequiredService<ILogger<GroupRegistry>>(), sp.GetRequiredService<TimeProvider>()));
services.AddSingleton(sp => new TriggerStore(options.WorkspaceRoot, triggers.MaxTriggersPerChat, sp.GetRequiredService<ILogger<TriggerStore>>(), sp.GetRequiredService<TimeProvider>()));
services.AddSingleton(new SnoozeQueue(triggers.MaxQueuedPerTrigger));
// Resolves the registry at call time: ChatRegistry → trigger extension → engine → delivery would be a cycle.
services.AddSingleton<ITriggerDelivery>(sp => new TelegramTriggerDelivery(
() => sp.GetRequiredService<ChatRegistry>(), sp.GetRequiredService<TimeProvider>(), sp.GetRequiredService<ILogger<TelegramTriggerDelivery>>()));
services.AddSingleton<TriggerDispatcher>();
services.AddSingleton<TriggerEngine>();
services.AddSingleton<IGroupMembership, TelegramGroupMembership>();
services.AddSingleton<TriggerServices>();
services.AddSingleton<GroupFeed>();
services.AddHostedService<TriggersHostedService>();
}
}
/// <summary>Flushes snoozes that ended while the host was down and arms the snooze timer.</summary>
public sealed class TriggersHostedService(TriggerEngine engine) : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken) => engine.StartAsync(cancellationToken);
public Task StopAsync(CancellationToken cancellationToken)
{
engine.Dispose();
return Task.CompletedTask;
}
}