using System.Collections.Concurrent; using System.Threading.Tasks; using Discord; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Extensions; using Discord.WebSocket; using Microsoft.EntityFrameworkCore; using NadekoBot.Services; using NadekoBot.Services.Database.Models; using NadekoBot.Db; namespace NadekoBot.Modules.Utility.Services; public class CommandMapService : IInputTransformer, INService { private readonly IEmbedBuilderService _eb; public ConcurrentDictionary> AliasMaps { get; } = new ConcurrentDictionary>(); private readonly DbService _db; //commandmap public CommandMapService(DiscordSocketClient client, DbService db, IEmbedBuilderService eb) { _eb = eb; using (var uow = db.GetDbContext()) { var guildIds = client.Guilds.Select(x => x.Id).ToList(); var configs = uow.Set() .Include(gc => gc.CommandAliases) .Where(x => guildIds.Contains(x.GuildId)) .ToList(); AliasMaps = new(configs .ToDictionary( x => x.GuildId, x => new ConcurrentDictionary(x.CommandAliases .Distinct(new CommandAliasEqualityComparer()) .ToDictionary(ca => ca.Trigger, ca => ca.Mapping)))); _db = db; } } public int ClearAliases(ulong guildId) { AliasMaps.TryRemove(guildId, out _); int count; using (var uow = _db.GetDbContext()) { var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.CommandAliases)); count = gc.CommandAliases.Count; gc.CommandAliases.Clear(); uow.SaveChanges(); } return count; } public async Task TransformInput(IGuild guild, IMessageChannel channel, IUser user, string input) { await Task.Yield(); if (guild is null || string.IsNullOrWhiteSpace(input)) return input; if (guild != null) { if (AliasMaps.TryGetValue(guild.Id, out var maps)) { var keys = maps.Keys .OrderByDescending(x => x.Length); foreach (var k in keys) { string newInput; if (input.StartsWith(k + " ", StringComparison.InvariantCultureIgnoreCase)) newInput = maps[k] + input.Substring(k.Length, input.Length - k.Length); else if (input.Equals(k, StringComparison.InvariantCultureIgnoreCase)) newInput = maps[k]; else continue; try { var toDelete = await channel.SendConfirmAsync(_eb, $"{input} => {newInput}").ConfigureAwait(false); var _ = Task.Run(async () => { await Task.Delay(1500).ConfigureAwait(false); await toDelete.DeleteAsync(new() { RetryMode = RetryMode.AlwaysRetry }).ConfigureAwait(false); }); } catch { } return newInput; } } } return input; } } public class CommandAliasEqualityComparer : IEqualityComparer { public bool Equals(CommandAlias x, CommandAlias y) => x.Trigger == y.Trigger; public int GetHashCode(CommandAlias obj) => obj.Trigger.GetHashCode(StringComparison.InvariantCulture); }