#nullable disable using Microsoft.EntityFrameworkCore; using EllieBot.Db.Models; namespace EllieBot.Modules.Administration.Services; public class SelfAssignedRolesService : IEService { public enum AssignResult { Assigned, // successfully removed ErrNotAssignable, // not assignable (error) ErrAlreadyHave, // you already have that role (error) ErrNotPerms, // bot doesn't have perms (error) ErrLvlReq // you are not required level (error) } public enum RemoveResult { Removed, // successfully removed ErrNotAssignable, // not assignable (error) ErrNotHave, // you don't have a role you want to remove (error) ErrNotPerms // bot doesn't have perms (error) } private readonly DbService _db; public SelfAssignedRolesService(DbService db) => _db = db; public bool AddNew(ulong guildId, IRole role, int group) { using var uow = _db.GetDbContext(); var roles = uow.Set<SelfAssignedRole>().GetFromGuild(guildId); if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.Guild.Id)) return false; uow.Set<SelfAssignedRole>().Add(new() { Group = group, RoleId = role.Id, GuildId = role.Guild.Id }); uow.SaveChanges(); return true; } public bool ToggleAdSarm(ulong guildId) { bool newval; using var uow = _db.GetDbContext(); var config = uow.GuildConfigsForId(guildId, set => set); newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages; uow.SaveChanges(); return newval; } public async Task<(AssignResult Result, bool AutoDelete, object extra)> Assign(IGuildUser guildUser, IRole role) { LevelStats userLevelData; await using (var uow = _db.GetDbContext()) { var stats = uow.GetOrCreateUserXpStats(guildUser.Guild.Id, guildUser.Id); userLevelData = new(stats.Xp + stats.AwardedXp); } var (autoDelete, exclusive, roles) = GetAdAndRoles(guildUser.Guild.Id); var theRoleYouWant = roles.FirstOrDefault(r => r.RoleId == role.Id); if (theRoleYouWant is null) return (AssignResult.ErrNotAssignable, autoDelete, null); if (theRoleYouWant.LevelRequirement > userLevelData.Level) return (AssignResult.ErrLvlReq, autoDelete, theRoleYouWant.LevelRequirement); if (guildUser.RoleIds.Contains(role.Id)) return (AssignResult.ErrAlreadyHave, autoDelete, null); var roleIds = roles.Where(x => x.Group == theRoleYouWant.Group).Select(x => x.RoleId).ToArray(); if (exclusive) { var sameRoles = guildUser.RoleIds.Where(r => roleIds.Contains(r)); foreach (var roleId in sameRoles) { var sameRole = guildUser.Guild.GetRole(roleId); if (sameRole is not null) { try { await guildUser.RemoveRoleAsync(sameRole); await Task.Delay(300); } catch { // ignored } } } } try { await guildUser.AddRoleAsync(role); } catch (Exception ex) { return (AssignResult.ErrNotPerms, autoDelete, ex); } return (AssignResult.Assigned, autoDelete, null); } public async Task<bool> SetNameAsync(ulong guildId, int group, string name) { var set = false; await using var uow = _db.GetDbContext(); var gc = uow.GuildConfigsForId(guildId, y => y.Include(x => x.SelfAssignableRoleGroupNames)); var toUpdate = gc.SelfAssignableRoleGroupNames.FirstOrDefault(x => x.Number == group); if (string.IsNullOrWhiteSpace(name)) { if (toUpdate is not null) gc.SelfAssignableRoleGroupNames.Remove(toUpdate); } else if (toUpdate is null) { gc.SelfAssignableRoleGroupNames.Add(new() { Name = name, Number = group }); set = true; } else { toUpdate.Name = name; set = true; } await uow.SaveChangesAsync(); return set; } public async Task<(RemoveResult Result, bool AutoDelete)> Remove(IGuildUser guildUser, IRole role) { var (autoDelete, _, roles) = GetAdAndRoles(guildUser.Guild.Id); if (roles.FirstOrDefault(r => r.RoleId == role.Id) is null) return (RemoveResult.ErrNotAssignable, autoDelete); if (!guildUser.RoleIds.Contains(role.Id)) return (RemoveResult.ErrNotHave, autoDelete); try { await guildUser.RemoveRoleAsync(role); } catch (Exception) { return (RemoveResult.ErrNotPerms, autoDelete); } return (RemoveResult.Removed, autoDelete); } public bool RemoveSar(ulong guildId, ulong roleId) { bool success; using var uow = _db.GetDbContext(); success = uow.Set<SelfAssignedRole>().DeleteByGuildAndRoleId(guildId, roleId); uow.SaveChanges(); return success; } public (bool AutoDelete, bool Exclusive, IReadOnlyCollection<SelfAssignedRole>) GetAdAndRoles(ulong guildId) { using var uow = _db.GetDbContext(); var gc = uow.GuildConfigsForId(guildId, set => set); var autoDelete = gc.AutoDeleteSelfAssignedRoleMessages; var exclusive = gc.ExclusiveSelfAssignedRoles; var roles = uow.Set<SelfAssignedRole>().GetFromGuild(guildId); return (autoDelete, exclusive, roles); } public bool SetLevelReq(ulong guildId, IRole role, int level) { using var uow = _db.GetDbContext(); var roles = uow.Set<SelfAssignedRole>().GetFromGuild(guildId); var sar = roles.FirstOrDefault(x => x.RoleId == role.Id); if (sar is not null) { sar.LevelRequirement = level; uow.SaveChanges(); } else return false; return true; } public bool ToggleEsar(ulong guildId) { bool areExclusive; using var uow = _db.GetDbContext(); var config = uow.GuildConfigsForId(guildId, set => set); areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles; uow.SaveChanges(); return areExclusive; } public (bool Exclusive, IReadOnlyCollection<(SelfAssignedRole Model, IRole Role)> Roles, IDictionary<int, string> GroupNames ) GetRoles(IGuild guild) { var exclusive = false; IReadOnlyCollection<(SelfAssignedRole Model, IRole Role)> roles; IDictionary<int, string> groupNames; using (var uow = _db.GetDbContext()) { var gc = uow.GuildConfigsForId(guild.Id, set => set.Include(x => x.SelfAssignableRoleGroupNames)); exclusive = gc.ExclusiveSelfAssignedRoles; groupNames = gc.SelfAssignableRoleGroupNames.ToDictionary(x => x.Number, x => x.Name); var roleModels = uow.Set<SelfAssignedRole>().GetFromGuild(guild.Id); roles = roleModels.Select(x => (Model: x, Role: guild.GetRole(x.RoleId))) .ToList(); uow.Set<SelfAssignedRole>().RemoveRange(roles.Where(x => x.Role is null).Select(x => x.Model).ToArray()); uow.SaveChanges(); } return (exclusive, roles.Where(x => x.Role is not null).ToList(), groupNames); } }