using System; using System.Collections.Concurrent; using System.Linq; using System.Threading.Tasks; using Discord.WebSocket; using NadekoBot.Core.Services; using NLog; using Discord; namespace NadekoBot.Modules.Administration.Services { public class AutoAssignRoleService : INService { private readonly Logger _log; private readonly DiscordSocketClient _client; private readonly DbService _db; //guildid/roleid public ConcurrentDictionary AutoAssignedRoles { get; } public BlockingCollection<(IGuildUser, ulong)> AutoAssignQueue { get; } = new BlockingCollection<(IGuildUser, ulong)>(); public AutoAssignRoleService(DiscordSocketClient client, NadekoBot bot, DbService db) { _log = LogManager.GetCurrentClassLogger(); _client = client; _db = db; AutoAssignedRoles = new ConcurrentDictionary( bot.AllGuildConfigs .Where(x => x.AutoAssignRoleId != 0) .ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId)); var _queueRunner = Task.Run(async () => { while (true) { var (user, roleId) = AutoAssignQueue.Take(); try { var role = user.Guild.Roles.FirstOrDefault(r => r.Id == roleId); if (role != null) await user.AddRoleAsync(role).ConfigureAwait(false); else { _log.Warn($"Disabled 'Auto assign role' feature on {0} server the role doesn't exist.", roleId); DisableAar(user.GuildId); } } catch (Discord.Net.HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.Forbidden) { _log.Warn($"Disabled 'Auto assign role' feature on {0} server because I don't have role management permissions.", roleId); DisableAar(user.GuildId); } catch (Exception ex) { _log.Warn(ex); } } }); _client.UserJoined += (user) => { if (AutoAssignedRoles.TryGetValue(user.Guild.Id, out ulong roleId) && roleId != 0) { AutoAssignQueue.Add((user, roleId)); } return Task.CompletedTask; }; } public void EnableAar(ulong guildId, ulong roleId) { using (var uow = _db.UnitOfWork) { var gc = uow.GuildConfigs.For(guildId, set => set); gc.AutoAssignRoleId = roleId; uow.Complete(); } AutoAssignedRoles.AddOrUpdate(guildId, roleId, delegate { return roleId; }); } public void DisableAar(ulong guildId) { using (var uow = _db.UnitOfWork) { var gc = uow.GuildConfigs.For(guildId, set => set); gc.AutoAssignRoleId = 0; uow.Complete(); } AutoAssignedRoles.TryRemove(guildId, out _); } } }