using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord; using Discord.WebSocket; using NadekoBot.Core.Services; using NadekoBot.Core.Services.Database.Models; using NLog; namespace NadekoBot.Modules.Administration.Services { public class VcRoleService : INService { private readonly Logger _log; private readonly DbService _db; private readonly DiscordSocketClient _client; public ConcurrentDictionary> VcRoles { get; } public VcRoleService(DiscordSocketClient client, NadekoBot bot, DbService db) { _log = LogManager.GetCurrentClassLogger(); _db = db; _client = client; _client.UserVoiceStateUpdated += ClientOnUserVoiceStateUpdated; VcRoles = new ConcurrentDictionary>(); var missingRoles = new List(); foreach (var gconf in bot.AllGuildConfigs) { var g = _client.GetGuild(gconf.GuildId); if (g == null) continue; var infos = new ConcurrentDictionary(); VcRoles.TryAdd(gconf.GuildId, infos); foreach (var ri in gconf.VcRoleInfos) { var role = g.GetRole(ri.RoleId); if (role == null) { missingRoles.Add(ri); continue; } infos.TryAdd(ri.VoiceChannelId, role); } } if(missingRoles.Any()) using (var uow = _db.UnitOfWork) { _log.Warn($"Removing {missingRoles.Count} missing roles from {nameof(VcRoleService)}"); uow._context.RemoveRange(missingRoles); uow.Complete(); } } private Task ClientOnUserVoiceStateUpdated(SocketUser usr, SocketVoiceState oldState, SocketVoiceState newState) { var gusr = usr as SocketGuildUser; if (gusr == null) return Task.CompletedTask; var oldVc = oldState.VoiceChannel; var newVc = newState.VoiceChannel; var _ = Task.Run(async () => { try { if (oldVc != newVc) { ulong guildId; guildId = newVc?.Guild.Id ?? oldVc.Guild.Id; if (VcRoles.TryGetValue(guildId, out ConcurrentDictionary guildVcRoles)) { //remove old if (oldVc != null && guildVcRoles.TryGetValue(oldVc.Id, out IRole role)) { try { await gusr.RemoveRoleAsync(role).ConfigureAwait(false); } catch { try { await Task.Delay(500).ConfigureAwait(false); await gusr.RemoveRoleAsync(role).ConfigureAwait(false); } catch { } } } //add new if (newVc != null && guildVcRoles.TryGetValue(newVc.Id, out role)) { if (!gusr.Roles.Contains(role)) { await Task.Delay(500).ConfigureAwait(false); await gusr.AddRoleAsync(role).ConfigureAwait(false); } } } } } catch (Exception ex) { _log.Warn(ex); } }); return Task.CompletedTask; } } }