From c0ce22a6b7fc2f0d33bc934fb066d89ce8761a7c Mon Sep 17 00:00:00 2001 From: Kwoth Date: Thu, 6 Jan 2022 22:53:59 +0100 Subject: [PATCH] .greetdm staggering to avoid ratelimits during raids --- .../Administration/ServerGreetCommands.cs | 3 +- .../Services/GreetSettingsService.cs | 63 ++++++++++++++----- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/ServerGreetCommands.cs b/src/NadekoBot/Modules/Administration/ServerGreetCommands.cs index 173ca4e85..b8d942f3f 100644 --- a/src/NadekoBot/Modules/Administration/ServerGreetCommands.cs +++ b/src/NadekoBot/Modules/Administration/ServerGreetCommands.cs @@ -258,8 +258,7 @@ namespace NadekoBot.Modules.Administration { user = user ?? (IGuildUser) ctx.User; - var channel = await user.GetOrCreateDMChannelAsync(); - var success = await _service.GreetDmTest(channel, user); + var success = await _service.GreetDmTest(user); if (success) await ctx.OkAsync(); else diff --git a/src/NadekoBot/Services/GreetSettingsService.cs b/src/NadekoBot/Services/GreetSettingsService.cs index 5c09e5bf4..5a367cb96 100644 --- a/src/NadekoBot/Services/GreetSettingsService.cs +++ b/src/NadekoBot/Services/GreetSettingsService.cs @@ -8,14 +8,16 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading.Channels; using System.Threading.Tasks; +using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Db; using NadekoBot.Modules.Administration; using Serilog; namespace NadekoBot.Services { - public class GreetSettingsService : INService + public class GreetSettingsService : INService, IReadyExecutor { private readonly DbService _db; @@ -51,6 +53,17 @@ namespace NadekoBot.Services _client.GuildMemberUpdated += ClientOnGuildMemberUpdated; } + + public async Task OnReadyAsync() + { + while (true) + { + var (conf, user, compl) = await _greetDmQueue.Reader.ReadAsync(); + var res = await GreetDmUserInternal(conf, user); + compl.TrySetResult(res); + await Task.Delay(2000); + } + } private Task ClientOnGuildMemberUpdated(SocketGuildUser oldUser, SocketGuildUser newUser) { @@ -240,16 +253,33 @@ namespace NadekoBot.Services } } - private async Task GreetDmUser(GreetSettings conf, IDMChannel channel, IGuildUser user) + private readonly Channel<(GreetSettings, IGuildUser, TaskCompletionSource)> _greetDmQueue = + Channel.CreateBounded<(GreetSettings, IGuildUser, TaskCompletionSource)>(new BoundedChannelOptions(60) + { + // The limit of 60 users should be only hit when there's a raid. In that case + // probably the best thing to do is to drop newest (raiding) users + FullMode = BoundedChannelFullMode.DropNewest + }); + + private async Task GreetDmUser(GreetSettings conf, IGuildUser user) + { + var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + await _greetDmQueue.Writer.WriteAsync((conf, user, completionSource)); + return await completionSource.Task; + } + + private async Task GreetDmUserInternal(GreetSettings conf, IGuildUser user) { - var rep = new ReplacementBuilder() - .WithDefault(user, channel, (SocketGuild)user.Guild, _client) - .Build(); - - var text = SmartText.CreateFrom(conf.DmGreetMessageText); - rep.Replace(text); try { + var rep = new ReplacementBuilder() + .WithUser(user) + .WithServer(_client, (SocketGuild)user.Guild) + .Build(); + + var text = SmartText.CreateFrom(conf.DmGreetMessageText); + text = rep.Replace(text); + if (text is SmartPlainText pt) { text = new SmartEmbedText() { PlainText = pt.Text }; @@ -259,8 +289,12 @@ namespace NadekoBot.Services { Text = $"This message was sent from {user.Guild} server.", IconUrl = user.Guild.IconUrl }; + + var ch = await user.GetOrCreateDMChannelAsync(); + if (ch is null) + return false; - await channel.SendAsync(text).ConfigureAwait(false); + await ch.SendAsync(text); } catch { @@ -311,12 +345,7 @@ namespace NadekoBot.Services if (conf.SendDmGreetMessage) { - var channel = await user.GetOrCreateDMChannelAsync().ConfigureAwait(false); - - if (channel != null) - { - await GreetDmUser(conf, channel, user); - } + await GreetDmUser(conf, user); } } catch @@ -487,10 +516,10 @@ namespace NadekoBot.Services return GreetUsers(conf, channel, user); } - public Task GreetDmTest(IDMChannel channel, IGuildUser user) + public Task GreetDmTest(IGuildUser user) { var conf = GetOrAddSettingsForGuild(user.GuildId); - return GreetDmUser(conf, channel, user); + return GreetDmUser(conf, user); } #endregion