#nullable disable using Microsoft.EntityFrameworkCore; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Db.Models; namespace NadekoBot.Modules.Utility.Services; public class AliasService : IInputTransformer, INService { public ConcurrentDictionary> AliasMaps { get; } = new(); private readonly DbService _db; private readonly IMessageSenderService _sender; public AliasService( DiscordSocketClient client, DbService db, IMessageSenderService sender) { _sender = sender; 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.DistinctBy(ca => ca.Trigger) .ToDictionary(ca => ca.Trigger, ca => ca.Mapping), StringComparer.OrdinalIgnoreCase))); _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) { if (guild is null || string.IsNullOrWhiteSpace(input)) return null; if (AliasMaps.TryGetValue(guild.Id, out var maps)) { string newInput = null; foreach (var (k, v) in maps) { if (string.Equals(input, k, StringComparison.OrdinalIgnoreCase)) { newInput = v; } else if (input.StartsWith(k + ' ', StringComparison.OrdinalIgnoreCase)) { if (v.Contains("%target%")) newInput = v.Replace("%target%", input[k.Length..]); else newInput = v + ' ' + input[k.Length..]; } if (newInput is not null) { try { var toDelete = await _sender.Response(channel) .Confirm($"{input} => {newInput}") .SendAsync(); toDelete.DeleteAfter(1.5f); } catch { // ignored } return newInput; } } return null; } return null; } }