#nullable disable using Microsoft.EntityFrameworkCore; using EllieBot.Db.Models; using EllieBot.Modules.Administration._common.results; namespace EllieBot.Modules.Administration; public class AdministrationService : IEService { public ConcurrentHashSet<ulong> DeleteMessagesOnCommand { get; } public ConcurrentDictionary<ulong, bool> DeleteMessagesOnCommandChannels { get; } private readonly DbService _db; private readonly IReplacementService _repSvc; private readonly ILogCommandService _logService; private readonly IHttpClientFactory _httpFactory; public AdministrationService( IBot bot, CommandHandler cmdHandler, DbService db, IReplacementService repSvc, ILogCommandService logService, IHttpClientFactory factory) { _db = db; _repSvc = repSvc; _logService = logService; _httpFactory = factory; DeleteMessagesOnCommand = new(bot.AllGuildConfigs.Where(g => g.DeleteMessageOnCommand).Select(g => g.GuildId)); DeleteMessagesOnCommandChannels = new(bot.AllGuildConfigs.SelectMany(x => x.DelMsgOnCmdChannels) .ToDictionary(x => x.ChannelId, x => x.State) .ToConcurrent()); cmdHandler.CommandExecuted += DelMsgOnCmd_Handler; } public (bool DelMsgOnCmd, IEnumerable<DelMsgOnCmdChannel> channels) GetDelMsgOnCmdData(ulong guildId) { using var uow = _db.GetDbContext(); var conf = uow.GuildConfigsForId(guildId, set => set.Include(x => x.DelMsgOnCmdChannels)); return (conf.DeleteMessageOnCommand, conf.DelMsgOnCmdChannels); } private Task DelMsgOnCmd_Handler(IUserMessage msg, CommandInfo cmd) { if (msg.Channel is not ITextChannel channel) return Task.CompletedTask; _ = Task.Run(async () => { //wat ?! if (DeleteMessagesOnCommandChannels.TryGetValue(channel.Id, out var state)) { if (state && cmd.Name != "prune" && cmd.Name != "pick") { _logService.AddDeleteIgnore(msg.Id); try { await msg.DeleteAsync(); } catch { } } //if state is false, that means do not do it } else if (DeleteMessagesOnCommand.Contains(channel.Guild.Id) && cmd.Name != "prune" && cmd.Name != "pick") { _logService.AddDeleteIgnore(msg.Id); try { await msg.DeleteAsync(); } catch { } } }); return Task.CompletedTask; } public bool ToggleDeleteMessageOnCommand(ulong guildId) { bool enabled; using var uow = _db.GetDbContext(); var conf = uow.GuildConfigsForId(guildId, set => set); enabled = conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand; uow.SaveChanges(); return enabled; } public async Task SetDelMsgOnCmdState(ulong guildId, ulong chId, Administration.State newState) { await using (var uow = _db.GetDbContext()) { var conf = uow.GuildConfigsForId(guildId, set => set.Include(x => x.DelMsgOnCmdChannels)); var old = conf.DelMsgOnCmdChannels.FirstOrDefault(x => x.ChannelId == chId); if (newState == Administration.State.Inherit) { if (old is not null) { conf.DelMsgOnCmdChannels.Remove(old); uow.Remove(old); } } else { if (old is null) { old = new() { ChannelId = chId }; conf.DelMsgOnCmdChannels.Add(old); } old.State = newState == Administration.State.Enable; DeleteMessagesOnCommandChannels[chId] = newState == Administration.State.Enable; } await uow.SaveChangesAsync(); } if (newState == Administration.State.Disable) { } else if (newState == Administration.State.Enable) DeleteMessagesOnCommandChannels[chId] = true; else DeleteMessagesOnCommandChannels.TryRemove(chId, out _); } public async Task DeafenUsers(bool value, params IGuildUser[] users) { if (!users.Any()) return; foreach (var u in users) { try { await u.ModifyAsync(usr => usr.Deaf = value); } catch { // ignored } } } public async Task EditMessage( ICommandContext context, ITextChannel chanl, ulong messageId, string input) { var msg = await chanl.GetMessageAsync(messageId); if (msg is not IUserMessage umsg || msg.Author.Id != context.Client.CurrentUser.Id) return; var repCtx = new ReplacementContext(context); var text = SmartText.CreateFrom(input); text = await _repSvc.ReplaceAsync(text, repCtx); await umsg.EditAsync(text); } public async Task<SetServerBannerResult> SetServerBannerAsync(IGuild guild, string img) { if (!IsValidUri(img)) return SetServerBannerResult.InvalidURL; var uri = new Uri(img); using var http = _httpFactory.CreateClient(); using var sr = await http.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead); if (!sr.IsImage()) return SetServerBannerResult.InvalidFileType; if (sr.GetContentLength() > 8.Megabytes()) { return SetServerBannerResult.Toolarge; } await using var imageStream = await sr.Content.ReadAsStreamAsync(); await guild.ModifyAsync(x => x.Banner = new Image(imageStream)); return SetServerBannerResult.Success; } public async Task<SetServerIconResult> SetServerIconAsync(IGuild guild, string img) { if (!IsValidUri(img)) return SetServerIconResult.InvalidURL; var uri = new Uri(img); using var http = _httpFactory.CreateClient(); using var sr = await http.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead); if (!sr.IsImage()) return SetServerIconResult.InvalidFileType; await using var imageStream = await sr.Content.ReadAsStreamAsync(); await guild.ModifyAsync(x => x.Icon = new Image(imageStream)); return SetServerIconResult.Success; } private bool IsValidUri(string img) => !string.IsNullOrWhiteSpace(img) && Uri.IsWellFormedUriString(img, UriKind.Absolute); }