- .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)
This commit is contained in:
Kwoth
2022-01-03 06:52:41 +01:00
parent 21bef1a98e
commit ade880a6e6
5 changed files with 46 additions and 40 deletions

View File

@@ -41,7 +41,8 @@ public abstract record SmartText
smartEmbedText.NormalizeFields(); smartEmbedText.NormalizeFields();
if (!smartEmbedText.IsValid) return new SmartPlainText(input); if (!smartEmbedText.IsValid)
return new SmartPlainText(input);
return smartEmbedText; return smartEmbedText;
} }

View File

@@ -3,8 +3,6 @@ using Newtonsoft.Json;
namespace NadekoBot; namespace NadekoBot;
// todo test smarttextembedfooter and smarttextembedauthor
public class SmartTextEmbedFooter public class SmartTextEmbedFooter
{ {
public string Text { get; set; } public string Text { get; set; }

View File

@@ -3,10 +3,11 @@ using NadekoBot.Db;
namespace NadekoBot.Modules.Administration.Services; namespace NadekoBot.Modules.Administration.Services;
// todo if any activity... // todo dateonly timeonly
// todo new apis
public class GameVoiceChannelService : INService public class GameVoiceChannelService : INService
{ {
public ConcurrentHashSet<ulong> GameVoiceChannels { get; } = new(); public ConcurrentHashSet<ulong> GameVoiceChannels { get; }
private readonly DbService _db; private readonly DbService _db;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
@@ -16,30 +17,38 @@ public class GameVoiceChannelService : INService
_db = db; _db = db;
_client = client; _client = client;
GameVoiceChannels = new(bot.AllGuildConfigs.Where(gc => gc.GameVoiceChannel is not null) GameVoiceChannels = new(bot.AllGuildConfigs
.Select(gc => gc.GameVoiceChannel.Value)); .Where(gc => gc.GameVoiceChannel is not null)
.Select(gc => gc.GameVoiceChannel!.Value));
_client.UserVoiceStateUpdated += Client_UserVoiceStateUpdated; _client.UserVoiceStateUpdated += OnUserVoiceStateUpdated;
_client.GuildMemberUpdated += _client_GuildMemberUpdated; _client.PresenceUpdated += OnPresenceUpdate;
} }
private Task _client_GuildMemberUpdated(Cacheable<SocketGuildUser, ulong> before, SocketGuildUser after) private Task OnPresenceUpdate(SocketUser socketUser, SocketPresence before, SocketPresence after)
{ {
var _ = Task.Run(async () => var _ = Task.Run(async () =>
{ {
try try
{ {
//if the user is in the voice channel and that voice channel is gvc if (socketUser is not SocketGuildUser newUser)
var vc = after.VoiceChannel; return;
if (vc is null || !GameVoiceChannels.Contains(vc.Id) || !before.HasValue) // if the user is in the voice channel and that voice channel is gvc
if (newUser.VoiceChannel is not { } vc
|| !GameVoiceChannels.Contains(vc.Id))
return; return;
//if the activity has changed, and is a playing activity //if the activity has changed, and is a playi1ng activity
var oldActivity = before.Value.Activities.FirstOrDefault(); foreach (var activity in after.Activities)
var newActivity = after.Activities.FirstOrDefault(); {
if (oldActivity != newActivity && newActivity is { Type: ActivityType.Playing }) if (activity is { Type: ActivityType.Playing })
//trigger gvc {
await TriggerGvc(after, newActivity.Name); //trigger gvc
if (await TriggerGvc(newUser, activity.Name))
return;
}
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -72,7 +81,7 @@ public class GameVoiceChannelService : INService
return id; 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 () => var _ = Task.Run(async () =>
{ {
@@ -81,15 +90,17 @@ public class GameVoiceChannelService : INService
if (usr is not SocketGuildUser gUser) if (usr is not SocketGuildUser gUser)
return; return;
var game = gUser.Activities.FirstOrDefault()?.Name; if (newState.VoiceChannel is null)
if (oldState.VoiceChannel == newState.VoiceChannel || newState.VoiceChannel is null)
return; return;
if (!GameVoiceChannels.Contains(newState.VoiceChannel.Id) || string.IsNullOrWhiteSpace(game)) if (!GameVoiceChannels.Contains(newState.VoiceChannel.Id))
return; return;
await TriggerGvc(gUser, game); foreach (var game in gUser.Activities.Select(x => x.Name))
{
if (await TriggerGvc(gUser, game))
return;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -100,18 +111,19 @@ public class GameVoiceChannelService : INService
return Task.CompletedTask; return Task.CompletedTask;
} }
private async Task TriggerGvc(SocketGuildUser gUser, string game) private async Task<bool> TriggerGvc(SocketGuildUser gUser, string game)
{ {
if (string.IsNullOrWhiteSpace(game)) if (string.IsNullOrWhiteSpace(game))
return; return false;
game = game.TrimTo(50).ToLowerInvariant(); game = game.TrimTo(50).ToLowerInvariant();
var vch = gUser.Guild.VoiceChannels.FirstOrDefault(x => x.Name.ToLowerInvariant() == game); var vch = gUser.Guild.VoiceChannels.FirstOrDefault(x => x.Name.ToLowerInvariant() == game);
if (vch is null) if (vch is null)
return; return false;
await Task.Delay(1000); await Task.Delay(1000);
await gUser.ModifyAsync(gu => gu.Channel = vch); await gUser.ModifyAsync(gu => gu.Channel = vch);
return true;
} }
} }

View File

@@ -12,12 +12,8 @@ using YamlDotNet.Serialization.NamingConventions;
namespace NadekoBot.Modules.NadekoExpressions; 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 public sealed class NadekoExpressionsService : IEarlyBehavior, IReadyExecutor
{ {
private const string MENTION_PH = "%bot.mention%"; private const string MENTION_PH = "%bot.mention%";
private const string PREPEND_EXPORT = private const string PREPEND_EXPORT =

View File

@@ -8,11 +8,10 @@ namespace NadekoBot.Modules.Utility.Services;
public sealed class RepeaterService : IReadyExecutor, INService public sealed class RepeaterService : IReadyExecutor, INService
{ {
public const int MAX_REPEATERS = 5; private const int MAX_REPEATERS = 5;
private readonly DbService _db; private readonly DbService _db;
private readonly IBotCredentials _creds; private readonly IBotCredentials _creds;
private readonly IEmbedBuilderService _eb;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly LinkedList<RunningRepeater> _repeaterQueue; private readonly LinkedList<RunningRepeater> _repeaterQueue;
private readonly ConcurrentHashSet<int> _noRedundant; private readonly ConcurrentHashSet<int> _noRedundant;
@@ -22,18 +21,16 @@ public sealed class RepeaterService : IReadyExecutor, INService
public RepeaterService( public RepeaterService(
DiscordSocketClient client, DiscordSocketClient client,
DbService db, DbService db,
IBotCredentials creds, IBotCredentials creds)
IEmbedBuilderService eb)
{ {
_db = db; _db = db;
_creds = creds; _creds = creds;
_eb = eb;
_client = client; _client = client;
var uow = _db.GetDbContext(); var uow = _db.GetDbContext();
var shardRepeaters = uow.Set<Repeater>() var shardRepeaters = uow.Set<Repeater>()
.FromSqlInterpolated($@"select * from repeaters .Where(x => ((int)(x.GuildId / Math.Pow(2, 22)) % _creds.TotalShards)
where ((guildid >> 22) % {_creds.TotalShards}) == {_client.ShardId};") == _client.ShardId)
.AsNoTracking() .AsNoTracking()
.ToList(); .ToList();
@@ -51,6 +48,7 @@ where ((guildid >> 22) % {_creds.TotalShards}) == {_client.ShardId};")
private async Task RunRepeatersLoop() private async Task RunRepeatersLoop()
{ {
while (true) while (true)
{
try try
{ {
// calculate timeout for the first item // 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); Log.Error(ex, "Critical error in repeater queue: {ErrorMessage}", ex.Message);
await Task.Delay(5000); await Task.Delay(5000);
} }
}
} }
private async Task HandlePostExecute(RunningRepeater rep) private async Task HandlePostExecute(RunningRepeater rep)