Merge branch 'v5' of toastielab.dev:Emotions-stuff/elliebot into v5

This commit is contained in:
Toastie (DCS Team) 2024-09-09 13:25:05 +12:00
commit 2d0d2ff877
No known key found for this signature in database
16 changed files with 93 additions and 93 deletions

View file

@ -6,6 +6,9 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
### Added ### Added
- Added `.leaveunkeptservers` which will make the bot leave all servers on all shards whose owners didn't run `.keep` command.
- This is a dangerous and irreversible command, don't use it. Meant for use on the public bot.
### Changed ### Changed
- `.quote` commands cleaned up and improved - `.quote` commands cleaned up and improved
@ -21,6 +24,8 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
- Fixed `.xpcurrew` breaking xp gain if user gains 0 xp from being in a voice channel - Fixed `.xpcurrew` breaking xp gain if user gains 0 xp from being in a voice channel
- Fixed a bug in `.gatari` command - Fixed a bug in `.gatari` command
- Fixed some waifu related strings
- Fixed `.quoteshow` and `.quoteid` commands
## [5.1.7] - 09.08.2024 ## [5.1.7] - 09.08.2024

View file

@ -69,9 +69,9 @@
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.Seq" Version="7.0.1" /> <PackageReference Include="Serilog.Sinks.Seq" Version="7.0.1" />
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17" /> <PackageReference Include="SixLabors.Fonts" Version="2.0.4" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.9" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4" />
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009" /> <PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009" />
<PackageReference Include="StackExchange.Redis" Version="2.8.0" /> <PackageReference Include="StackExchange.Redis" Version="2.8.0" />
<PackageReference Include="YamlDotNet" Version="15.1.4" /> <PackageReference Include="YamlDotNet" Version="15.1.4" />

View file

@ -37,6 +37,8 @@ public class AutoPublishService : IExecNoCommand, IReadyExecutor, IEService
}); });
} }
// todo GUILDS
public async Task OnReadyAsync() public async Task OnReadyAsync()
{ {
var creds = _creds.GetCreds(); var creds = _creds.GetCreds();

View file

@ -62,10 +62,10 @@ public partial class Administration
if (!response) if (!response)
return; return;
for (var i = startShardId; i < _creds.GetCreds().TotalShards; i++) for (var shardId = startShardId; shardId < _creds.GetCreds().TotalShards; shardId++)
{ {
await _svc.LeaveUnkeptServers(i); await _svc.StartLeavingUnkeptServers(shardId);
await Task.Delay(2250 * 1000); await Task.Delay(3000 * 1000);
} }
await ctx.OkAsync(); await ctx.OkAsync();

View file

@ -237,7 +237,7 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService
return await table.CountAsync(); return await table.CountAsync();
} }
public async Task LeaveUnkeptServers(int shardId) public async Task StartLeavingUnkeptServers(int shardId)
=> await _pubSub.Pub(_keepTriggerKey, shardId); => await _pubSub.Pub(_keepTriggerKey, shardId);
private ValueTask OnKeepReport(KeepReport report) private ValueTask OnKeepReport(KeepReport report)

View file

@ -5,5 +5,5 @@ public interface ICleanupService
Task<KeepResult?> DeleteMissingGuildDataAsync(); Task<KeepResult?> DeleteMissingGuildDataAsync();
Task<bool> KeepGuild(ulong guildId); Task<bool> KeepGuild(ulong guildId);
Task<int> GetKeptGuildCount(); Task<int> GetKeptGuildCount();
Task LeaveUnkeptServers(int shardId); Task StartLeavingUnkeptServers(int shardId);
} }

View file

@ -111,13 +111,17 @@ public class PlantPickService : IEService, IExecNoCommand
{ {
var curImg = await _images.GetCurrencyImageAsync(); var curImg = await _images.GetCurrencyImageAsync();
if (curImg is null)
return (new MemoryStream(), null);
if (string.IsNullOrWhiteSpace(pass)) if (string.IsNullOrWhiteSpace(pass))
{ {
// determine the extension // determine the extension
using var load = _ = Image.Load(curImg, out var format); using var load = Image.Load(curImg);
var format = load.Metadata.DecodedImageFormat;
// return the image // return the image
return (curImg.ToStream(), format.FileExtensions.FirstOrDefault() ?? "png"); return (curImg.ToStream(), format?.FileExtensions.FirstOrDefault() ?? "png");
} }
// get the image stream and extension // get the image stream and extension
@ -134,16 +138,17 @@ public class PlantPickService : IEService, IExecNoCommand
{ {
// draw lower, it looks better // draw lower, it looks better
pass = pass.TrimTo(10, true).ToLowerInvariant(); pass = pass.TrimTo(10, true).ToLowerInvariant();
using var img = Image.Load<Rgba32>(curImg, out var format); using var img = Image.Load<Rgba32>(curImg);
// choose font size based on the image height, so that it's visible // choose font size based on the image height, so that it's visible
var font = _fonts.NotoSans.CreateFont(img.Height / 12.0f, FontStyle.Bold); var font = _fonts.NotoSans.CreateFont(img.Height / 12.0f, FontStyle.Bold);
img.Mutate(x => img.Mutate(x =>
{ {
// measure the size of the text to be drawing // measure the size of the text to be drawing
var size = TextMeasurer.Measure(pass, new TextOptions(font) var size = TextMeasurer.MeasureSize(pass,
{ new TextOptions(font)
Origin = new PointF(0, 0) {
}); Origin = new PointF(0, 0)
});
// fill the background with black, add 5 pixels on each side to make it look better // fill the background with black, add 5 pixels on each side to make it look better
x.FillPolygon(Color.ParseHex("00000080"), x.FillPolygon(Color.ParseHex("00000080"),
@ -156,6 +161,7 @@ public class PlantPickService : IEService, IExecNoCommand
x.DrawText(pass, font, Color.White, new(0, 0)); x.DrawText(pass, font, Color.White, new(0, 0));
}); });
// return image as a stream for easy sending // return image as a stream for easy sending
var format = img.Metadata.DecodedImageFormat;
return (img.ToStream(format), format.FileExtensions.FirstOrDefault() ?? "png"); return (img.ToStream(format), format.FileExtensions.FirstOrDefault() ?? "png");
} }
@ -256,7 +262,8 @@ public class PlantPickService : IEService, IExecNoCommand
pass = pass?.Trim().TrimTo(10, true).ToUpperInvariant(); pass = pass?.Trim().TrimTo(10, true).ToUpperInvariant();
// gets all plants in this channel with the same password // gets all plants in this channel with the same password
var entries = uow.Set<PlantedCurrency>().AsQueryable() var entries = uow.Set<PlantedCurrency>()
.AsQueryable()
.Where(x => x.ChannelId == ch.Id && pass == x.Password) .Where(x => x.ChannelId == ch.Id && pass == x.Password)
.ToList(); .ToList();
// sum how much currency that is, and get all of the message ids (so that i can delete them) // sum how much currency that is, and get all of the message ids (so that i can delete them)
@ -368,15 +375,16 @@ public class PlantPickService : IEService, IExecNoCommand
string pass) string pass)
{ {
await using var uow = _db.GetDbContext(); await using var uow = _db.GetDbContext();
uow.Set<PlantedCurrency>().Add(new() uow.Set<PlantedCurrency>()
{ .Add(new()
Amount = amount, {
GuildId = gid, Amount = amount,
ChannelId = cid, GuildId = gid,
Password = pass, ChannelId = cid,
UserId = uid, Password = pass,
MessageId = mid UserId = uid,
}); MessageId = mid
});
await uow.SaveChangesAsync(); await uow.SaveChangesAsync();
} }
} }

View file

@ -172,13 +172,13 @@ public partial class Gambling
} }
var slotBg = await _images.GetSlotBgAsync(); var slotBg = await _images.GetSlotBgAsync();
var bgImage = Image.Load<Rgba32>(slotBg, out _); var bgImage = Image.Load<Rgba32>(slotBg);
var numbers = new int[3]; var numbers = new int[3];
result.Rolls.CopyTo(numbers, 0); result.Rolls.CopyTo(numbers, 0);
Color fontColor = Config.Slots.CurrencyFontColor; Color fontColor = Config.Slots.CurrencyFontColor;
bgImage.Mutate(x => x.DrawText(new TextOptions(_fonts.DottyFont.CreateFont(65)) bgImage.Mutate<Rgba32>(x => x.DrawText(new RichTextOptions(_fonts.DottyFont.CreateFont(65))
{ {
HorizontalAlignment = HorizontalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
@ -190,7 +190,7 @@ public partial class Gambling
var bottomFont = _fonts.DottyFont.CreateFont(50); var bottomFont = _fonts.DottyFont.CreateFont(50);
bgImage.Mutate(x => x.DrawText(new TextOptions(bottomFont) bgImage.Mutate(x => x.DrawText(new RichTextOptions(bottomFont)
{ {
HorizontalAlignment = HorizontalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,

View file

@ -90,7 +90,7 @@ public class CryptoService : IEService
img.Mutate(x => img.Mutate(x =>
{ {
x.DrawLines(color, 2, points); x.DrawLine(color, 2, points);
}); });
return img; return img;

View file

@ -94,7 +94,7 @@ public sealed class ImagesharpStockChartDrawingService : IStockChartDrawingServi
=> image.Mutate(ctx => => image.Mutate(ctx =>
{ {
foreach (var data in drawData) foreach (var data in drawData)
ctx.DrawLines(data.IsGreen ctx.DrawLine(data.IsGreen
? _greenBrush ? _greenBrush
: _redBrush, : _redBrush,
1, 1,
@ -128,7 +128,7 @@ public sealed class ImagesharpStockChartDrawingService : IStockChartDrawingServi
{ {
// draw guides // draw guides
foreach (var y in lines) foreach (var y in lines)
ctx.DrawLines(_lineGuideColor, 1, new PointF(0, y), new PointF(WIDTH, y)); ctx.DrawLine(_lineGuideColor, 1, new PointF(0, y), new PointF(WIDTH, y));
// // draw min and max price on the chart // // draw min and max price on the chart
// ctx.DrawText(min.ToString(CultureInfo.InvariantCulture), // ctx.DrawText(min.ToString(CultureInfo.InvariantCulture),
@ -156,7 +156,7 @@ public sealed class ImagesharpStockChartDrawingService : IStockChartDrawingServi
image.Mutate(ctx => image.Mutate(ctx =>
{ {
ctx.DrawLines(_sparklineColor, 2, points); ctx.DrawLine(_sparklineColor, 2, points);
}); });
return Task.FromResult<ImageData?>(new("png", image.ToStream())); return Task.FromResult<ImageData?>(new("png", image.ToStream()));
@ -177,7 +177,7 @@ public sealed class ImagesharpStockChartDrawingService : IStockChartDrawingServi
var points = GetSparklinePointsInternal(series); var points = GetSparklinePointsInternal(series);
image.Mutate(ctx => image.Mutate(ctx =>
{ {
ctx.DrawLines(Color.ParseHex("00FFFFAA"), 1, points); ctx.DrawLine(Color.ParseHex("00FFFFAA"), 1, points);
}); });
return Task.FromResult<ImageData?>(new("png", image.ToStream())); return Task.FromResult<ImageData?>(new("png", image.ToStream()));

View file

@ -29,7 +29,7 @@ public interface IQuoteService
Task<IReadOnlyCollection<Quote>> GetGuildQuotesAsync(ulong guildId); Task<IReadOnlyCollection<Quote>> GetGuildQuotesAsync(ulong guildId);
Task<int> RemoveAllByKeyword(ulong guildId, string keyword); Task<int> RemoveAllByKeyword(ulong guildId, string keyword);
Task<Quote?> GetQuoteByIdAsync(ulong guildId, kwum quoteId); Task<Quote?> GetQuoteByIdAsync(ulong guildId, int quoteId);
Task<Quote> AddQuoteAsync( Task<Quote> AddQuoteAsync(
ulong guildId, ulong guildId,

View file

@ -121,7 +121,7 @@ public sealed class QuoteService : IQuoteService, IEService
return count; return count;
} }
public async Task<Quote?> GetQuoteByIdAsync(ulong guildId, kwum quoteId) public async Task<Quote?> GetQuoteByIdAsync(ulong guildId, int quoteId)
{ {
await using var uow = _db.GetDbContext(); await using var uow = _db.GetDbContext();

View file

@ -994,23 +994,23 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
throw new ArgumentNullException(nameof(bgBytes)); throw new ArgumentNullException(nameof(bgBytes));
} }
var outlinePen = new Pen(Color.Black, 1f); var outlinePen = new SolidPen(Color.Black, 1f);
using var img = Image.Load<Rgba32>(bgBytes, out var imageFormat); using var img = Image.Load<Rgba32>(bgBytes);
if (template.User.Name.Show) if (template.User.Name.Show)
{ {
var fontSize = (int)(template.User.Name.FontSize * 0.9); var fontSize = (int)(template.User.Name.FontSize * 0.9);
var username = stats.User.ToString(); var username = stats.User.ToString();
var usernameFont = _fonts.NotoSans.CreateFont(fontSize, FontStyle.Bold); var usernameFont = _fonts.NotoSans.CreateFont(fontSize, FontStyle.Bold);
var size = TextMeasurer.Measure($"@{username}", new(usernameFont)); var size = TextMeasurer.MeasureSize($"@{username}", new(usernameFont));
var scale = 400f / size.Width; var scale = 400f / size.Width;
if (scale < 1) if (scale < 1)
usernameFont = _fonts.NotoSans.CreateFont(template.User.Name.FontSize * scale, FontStyle.Bold); usernameFont = _fonts.NotoSans.CreateFont(template.User.Name.FontSize * scale, FontStyle.Bold);
img.Mutate(x => img.Mutate(x =>
{ {
x.DrawText(new TextOptions(usernameFont) x.DrawText(new RichTextOptions(usernameFont)
{ {
HorizontalAlignment = HorizontalAlignment.Left, HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
@ -1031,7 +1031,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
var clubFont = _fonts.NotoSans.CreateFont(template.Club.Name.FontSize, FontStyle.Regular); var clubFont = _fonts.NotoSans.CreateFont(template.Club.Name.FontSize, FontStyle.Regular);
img.Mutate(x => x.DrawText(new TextOptions(clubFont) img.Mutate(x => x.DrawText(new RichTextOptions(clubFont)
{ {
HorizontalAlignment = HorizontalAlignment.Right, HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Top, VerticalAlignment = VerticalAlignment.Top,
@ -1051,7 +1051,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
int maxSize) int maxSize)
{ {
var font = fontFamily.CreateFont(fontSize, style); var font = fontFamily.CreateFont(fontSize, style);
var size = TextMeasurer.Measure(text, new(font)); var size = TextMeasurer.MeasureSize(text, new(font));
var scale = maxSize / size.Width; var scale = maxSize / size.Width;
if (scale < 1) if (scale < 1)
font = fontFamily.CreateFont(fontSize * scale, style); font = fontFamily.CreateFont(fontSize * scale, style);
@ -1114,7 +1114,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
if (template.User.Xp.Global.Show) if (template.User.Xp.Global.Show)
{ {
img.Mutate(x => x.DrawText( img.Mutate(x => x.DrawText(
new TextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Global.FontSize, FontStyle.Bold)) new RichTextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Global.FontSize, FontStyle.Bold))
{ {
HorizontalAlignment = HorizontalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
@ -1128,7 +1128,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
if (template.User.Xp.Guild.Show) if (template.User.Xp.Guild.Show)
{ {
img.Mutate(x => x.DrawText( img.Mutate(x => x.DrawText(
new TextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Guild.FontSize, FontStyle.Bold)) new RichTextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Guild.FontSize, FontStyle.Bold))
{ {
HorizontalAlignment = HorizontalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
@ -1152,7 +1152,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
new(awX, awY))); new(awX, awY)));
} }
var rankPen = new Pen(Color.White, 1); var rankPen = new SolidPen(Color.White, 1);
//ranking //ranking
if (template.User.GlobalRank.Show) if (template.User.GlobalRank.Show)
{ {
@ -1166,7 +1166,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
68); 68);
img.Mutate(x => x.DrawText( img.Mutate(x => x.DrawText(
new TextOptions(globalRankFont) new RichTextOptions(globalRankFont)
{ {
Origin = new(template.User.GlobalRank.Pos.X, template.User.GlobalRank.Pos.Y) Origin = new(template.User.GlobalRank.Pos.X, template.User.GlobalRank.Pos.Y)
}, },
@ -1188,7 +1188,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
43); 43);
img.Mutate(x => x.DrawText( img.Mutate(x => x.DrawText(
new TextOptions(guildRankFont) new RichTextOptions(guildRankFont)
{ {
Origin = new(template.User.GuildRank.Pos.X, template.User.GuildRank.Pos.Y) Origin = new(template.User.GuildRank.Pos.X, template.User.GuildRank.Pos.Y)
}, },
@ -1231,7 +1231,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
} }
using var toDraw = Image.Load(data); using var toDraw = Image.Load(data);
if (toDraw.Size() != new Size(template.User.Icon.Size.X, template.User.Icon.Size.Y)) if (toDraw.Size != new Size(template.User.Icon.Size.X, template.User.Icon.Size.Y))
toDraw.Mutate(x => x.Resize(template.User.Icon.Size.X, template.User.Icon.Size.Y)); toDraw.Mutate(x => x.Resize(template.User.Icon.Size.X, template.User.Icon.Size.Y));
img.Mutate(x => x.DrawImage(toDraw, img.Mutate(x => x.DrawImage(toDraw,
@ -1257,6 +1257,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
if (outputSize.X != img.Width || outputSize.Y != img.Height) if (outputSize.X != img.Width || outputSize.Y != img.Height)
img.Mutate(x => x.Resize(template.OutputSize.X, template.OutputSize.Y)); img.Mutate(x => x.Resize(template.OutputSize.X, template.OutputSize.Y));
var imageFormat = img.Metadata.DecodedImageFormat;
var output = ((Stream)await img.ToStreamAsync(imageFormat), imageFormat); var output = ((Stream)await img.ToStreamAsync(imageFormat), imageFormat);
return output; return output;
@ -1393,7 +1394,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
} }
using var toDraw = Image.Load(data); using var toDraw = Image.Load(data);
if (toDraw.Size() != new Size(template.Club.Icon.Size.X, template.Club.Icon.Size.Y)) if (toDraw.Size != new Size(template.Club.Icon.Size.X, template.Club.Icon.Size.Y))
toDraw.Mutate(x => x.Resize(template.Club.Icon.Size.X, template.Club.Icon.Size.Y)); toDraw.Mutate(x => x.Resize(template.Club.Icon.Size.X, template.Club.Icon.Size.Y));
img.Mutate(x => x.DrawImage( img.Mutate(x => x.DrawImage(

View file

@ -7,7 +7,7 @@ namespace EllieBot.Common.JsonConverters;
public class Rgba32Converter : JsonConverter<Rgba32> public class Rgba32Converter : JsonConverter<Rgba32>
{ {
public override Rgba32 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override Rgba32 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> Rgba32.ParseHex(reader.GetString()); => Rgba32.ParseHex(reader.GetString()!);
public override void Write(Utf8JsonWriter writer, Rgba32 value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, Rgba32 value, JsonSerializerOptions options)
=> writer.WriteStringValue(value.ToHex()); => writer.WriteStringValue(value.ToHex());

View file

@ -55,76 +55,60 @@ public sealed class StatsService : IStatsService, IReadyExecutor, IEService
_client.ChannelCreated += c => _client.ChannelCreated += c =>
{ {
_ = Task.Run(() => if (c is IVoiceChannel)
{ Interlocked.Increment(ref voiceChannels);
if (c is ITextChannel) else if (c is ITextChannel)
Interlocked.Increment(ref textChannels); Interlocked.Increment(ref textChannels);
else if (c is IVoiceChannel)
Interlocked.Increment(ref voiceChannels);
});
return Task.CompletedTask; return Task.CompletedTask;
}; };
_client.ChannelDestroyed += c => _client.ChannelDestroyed += c =>
{ {
_ = Task.Run(() => if (c is IVoiceChannel)
{ Interlocked.Decrement(ref voiceChannels);
if (c is ITextChannel) else if (c is ITextChannel)
Interlocked.Decrement(ref textChannels); Interlocked.Decrement(ref textChannels);
else if (c is IVoiceChannel)
Interlocked.Decrement(ref voiceChannels);
});
return Task.CompletedTask; return Task.CompletedTask;
}; };
_client.GuildAvailable += g => _client.GuildAvailable += g =>
{ {
_ = Task.Run(() => var tc = g.Channels.Count(cx => cx is ITextChannel and not IVoiceChannel);
{ var vc = g.Channels.Count(cx => cx is IVoiceChannel);
var tc = g.Channels.Count(cx => cx is ITextChannel); Interlocked.Add(ref textChannels, tc);
var vc = g.Channels.Count - tc; Interlocked.Add(ref voiceChannels, vc);
Interlocked.Add(ref textChannels, tc);
Interlocked.Add(ref voiceChannels, vc);
});
return Task.CompletedTask; return Task.CompletedTask;
}; };
_client.JoinedGuild += g => _client.JoinedGuild += g =>
{ {
_ = Task.Run(() => var tc = g.Channels.Count(cx => cx is ITextChannel and not IVoiceChannel);
{ var vc = g.Channels.Count(cx => cx is IVoiceChannel);
var tc = g.Channels.Count(cx => cx is ITextChannel); Interlocked.Add(ref textChannels, tc);
var vc = g.Channels.Count - tc; Interlocked.Add(ref voiceChannels, vc);
Interlocked.Add(ref textChannels, tc);
Interlocked.Add(ref voiceChannels, vc);
});
return Task.CompletedTask; return Task.CompletedTask;
}; };
_client.GuildUnavailable += g => _client.GuildUnavailable += g =>
{ {
_ = Task.Run(() => var tc = g.Channels.Count(cx => cx is ITextChannel and not IVoiceChannel);
{ var vc = g.Channels.Count(cx => cx is IVoiceChannel);
var tc = g.Channels.Count(cx => cx is ITextChannel); Interlocked.Add(ref textChannels, -tc);
var vc = g.Channels.Count - tc; Interlocked.Add(ref voiceChannels, -vc);
Interlocked.Add(ref textChannels, -tc);
Interlocked.Add(ref voiceChannels, -vc);
});
return Task.CompletedTask; return Task.CompletedTask;
}; };
_client.LeftGuild += g => _client.LeftGuild += g =>
{ {
_ = Task.Run(() => var tc = g.Channels.Count(cx => cx is ITextChannel and not IVoiceChannel);
{ var vc = g.Channels.Count(cx => cx is IVoiceChannel);
var tc = g.Channels.Count(cx => cx is ITextChannel); Interlocked.Add(ref textChannels, -tc);
var vc = g.Channels.Count - tc; Interlocked.Add(ref voiceChannels, -vc);
Interlocked.Add(ref textChannels, -tc);
Interlocked.Add(ref voiceChannels, -vc);
});
return Task.CompletedTask; return Task.CompletedTask;
}; };
@ -133,7 +117,7 @@ public sealed class StatsService : IStatsService, IReadyExecutor, IEService
private void InitializeChannelCount() private void InitializeChannelCount()
{ {
var guilds = _client.Guilds; var guilds = _client.Guilds;
textChannels = guilds.Sum(static g => g.Channels.Count(static cx => cx is ITextChannel)); textChannels = guilds.Sum(static g => g.Channels.Count(static cx => cx is ITextChannel and not IVoiceChannel));
voiceChannels = guilds.Sum(static g => g.Channels.Count(static cx => cx is IVoiceChannel)); voiceChannels = guilds.Sum(static g => g.Channels.Count(static cx => cx is IVoiceChannel));
} }

View file

@ -24,7 +24,7 @@ public static class Rgba32Extensions
using var frame = imgArray[i].Frames.CloneFrame(frameNumber % imgArray[i].Frames.Count); using var frame = imgArray[i].Frames.CloneFrame(frameNumber % imgArray[i].Frames.Count);
var offset = xOffset; var offset = xOffset;
imgFrame.Mutate(x => x.DrawImage(frame, new Point(offset, 0), new GraphicsOptions())); imgFrame.Mutate(x => x.DrawImage(frame, new Point(offset, 0), new GraphicsOptions()));
xOffset += imgArray[i].Bounds().Width; xOffset += imgArray[i].Bounds.Width;
} }
} }