Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Kattbot/Infrastructure/NotificationPublisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public Task Publish(INotification notification, CancellationToken cancellationTo
/// <summary>
/// Sauce: https://github.com/jbogard/MediatR/blob/master/samples/MediatR.Examples.PublishStrategies/Publisher.cs.
/// </summary>
private async Task SyncContinueOnException(
private static async Task SyncContinueOnException(
IEnumerable<NotificationHandlerExecutor> handlers,
INotification notification,
CancellationToken cancellationToken)
Expand All @@ -41,7 +41,7 @@ private async Task SyncContinueOnException(
{
exceptions.AddRange(ex.Flatten().InnerExceptions);
}
catch (Exception ex) when (!(ex is OutOfMemoryException || ex is StackOverflowException))
catch (Exception ex) when (ex is not (OutOfMemoryException or StackOverflowException))
{
exceptions.Add(ex);
}
Expand Down
60 changes: 24 additions & 36 deletions src/Kattbot/Infrastructure/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,29 @@ public static void AddDiscordClient(this IServiceCollection services, IConfigura

var clientBuilder = DiscordClientBuilder.CreateDefault(botToken, DiscordIntents.All, services);

clientBuilder.ConfigureExtraFeatures(cfg => { cfg.LogUnknownEvents = false; });

clientBuilder.SetLogLevel(logLevel);

clientBuilder.RegisterCommands(configuration);

clientBuilder.RegisterEventHandlers();

// This replacement has to happen after the DiscordClientBuilder.CreateDefault call
// and before the DiscordClient is built.
services.Replace<IGatewayController, NoWayGateway>();

// Calling build registers the DiscordClient as a singleton in the service collection
clientBuilder.Build();
}

public static void AddDbContext(this IServiceCollection services, IConfiguration configuration)
{
services.AddDbContext<KattbotContext>(
builder =>
{
var dbConnString = configuration.GetValue<string>("Kattbot:ConnectionString");
var logLevel = configuration.GetValue<string>("Logging:LogLevel:Default");
services.AddDbContext<KattbotContext>(builder =>
{
var dbConnString = configuration.GetValue<string>("Kattbot:ConnectionString");
var logLevel = configuration.GetValue<string>("Logging:LogLevel:Default");

builder.EnableSensitiveDataLogging(logLevel == "Debug");
builder.EnableSensitiveDataLogging(logLevel == "Debug");

builder.UseNpgsql(dbConnString);
},
ServiceLifetime.Transient,
ServiceLifetime.Singleton);
builder.UseNpgsql(dbConnString);
});
}

private static void RegisterCommands(this DiscordClientBuilder builder, IConfiguration configuration)
Expand Down Expand Up @@ -95,28 +90,21 @@ private static void RegisterCommands(this DiscordClientBuilder builder, IConfigu

private static void RegisterEventHandlers(this DiscordClientBuilder builder)
{
builder.ConfigureEventHandlers(
cfg =>
{
cfg.HandleMessageCreated(
(client, args) =>
client.WriteNotification(new MessageCreatedNotification(args)));
cfg.HandleMessageUpdated(
(client, args) =>
client.WriteNotification(new MessageUpdatedNotification(args)));
cfg.HandleMessageDeleted(
(client, args) =>
client.WriteNotification(new MessageDeletedNotification(args)));
cfg.HandleMessagesBulkDeleted(
(client, args) =>
client.WriteNotification(new MessageBulkDeletedNotification(args)));
cfg.HandleMessageReactionAdded(
(client, args) =>
client.WriteNotification(new MessageReactionAddedNotification(args)));
cfg.HandleMessageReactionRemoved(
(client, args) =>
client.WriteNotification(new MessageReactionRemovedNotification(args)));
});
builder.ConfigureEventHandlers(cfg =>
{
cfg.HandleMessageCreated((client, args) =>
client.WriteNotification(new MessageCreatedNotification(args)));
cfg.HandleMessageUpdated((client, args) =>
client.WriteNotification(new MessageUpdatedNotification(args)));
cfg.HandleMessageDeleted((client, args) =>
client.WriteNotification(new MessageDeletedNotification(args)));
cfg.HandleMessagesBulkDeleted((client, args) =>
client.WriteNotification(new MessageBulkDeletedNotification(args)));
cfg.HandleMessageReactionAdded((client, args) =>
client.WriteNotification(new MessageReactionAddedNotification(args)));
cfg.HandleMessageReactionRemoved((client, args) =>
client.WriteNotification(new MessageReactionRemovedNotification(args)));
});
}

private static async Task WriteNotification<T>(this DiscordClient client, T notification)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,16 @@ namespace Kattbot.NotificationHandlers.Emotes;
public class MessageCreatedNotificationHandler : BaseNotificationHandler,
INotificationHandler<MessageCreatedNotification>
{
private readonly EmoteEntityBuilder _emoteBuilder;
private readonly EmotesRepository _kattbotRepo;
private readonly IOptions<BotOptions> _botOptions;
private readonly ILogger<MessageCreatedNotificationHandler> _logger;

public MessageCreatedNotificationHandler(
ILogger<MessageCreatedNotificationHandler> logger,
EmoteEntityBuilder emoteBuilder,
EmotesRepository kattbotRepo,
IOptions<BotOptions> botOptions)
{
_logger = logger;
_emoteBuilder = emoteBuilder;
_kattbotRepo = kattbotRepo;
_botOptions = botOptions;
}
Expand Down Expand Up @@ -64,7 +61,7 @@ public async Task Handle(MessageCreatedNotification notification, CancellationTo

ulong guildId = guild.Id;

List<EmoteEntity> emotes = _emoteBuilder.BuildFromSocketUserMessage(message, guildId);
List<EmoteEntity> emotes = EmoteEntityBuilder.BuildFromSocketUserMessage(message, guildId);

if (emotes.Count > 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,14 @@ namespace Kattbot.NotificationHandlers.Emotes;
public class MessageReactionAddedNotificationHandler : BaseNotificationHandler,
INotificationHandler<MessageReactionAddedNotification>
{
private readonly EmoteEntityBuilder _emoteBuilder;
private readonly EmotesRepository _kattbotRepo;
private readonly ILogger<MessageReactionAddedNotificationHandler> _logger;

public MessageReactionAddedNotificationHandler(
ILogger<MessageReactionAddedNotificationHandler> logger,
EmoteEntityBuilder emoteBuilder,
EmotesRepository kattbotRepo)
{
_logger = logger;
_emoteBuilder = emoteBuilder;
_kattbotRepo = kattbotRepo;
}

Expand Down Expand Up @@ -59,7 +56,7 @@ public Task Handle(MessageReactionAddedNotification notification, CancellationTo
return Task.CompletedTask;
}

EmoteEntity emoteEntity = _emoteBuilder.BuildFromUserReaction(message, emoji, userId, guild.Id);
EmoteEntity emoteEntity = EmoteEntityBuilder.BuildFromUserReaction(message, emoji, userId, guild.Id);

_logger.LogDebug($"Saving reaction emote {emoteEntity}");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,14 @@ namespace Kattbot.NotificationHandlers.Emotes;
public class MessageReactionRemovedNotificationHandler : BaseNotificationHandler,
INotificationHandler<MessageReactionRemovedNotification>
{
private readonly EmoteEntityBuilder _emoteBuilder;
private readonly EmotesRepository _kattbotRepo;
private readonly ILogger<MessageReactionRemovedNotificationHandler> _logger;

public MessageReactionRemovedNotificationHandler(
ILogger<MessageReactionRemovedNotificationHandler> logger,
EmoteEntityBuilder emoteBuilder,
EmotesRepository kattbotRepo)
{
_logger = logger;
_emoteBuilder = emoteBuilder;
_kattbotRepo = kattbotRepo;
}

Expand Down Expand Up @@ -59,7 +56,7 @@ public Task Handle(MessageReactionRemovedNotification notification, Cancellation
return Task.CompletedTask;
}

EmoteEntity emoteEntity = _emoteBuilder.BuildFromUserReaction(message, emoji, userId, guild.Id);
EmoteEntity emoteEntity = EmoteEntityBuilder.BuildFromUserReaction(message, emoji, userId, guild.Id);

_logger.LogDebug($"Removing reaction emote {emoteEntity}");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,14 @@ namespace Kattbot.NotificationHandlers.Emotes;
public class MessageUpdatedNotificationHandler : BaseNotificationHandler,
INotificationHandler<MessageUpdatedNotification>
{
private readonly EmoteEntityBuilder _emoteBuilder;
private readonly EmotesRepository _kattbotRepo;
private readonly ILogger<MessageUpdatedNotificationHandler> _logger;

public MessageUpdatedNotificationHandler(
ILogger<MessageUpdatedNotificationHandler> logger,
EmoteEntityBuilder emoteBuilder,
EmotesRepository kattbotRepo)
{
_logger = logger;
_emoteBuilder = emoteBuilder;
_kattbotRepo = kattbotRepo;
}

Expand All @@ -58,7 +55,7 @@ public async Task Handle(MessageUpdatedNotification notification, CancellationTo

await _kattbotRepo.RemoveEmotesForMessage(messageId);

List<EmoteEntity> emotes = _emoteBuilder.BuildFromSocketUserMessage(message, guildId);
List<EmoteEntity> emotes = EmoteEntityBuilder.BuildFromSocketUserMessage(message, guildId);

if (emotes.Count > 0)
{
Expand Down
155 changes: 74 additions & 81 deletions src/Kattbot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,87 +16,80 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace Kattbot;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
ConfigurationManager configuration = builder.Configuration;
IServiceCollection services = builder.Services;

public class Program
services.Configure<BotOptions>(configuration.GetSection(BotOptions.OptionsKey));
services.Configure<KattGptOptions>(configuration.GetSection(KattGptOptions.OptionsKey));

services.AddHttpClient();
services.AddHttpClient<ChatGptHttpClient>();
services.AddHttpClient<SpeechHttpClient>();
services.AddHttpClient<GptImagesHttpClient>();

services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssemblyContaining<Program>();
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(CommandRequestPipelineBehaviour<,>));
});

// Registered as Transient to match lifetime of MediatR
services.AddTransient<NotificationPublisher>();

AddWorkers(services);

AddChannels(services);

AddInternalServices(services);

AddRepositories(services);

services.AddDbContext(configuration);

services.AddDiscordClient(configuration);

IHost app = builder.Build();

app.Run();

return;

static void AddInternalServices(IServiceCollection services)
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
IConfiguration configuration = hostContext.Configuration;

services.Configure<BotOptions>(hostContext.Configuration.GetSection(BotOptions.OptionsKey));
services.Configure<KattGptOptions>(hostContext.Configuration.GetSection(KattGptOptions.OptionsKey));

services.AddHttpClient();
services.AddHttpClient<ChatGptHttpClient>();
services.AddHttpClient<SpeechHttpClient>();
services.AddHttpClient<GptImagesHttpClient>();

services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssemblyContaining<Program>();
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(CommandRequestPipelineBehaviour<,>));
});
services.AddSingleton<NotificationPublisher>();

services.AddSingleton<SharedCache>();
services.AddSingleton<KattGptChannelCache>();

AddWorkers(services);

AddChannels(services);

AddInternalServices(services);

AddRepositories(services);

services.AddDbContext(configuration);

services.AddDiscordClient(configuration);
});
}

private static void AddInternalServices(IServiceCollection services)
{
services.AddTransient<EmoteEntityBuilder>();
services.AddTransient<DateTimeProvider>();
services.AddTransient<GuildSettingsService>();
services.AddTransient<ImageService>();
services.AddTransient<DiscordErrorLogger>();
services.AddTransient<DiscordResolver>();
services.AddTransient<KattGptService>();
}

private static void AddRepositories(IServiceCollection services)
{
services.AddTransient<EmotesRepository>();
services.AddTransient<EmoteStatsRepository>();
services.AddTransient<BotUserRolesRepository>();
services.AddTransient<GuildSettingsRepository>();
}

private static void AddWorkers(IServiceCollection services)
{
services.AddHostedService<CommandQueueWorker>();
services.AddHostedService<EventQueueWorker>();
services.AddHostedService<DiscordLoggerWorker>();
services.AddHostedService<BotWorker>();
}

private static void AddChannels(IServiceCollection services)
{
const int channelSize = 1024;

services.AddSingleton(new CommandQueueChannel(Channel.CreateBounded<CommandRequest>(channelSize)));
services.AddSingleton(new EventQueueChannel(Channel.CreateBounded<INotification>(channelSize)));
services.AddSingleton(new DiscordLogChannel(Channel.CreateBounded<BaseDiscordLogItem>(channelSize)));
}
services.AddSingleton<SharedCache>();
services.AddSingleton<KattGptChannelCache>();

services.AddSingleton<DateTimeProvider>();
services.AddSingleton<DiscordErrorLogger>();
services.AddSingleton<DiscordResolver>();

services.AddScoped<GuildSettingsService>();
services.AddScoped<ImageService>();
services.AddScoped<KattGptService>();
}

static void AddRepositories(IServiceCollection services)
{
services.AddScoped<EmotesRepository>();
services.AddScoped<EmoteStatsRepository>();
services.AddScoped<BotUserRolesRepository>();
services.AddScoped<GuildSettingsRepository>();
}

static void AddWorkers(IServiceCollection services)
{
services.AddHostedService<CommandQueueWorker>();
services.AddHostedService<EventQueueWorker>();
services.AddHostedService<DiscordLoggerWorker>();
services.AddHostedService<BotWorker>();
}

static void AddChannels(IServiceCollection services)
{
const int channelSize = 1024;

services.AddSingleton(new CommandQueueChannel(Channel.CreateBounded<CommandRequest>(channelSize)));
services.AddSingleton(new EventQueueChannel(Channel.CreateBounded<INotification>(channelSize)));
services.AddSingleton(new DiscordLoggerChannel(Channel.CreateBounded<BaseDiscordLogItem>(channelSize)));
}
4 changes: 2 additions & 2 deletions src/Kattbot/Services/DiscordErrorLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ namespace Kattbot.Services;

public class DiscordErrorLogger
{
private readonly DiscordLogChannel _channel;
private readonly DiscordLoggerChannel _channel;
private readonly BotOptions _options;

public DiscordErrorLogger(IOptions<BotOptions> options, DiscordLogChannel channel)
public DiscordErrorLogger(IOptions<BotOptions> options, DiscordLoggerChannel channel)
{
_channel = channel;
_options = options.Value;
Expand Down
Loading
Loading