Skip to content

Commit

Permalink
make discord message logger queue messages and send multiple at once
Browse files Browse the repository at this point in the history
  • Loading branch information
loukylor committed Dec 31, 2024
1 parent a1ddd77 commit 9d59e9c
Showing 1 changed file with 63 additions and 4 deletions.
67 changes: 63 additions & 4 deletions TrickFireDiscordBot/Services/Discord/DiscordMessageLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using DSharpPlus.Exceptions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Text;
using System.Threading.Channels;

namespace TrickFireDiscordBot.Services.Discord;
Expand All @@ -13,6 +14,7 @@ public class DiscordMessageLogger(
DiscordService discordService) : BackgroundService, IAutoRegisteredService, ILogger
{
private readonly Channel<string> queue = Channel.CreateBounded<string>(100);
private readonly StringBuilder sb = new();

private DiscordChannel? channel;

Expand All @@ -28,7 +30,18 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
return;
}

queue.Writer.TryWrite($"[{eventId.Id,2}: {logLevel,-12}] {formatter(state, exception)}");
string message = $"[{eventId.Id,2}: {logLevel,-12}] {formatter(state, exception)}";
if (message.Length < 2000)
{
queue.Writer.TryWrite(message);
return;
}

// Split log message into 2000 char chunks
for (int i = 0; i < message.Length; i += 2000)
{
queue.Writer.TryWrite(message[i..(i + 2000)]);
}
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
Expand All @@ -37,16 +50,62 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
string message = await queue.Reader.ReadAsync(stoppingToken);
// Dequeue all items from queue
// cts will be cancelled after 3 seconds
using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
cts.CancelAfter(3000);
while (!cts.IsCancellationRequested)
{
// Wait for item to be available
try
{
await queue.Reader.WaitToReadAsync(cts.Token);
}
catch (OperationCanceledException)
{
break;
}

// Peek the item
if (!queue.Reader.TryPeek(out string? message) || message == null)
{
continue;
}

// Make sure it fits within our message, if it doesn't then
// send message
if (sb.Length + 1 + message.Length > 2000)
{
// Ensure the timeout is finished
try
{
await Task.Delay(-1, cts.Token);
}
catch (OperationCanceledException) { }
break;
}

// Add item to our message
sb.AppendLine(message);
queue.Reader.TryRead(out message);
}

// Keep waiting if no messages were enqueued
if (sb.Length == 0)
{
continue;
}

// Make sure channel is not null
DiscordChannel? channel = await GetChannel();
if (channel is null)
{
continue;
}

await channel.SendMessageAsync(message);
await Task.Delay(3000, stoppingToken);
// Send message
await channel.SendMessageAsync(sb.ToString());
sb.Clear();
}
catch (Exception ex)
{
Expand Down

0 comments on commit 9d59e9c

Please sign in to comment.