From ade880a6e6c7b3e60b883582987a6dd49dd05c89 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Mon, 3 Jan 2022 06:52:41 +0100 Subject: [PATCH] - .gvc should now properly trigger when a user is already in a gvc and changes his activity - .gvc should now properly detect multiple activities - Rewrote repeat raw query bitshift to linqtodb query with division (thx kotz) --- src/NadekoBot/Common/SmartText/SmartText.cs | 3 +- .../Common/SmartText/SmartTextEmbedFooter.cs | 2 - .../GameVoiceChannelService.cs | 64 +++++++++++-------- .../NadekoExpressionsService.cs | 4 -- .../Utility/Repeater/RepeaterService.cs | 13 ++-- 5 files changed, 46 insertions(+), 40 deletions(-) diff --git a/src/NadekoBot/Common/SmartText/SmartText.cs b/src/NadekoBot/Common/SmartText/SmartText.cs index 991656c6b..41edf5d04 100644 --- a/src/NadekoBot/Common/SmartText/SmartText.cs +++ b/src/NadekoBot/Common/SmartText/SmartText.cs @@ -41,7 +41,8 @@ public abstract record SmartText smartEmbedText.NormalizeFields(); - if (!smartEmbedText.IsValid) return new SmartPlainText(input); + if (!smartEmbedText.IsValid) + return new SmartPlainText(input); return smartEmbedText; } diff --git a/src/NadekoBot/Common/SmartText/SmartTextEmbedFooter.cs b/src/NadekoBot/Common/SmartText/SmartTextEmbedFooter.cs index 374b8d3d1..19489881f 100644 --- a/src/NadekoBot/Common/SmartText/SmartTextEmbedFooter.cs +++ b/src/NadekoBot/Common/SmartText/SmartTextEmbedFooter.cs @@ -3,8 +3,6 @@ using Newtonsoft.Json; namespace NadekoBot; -// todo test smarttextembedfooter and smarttextembedauthor - public class SmartTextEmbedFooter { public string Text { get; set; } diff --git a/src/NadekoBot/Modules/Administration/GameVoiceChannel/GameVoiceChannelService.cs b/src/NadekoBot/Modules/Administration/GameVoiceChannel/GameVoiceChannelService.cs index 9dc41bd4b..b87924fb6 100644 --- a/src/NadekoBot/Modules/Administration/GameVoiceChannel/GameVoiceChannelService.cs +++ b/src/NadekoBot/Modules/Administration/GameVoiceChannel/GameVoiceChannelService.cs @@ -3,10 +3,11 @@ using NadekoBot.Db; namespace NadekoBot.Modules.Administration.Services; -// todo if any activity... +// todo dateonly timeonly +// todo new apis public class GameVoiceChannelService : INService { - public ConcurrentHashSet GameVoiceChannels { get; } = new(); + public ConcurrentHashSet GameVoiceChannels { get; } private readonly DbService _db; private readonly DiscordSocketClient _client; @@ -16,30 +17,38 @@ public class GameVoiceChannelService : INService _db = db; _client = client; - GameVoiceChannels = new(bot.AllGuildConfigs.Where(gc => gc.GameVoiceChannel is not null) - .Select(gc => gc.GameVoiceChannel.Value)); + GameVoiceChannels = new(bot.AllGuildConfigs + .Where(gc => gc.GameVoiceChannel is not null) + .Select(gc => gc.GameVoiceChannel!.Value)); - _client.UserVoiceStateUpdated += Client_UserVoiceStateUpdated; - _client.GuildMemberUpdated += _client_GuildMemberUpdated; + _client.UserVoiceStateUpdated += OnUserVoiceStateUpdated; + _client.PresenceUpdated += OnPresenceUpdate; } - private Task _client_GuildMemberUpdated(Cacheable before, SocketGuildUser after) + private Task OnPresenceUpdate(SocketUser socketUser, SocketPresence before, SocketPresence after) { var _ = Task.Run(async () => { try { - //if the user is in the voice channel and that voice channel is gvc - var vc = after.VoiceChannel; - if (vc is null || !GameVoiceChannels.Contains(vc.Id) || !before.HasValue) + if (socketUser is not SocketGuildUser newUser) return; + // if the user is in the voice channel and that voice channel is gvc - //if the activity has changed, and is a playing activity - var oldActivity = before.Value.Activities.FirstOrDefault(); - var newActivity = after.Activities.FirstOrDefault(); - if (oldActivity != newActivity && newActivity is { Type: ActivityType.Playing }) - //trigger gvc - await TriggerGvc(after, newActivity.Name); + if (newUser.VoiceChannel is not { } vc + || !GameVoiceChannels.Contains(vc.Id)) + return; + + //if the activity has changed, and is a playi1ng activity + foreach (var activity in after.Activities) + { + if (activity is { Type: ActivityType.Playing }) + { + //trigger gvc + if (await TriggerGvc(newUser, activity.Name)) + return; + } + } } catch (Exception ex) { @@ -72,7 +81,7 @@ public class GameVoiceChannelService : INService return id; } - private Task Client_UserVoiceStateUpdated(SocketUser usr, SocketVoiceState oldState, SocketVoiceState newState) + private Task OnUserVoiceStateUpdated(SocketUser usr, SocketVoiceState oldState, SocketVoiceState newState) { var _ = Task.Run(async () => { @@ -81,15 +90,17 @@ public class GameVoiceChannelService : INService if (usr is not SocketGuildUser gUser) return; - var game = gUser.Activities.FirstOrDefault()?.Name; - - if (oldState.VoiceChannel == newState.VoiceChannel || newState.VoiceChannel is null) + if (newState.VoiceChannel is null) return; - if (!GameVoiceChannels.Contains(newState.VoiceChannel.Id) || string.IsNullOrWhiteSpace(game)) + if (!GameVoiceChannels.Contains(newState.VoiceChannel.Id)) return; - - await TriggerGvc(gUser, game); + + foreach (var game in gUser.Activities.Select(x => x.Name)) + { + if (await TriggerGvc(gUser, game)) + return; + } } catch (Exception ex) { @@ -100,18 +111,19 @@ public class GameVoiceChannelService : INService return Task.CompletedTask; } - private async Task TriggerGvc(SocketGuildUser gUser, string game) + private async Task TriggerGvc(SocketGuildUser gUser, string game) { if (string.IsNullOrWhiteSpace(game)) - return; + return false; game = game.TrimTo(50).ToLowerInvariant(); var vch = gUser.Guild.VoiceChannels.FirstOrDefault(x => x.Name.ToLowerInvariant() == game); if (vch is null) - return; + return false; await Task.Delay(1000); await gUser.ModifyAsync(gu => gu.Channel = vch); + return true; } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs b/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs index 8cd85dac7..b677370b3 100644 --- a/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs +++ b/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs @@ -12,12 +12,8 @@ using YamlDotNet.Serialization.NamingConventions; namespace NadekoBot.Modules.NadekoExpressions; -// todo recheck whether ACTUALEXPRESSIONS perm works -// todo run db migration and rename ACTUALCUSTOMREACTIONS to ACTUALEXPRESSIONS - public sealed class NadekoExpressionsService : IEarlyBehavior, IReadyExecutor { - private const string MENTION_PH = "%bot.mention%"; private const string PREPEND_EXPORT = diff --git a/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs b/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs index 4250bf378..73fdd8679 100644 --- a/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs +++ b/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs @@ -8,11 +8,10 @@ namespace NadekoBot.Modules.Utility.Services; public sealed class RepeaterService : IReadyExecutor, INService { - public const int MAX_REPEATERS = 5; + private const int MAX_REPEATERS = 5; private readonly DbService _db; private readonly IBotCredentials _creds; - private readonly IEmbedBuilderService _eb; private readonly DiscordSocketClient _client; private readonly LinkedList _repeaterQueue; private readonly ConcurrentHashSet _noRedundant; @@ -22,18 +21,16 @@ public sealed class RepeaterService : IReadyExecutor, INService public RepeaterService( DiscordSocketClient client, DbService db, - IBotCredentials creds, - IEmbedBuilderService eb) + IBotCredentials creds) { _db = db; _creds = creds; - _eb = eb; _client = client; var uow = _db.GetDbContext(); var shardRepeaters = uow.Set() - .FromSqlInterpolated($@"select * from repeaters -where ((guildid >> 22) % {_creds.TotalShards}) == {_client.ShardId};") + .Where(x => ((int)(x.GuildId / Math.Pow(2, 22)) % _creds.TotalShards) + == _client.ShardId) .AsNoTracking() .ToList(); @@ -51,6 +48,7 @@ where ((guildid >> 22) % {_creds.TotalShards}) == {_client.ShardId};") private async Task RunRepeatersLoop() { while (true) + { try { // calculate timeout for the first item @@ -92,6 +90,7 @@ where ((guildid >> 22) % {_creds.TotalShards}) == {_client.ShardId};") Log.Error(ex, "Critical error in repeater queue: {ErrorMessage}", ex.Message); await Task.Delay(5000); } + } } private async Task HandlePostExecute(RunningRepeater rep)