public CustomReactionsService(PermissionService perms, NadekoStrings strings, DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, IUnitOfWork uow) { _log = LogManager.GetCurrentClassLogger(); _client = client; _perms = perms; _cmd = cmd; _bc = bc; _strings = strings; var items = uow.CustomReactions.GetAll().ToList(); GuildReactions = new ConcurrentDictionary <ulong, CustomReaction[]>(items.Where(cr => cr.GuildId != null && cr.GuildId != 0).GroupBy(cr => cr.GuildId.Value).ToDictionary(cr => cr.Key, cr => cr.ToArray())); GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray(); }
public SelfService(DiscordSocketClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db, IBotConfigProvider bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds, IDataCache cache, IImagesService imgs) { _redis = cache.Redis; _bot = bot; _cmdHandler = cmdHandler; _db = db; _log = LogManager.GetCurrentClassLogger(); _localization = localization; _strings = strings; _client = client; _creds = creds; _bc = bc; _imgs = imgs; var sub = _redis.GetSubscriber(); sub.Subscribe(_creds.RedisKey() + "_reload_images", delegate { _imgs.Reload(); }, CommandFlags.FireAndForget); Task.Run(async() => { await bot.Ready.Task.ConfigureAwait(false); foreach (var cmd in bc.BotConfig.StartupCommands) { var prefix = _cmdHandler.GetPrefix(cmd.GuildId); //if someone already has .die as their startup command, ignore it if (cmd.CommandText.StartsWith(prefix + "die")) { continue; } await cmdHandler.ExecuteExternal(cmd.GuildId, cmd.ChannelId, cmd.CommandText); await Task.Delay(400).ConfigureAwait(false); } }); Task.Run(async() => { await bot.Ready.Task.ConfigureAwait(false); await Task.Delay(5000); if (client.ShardId == 0) { LoadOwnerChannels(); } }); }
public ChatterBotService(DiscordSocketClient client, PermissionService perms, IEnumerable <GuildConfig> gcs, CommandHandler cmd, NadekoStrings strings, IBotCredentials creds) { _client = client; _log = LogManager.GetCurrentClassLogger(); _perms = perms; _cmd = cmd; _strings = strings; _creds = creds; ChatterBotGuilds = new ConcurrentDictionary <ulong, Lazy <IChatterBotSession> >( gcs.Where(gc => gc.CleverbotEnabled) .ToDictionary(gc => gc.GuildId, gc => new Lazy <IChatterBotSession>(() => CreateSession(), true))); }
public CustomReactionsService(PermissionService perms, DbService db, NadekoStrings strings, DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, IDataCache cache, GlobalPermissionService gperm, NadekoBot bot) { _log = LogManager.GetCurrentClassLogger(); _db = db; _client = client; _perms = perms; _cmd = cmd; _bc = bc; _strings = strings; _cache = cache; _gperm = gperm; var sub = _cache.Redis.GetSubscriber(); sub.Subscribe(_client.CurrentUser.Id + "_crs.reload", (ch, msg) => { ReloadInternal(bot.GetCurrentGuildConfigs()); }, StackExchange.Redis.CommandFlags.FireAndForget); sub.Subscribe(_client.CurrentUser.Id + "_gcr.added", (ch, msg) => { var cr = JsonConvert.DeserializeObject <CustomReaction>(msg); _globalReactions.TryAdd(cr.Id, cr); }, StackExchange.Redis.CommandFlags.FireAndForget); sub.Subscribe(_client.CurrentUser.Id + "_gcr.deleted", (ch, msg) => { var id = int.Parse(msg); _globalReactions.TryRemove(id, out _); }, StackExchange.Redis.CommandFlags.FireAndForget); sub.Subscribe(_client.CurrentUser.Id + "_gcr.edited", (ch, msg) => { var obj = new { Id = 0, Res = "", Ad = false, Dm = false, Ca = false, Re = "" }; obj = JsonConvert.DeserializeAnonymousType(msg, obj); if (_globalReactions.TryGetValue(obj.Id, out var gcr)) { gcr.Response = obj.Res; gcr.AutoDeleteTrigger = obj.Ad; gcr.DmResponse = obj.Dm; gcr.ContainsAnywhere = obj.Ca; gcr.Reactions = obj.Re; } }, StackExchange.Redis.CommandFlags.FireAndForget); ReloadInternal(bot.AllGuildConfigs); bot.JoinedGuild += Bot_JoinedGuild; _client.LeftGuild += _client_LeftGuild; }
public TicTacToe(NadekoStrings strings, DiscordSocketClient client, ITextChannel channel, IGuildUser firstUser) { _channel = channel; _strings = strings; _client = client; _users = new[] { firstUser, null }; _state = new int?[, ] { { null, null, null }, { null, null, null }, { null, null, null }, }; _phase = Phase.Starting; _moveLock = new SemaphoreSlim(1, 1); }
public TriviaGame(NadekoStrings strings, DiscordSocketClient client, IBotConfigProvider bc, IDataCache cache, ICurrencyService cs, IGuild guild, ITextChannel channel, TriviaOptions options) { _log = LogManager.GetCurrentClassLogger(); _cache = cache; _questionPool = new TriviaQuestionPool(_cache); _strings = strings; _client = client; _bc = bc; _cs = cs; _options = options; Guild = guild; Channel = channel; }
public TriviaGame(NadekoStrings strings, DiscordSocketClient client, IBotConfigProvider bc, CurrencyService cs, IGuild guild, ITextChannel channel, bool showHints, int winReq, bool isPokemon) { _log = LogManager.GetCurrentClassLogger(); _strings = strings; _client = client; _bc = bc; _cs = cs; ShowHints = showHints; Guild = guild; Channel = channel; WinRequirement = winReq; IsPokemon = isPokemon; }
public PermissionService(DiscordSocketClient client, DbService db, CommandHandler cmd, NadekoStrings strings) { _db = db; _cmd = cmd; _strings = strings; using (var uow = _db.UnitOfWork) { foreach (var x in uow.GuildConfigs.Permissionsv2ForAll(client.Guilds.ToArray().Select(x => (long)x.Id).ToList())) { Cache.TryAdd(x.GuildId, new PermissionCache { Verbose = x.VerbosePermissions, PermRole = x.PermissionRole, Permissions = new PermissionsCollection <Permissionv2>(x.Permissions) }); } } }
public MusicService(DiscordSocketClient client, IGoogleApiService google, NadekoStrings strings, ILocalization localization, DbService db, SoundCloudApiService sc, IEnumerable <GuildConfig> gcs) { _client = client; _google = google; _strings = strings; _localization = localization; _db = db; _sc = sc; _log = LogManager.GetCurrentClassLogger(); try { Directory.Delete(MusicDataPath, true); } catch { } _defaultVolumes = new ConcurrentDictionary <ulong, float>(gcs.ToDictionary(x => x.GuildId, x => x.DefaultMusicVolume)); Directory.CreateDirectory(MusicDataPath); //_t = new Timer(_ => _log.Info(MusicPlayers.Count(x => x.Value.Current.Current != null)), null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5)); }
public PollService(DiscordSocketClient client, NadekoStrings strings, DbService db, NadekoStrings strs, IUnitOfWork uow) { _log = LogManager.GetCurrentClassLogger(); _client = client; _strings = strings; _db = db; _strs = strs; ActivePolls = uow.Polls.GetAllPolls() .ToDictionary(x => x.GuildId, x => { var pr = new PollRunner(db, x); pr.OnVoted += Pr_OnVoted; return(pr); }) .ToConcurrent(); }
public PlantPickService(DbService db, CommandHandler cmd, NadekoBot bot, NadekoStrings strings, IDataCache cache, FontProvider fonts, IBotConfigProvider bc, ICurrencyService cs, CommandHandler cmdHandler, DiscordSocketClient client) { _db = db; _strings = strings; _images = cache.LocalImages; _fonts = fonts; _bc = bc; _log = LogManager.GetCurrentClassLogger(); _cs = cs; _cmdHandler = cmdHandler; _rng = new NadekoRandom(); _client = client; cmd.OnMessageNoTrigger += PotentialFlowerGeneration; _generationChannels = new ConcurrentHashSet <ulong>(bot .AllGuildConfigs .SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId))); }
public SelfService(DiscordSocketClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db, IBotConfigProvider bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds) { _bot = bot; _cmdHandler = cmdHandler; _db = db; _log = LogManager.GetCurrentClassLogger(); _localization = localization; _strings = strings; _client = client; _creds = creds; _bc = bc; var _ = Task.Run(async() => { await bot.Ready.Task.ConfigureAwait(false); foreach (var cmd in bc.BotConfig.StartupCommands) { await cmdHandler.ExecuteExternal(cmd.GuildId, cmd.ChannelId, cmd.CommandText); await Task.Delay(400).ConfigureAwait(false); } }); var ___ = Task.Run(async() => { await bot.Ready.Task.ConfigureAwait(false); await Task.Delay(5000); _client.Guilds.SelectMany(g => g.Users); if (client.ShardId == 0) { LoadOwnerChannels(); } }); }
public GamesService(CommandHandler cmd, IBotConfigProvider bc, NadekoBot bot, NadekoStrings strings, IDataCache data, CommandHandler cmdHandler, CurrencyService cs) { _bc = bc; _cmd = cmd; _strings = strings; _images = data.LocalImages; _cmdHandler = cmdHandler; _log = LogManager.GetCurrentClassLogger(); _rng = new NadekoRandom(); _cs = cs; //8ball EightBallResponses = _bc.BotConfig.EightBallResponses.Select(ebr => ebr.Text).ToImmutableArray(); //girl ratings _t = new Timer((_) => { GirlRatings.Clear(); }, null, TimeSpan.FromDays(1), TimeSpan.FromDays(1)); //plantpick _cmd.OnMessageNoTrigger += PotentialFlowerGeneration; GenerationChannels = new ConcurrentHashSet <ulong>(bot .AllGuildConfigs .SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId))); try { TypingArticles = JsonConvert.DeserializeObject <List <TypingArticle> >(File.ReadAllText(TypingArticlesPath)); } catch (Exception ex) { _log.Warn("Error while loading typing articles {0}", ex.ToString()); TypingArticles = new List <TypingArticle>(); } }
public MusicService(DiscordSocketClient client, IGoogleApiService google, NadekoStrings strings, ILocalization localization, DbService db, SoundCloudApiService sc, IBotCredentials creds, NadekoBot bot) { _client = client; _google = google; _strings = strings; _localization = localization; _db = db; _sc = sc; _creds = creds; _log = LogManager.GetCurrentClassLogger(); _client.LeftGuild += _client_LeftGuild; try { Directory.Delete(MusicDataPath, true); } catch { } _defaultVolumes = new ConcurrentDictionary <ulong, float>( bot.AllGuildConfigs .ToDictionary(x => x.GuildId, x => x.DefaultMusicVolume)); Directory.CreateDirectory(MusicDataPath); }
public GamesService(CommandHandler cmd, IBotConfigProvider bc, NadekoBot bot, NadekoStrings strings, IDataCache data, CommandHandler cmdHandler, ICurrencyService cs, FontProvider fonts, IHttpClientFactory httpFactory) { _bc = bc; _cmd = cmd; _strings = strings; _images = data.LocalImages; _cmdHandler = cmdHandler; _log = LogManager.GetCurrentClassLogger(); _rng = new NadekoRandom(); _cs = cs; _fonts = fonts; _httpFactory = httpFactory; Ratings = new AsyncLazy <RatingTexts>(GetRatingTexts); //8ball EightBallResponses = _bc.BotConfig.EightBallResponses.Select(ebr => ebr.Text).ToImmutableArray(); //girl ratings _t = new Timer((_) => { GirlRatings.Clear(); }, null, TimeSpan.FromDays(1), TimeSpan.FromDays(1)); try { TypingArticles = JsonConvert.DeserializeObject <List <TypingArticle> >(File.ReadAllText(TypingArticlesPath)); } catch (Exception ex) { _log.Warn("Error while loading typing articles {0}", ex.ToString()); TypingArticles = new List <TypingArticle>(); } }
public HelpService(IBotConfigProvider bc, CommandHandler ch, NadekoStrings strings) { _bc = bc; _ch = ch; _strings = strings; }
public XpService(DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, NadekoBot bot, DbService db, NadekoStrings strings, IDataCache cache, FontProvider fonts, IBotCredentials creds, ICurrencyService cs, IHttpClientFactory http) { _db = db; _cmd = cmd; _bc = bc; _images = cache.LocalImages; _log = LogManager.GetCurrentClassLogger(); _strings = strings; _cache = cache; _fonts = fonts; _creds = creds; _cs = cs; _httpFactory = http; InternalReloadXpTemplate(); if (client.ShardId == 0) { var sub = _cache.Redis.GetSubscriber(); sub.Subscribe(_creds.RedisKey() + "_reload_xp_template", (ch, val) => InternalReloadXpTemplate()); } //load settings var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null); _excludedChannels = allGuildConfigs .ToDictionary( x => x.GuildId, x => new ConcurrentHashSet <ulong>(x.XpSettings .ExclusionList .Where(ex => ex.ItemType == ExcludedItemType.Channel) .Select(ex => ex.ItemId) .Distinct())) .ToConcurrent(); _excludedRoles = allGuildConfigs .ToDictionary( x => x.GuildId, x => new ConcurrentHashSet <ulong>(x.XpSettings .ExclusionList .Where(ex => ex.ItemType == ExcludedItemType.Role) .Select(ex => ex.ItemId) .Distinct())) .ToConcurrent(); _excludedServers = new ConcurrentHashSet <ulong>( allGuildConfigs.Where(x => x.XpSettings.ServerExcluded) .Select(x => x.GuildId)); _cmd.OnMessageNoTrigger += _cmd_OnMessageNoTrigger; updateXpTask = Task.Run(async() => { while (true) { await Task.Delay(TimeSpan.FromSeconds(5)); try { var toNotify = new List <(IMessageChannel MessageChannel, IUser User, int Level, XpNotificationType NotifyType, NotifOf NotifOf)>(); var roleRewards = new Dictionary <ulong, List <XpRoleReward> >(); var curRewards = new Dictionary <ulong, List <XpCurrencyReward> >(); var toAddTo = new List <UserCacheItem>(); while (_addMessageXp.TryDequeue(out var usr)) { toAddTo.Add(usr); } var group = toAddTo.GroupBy(x => (GuildId: x.Guild.Id, x.User)); if (toAddTo.Count == 0) { continue; } using (var uow = _db.UnitOfWork) { foreach (var item in group) { var xp = item.Select(x => bc.BotConfig.XpPerMessage).Sum(); //1. Mass query discord users and userxpstats and get them from local dict //2. (better but much harder) Move everything to the database, and get old and new xp // amounts for every user (in order to give rewards) var usr = uow.Xp.GetOrCreateUser(item.Key.GuildId, item.Key.User.Id); var du = uow.DiscordUsers.GetOrCreate(item.Key.User); var globalXp = du.TotalXp; var oldGlobalLevelData = new LevelStats(globalXp); var newGlobalLevelData = new LevelStats(globalXp + xp); var oldGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp); usr.Xp += xp; du.TotalXp += xp; if (du.Club != null) { du.Club.Xp += xp; } var newGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp); if (oldGlobalLevelData.Level < newGlobalLevelData.Level) { du.LastLevelUp = DateTime.UtcNow; var first = item.First(); if (du.NotifyOnLevelUp != XpNotificationType.None) { toNotify.Add((first.Channel, first.User, newGlobalLevelData.Level, du.NotifyOnLevelUp, NotifOf.Global)); } } if (oldGuildLevelData.Level < newGuildLevelData.Level) { usr.LastLevelUp = DateTime.UtcNow; //send level up notification var first = item.First(); if (usr.NotifyOnLevelUp != XpNotificationType.None) { toNotify.Add((first.Channel, first.User, newGuildLevelData.Level, usr.NotifyOnLevelUp, NotifOf.Server)); } //give role if (!roleRewards.TryGetValue(usr.GuildId, out var rrews)) { rrews = uow.GuildConfigs.XpSettingsFor(usr.GuildId).RoleRewards.ToList(); roleRewards.Add(usr.GuildId, rrews); } if (!curRewards.TryGetValue(usr.GuildId, out var crews)) { crews = uow.GuildConfigs.XpSettingsFor(usr.GuildId).CurrencyRewards.ToList(); curRewards.Add(usr.GuildId, crews); } var rrew = rrews.FirstOrDefault(x => x.Level == newGuildLevelData.Level); if (rrew != null) { var role = first.User.Guild.GetRole(rrew.RoleId); if (role != null) { var __ = first.User.AddRoleAsync(role); } } //get currency reward for this level var crew = crews.FirstOrDefault(x => x.Level == newGuildLevelData.Level); if (crew != null) { //give the user the reward if it exists await _cs.AddAsync(item.Key.User.Id, "Level-up Reward", crew.Amount); } } } uow.Complete(); } await Task.WhenAll(toNotify.Select(async x => { if (x.NotifOf == NotifOf.Server) { if (x.NotifyType == XpNotificationType.Dm) { var chan = await x.User.GetOrCreateDMChannelAsync(); if (chan != null) { await chan.SendConfirmAsync(_strings.GetText("level_up_dm", (x.MessageChannel as ITextChannel)?.GuildId, "xp", x.User.Mention, Format.Bold(x.Level.ToString()), Format.Bold((x.MessageChannel as ITextChannel)?.Guild.ToString() ?? "-"))); } } else // channel { await x.MessageChannel.SendConfirmAsync(_strings.GetText("level_up_channel", (x.MessageChannel as ITextChannel)?.GuildId, "xp", x.User.Mention, Format.Bold(x.Level.ToString()))); } } else { IMessageChannel chan; if (x.NotifyType == XpNotificationType.Dm) { chan = await x.User.GetOrCreateDMChannelAsync(); } else // channel { chan = x.MessageChannel; } await chan.SendConfirmAsync(_strings.GetText("level_up_global", (x.MessageChannel as ITextChannel)?.GuildId, "xp", x.User.Mention, Format.Bold(x.Level.ToString()))); } })); } catch (Exception ex) { _log.Warn(ex); } } }); }
public VplusTService(DiscordSocketClient client, IEnumerable <GuildConfig> gcs, NadekoStrings strings, DbService db) { _client = client; _strings = strings; _db = db; _log = LogManager.GetCurrentClassLogger(); VoicePlusTextCache = new ConcurrentHashSet <ulong>(gcs.Where(g => g.VoicePlusTextEnabled).Select(g => g.GuildId)); _client.UserVoiceStateUpdated += UserUpdatedEventHandler; }
public XpService(DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, NadekoBot bot, DbService db, NadekoStrings strings, IDataCache cache, FontProvider fonts, IBotCredentials creds, ICurrencyService cs, IHttpClientFactory http) { _db = db; _cmd = cmd; _bc = bc; _images = cache.LocalImages; _log = LogManager.GetCurrentClassLogger(); _strings = strings; _cache = cache; _fonts = fonts; _creds = creds; _cs = cs; _httpFactory = http; _client = client; InternalReloadXpTemplate(); if (client.ShardId == 0) { var sub = _cache.Redis.GetSubscriber(); sub.Subscribe(_creds.RedisKey() + "_reload_xp_template", (ch, val) => InternalReloadXpTemplate()); } //load settings var allGuildConfigs = bot.AllGuildConfigs .Where(x => x.XpSettings != null) .ToList(); _excludedChannels = allGuildConfigs .ToDictionary( x => x.GuildId, x => new ConcurrentHashSet <ulong>(x.XpSettings .ExclusionList .Where(ex => ex.ItemType == ExcludedItemType.Channel) .Select(ex => ex.ItemId) .Distinct())) .ToConcurrent(); _excludedRoles = allGuildConfigs .ToDictionary( x => x.GuildId, x => new ConcurrentHashSet <ulong>(x.XpSettings .ExclusionList .Where(ex => ex.ItemType == ExcludedItemType.Role) .Select(ex => ex.ItemId) .Distinct())) .ToConcurrent(); _excludedServers = new ConcurrentHashSet <ulong>( allGuildConfigs.Where(x => x.XpSettings.ServerExcluded) .Select(x => x.GuildId)); _cmd.OnMessageNoTrigger += _cmd_OnMessageNoTrigger; #if !GLOBAL_NADEKO _client.UserVoiceStateUpdated += _client_OnUserVoiceStateUpdated; // Scan guilds on startup. _client.GuildAvailable += _client_OnGuildAvailable; foreach (var guild in _client.Guilds) { _client_OnGuildAvailable(guild); } #endif updateXpTask = Task.Run(UpdateLoop); }
public SelfService(DiscordSocketClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db, IBotConfigProvider bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds, IDataCache cache) { _redis = cache.Redis; _bot = bot; _cmdHandler = cmdHandler; _db = db; _log = LogManager.GetCurrentClassLogger(); _localization = localization; _strings = strings; _client = client; _creds = creds; _bc = bc; _cache = cache; _imgs = cache.LocalImages; if (_client.ShardId == 0) { _updateTimer = new Timer(async _ => { try { var ch = ownerChannels?.Values.FirstOrDefault(); if (ch == null) // no owner channels { return; } var cfo = _bc.BotConfig.CheckForUpdates; if (cfo == UpdateCheckType.None) { return; } string data; if ((cfo == UpdateCheckType.Commit && (data = await GetNewCommit()) != null) || (cfo == UpdateCheckType.Release && (data = await GetNewRelease()) != null)) { await ch.SendConfirmAsync("New Bot Update", data).ConfigureAwait(false); } } catch (Exception ex) { _log.Warn(ex); } }, null, TimeSpan.FromHours(8), TimeSpan.FromHours(8)); } var sub = _redis.GetSubscriber(); sub.Subscribe(_creds.RedisKey() + "_reload_images", delegate { _imgs.Reload(); }, CommandFlags.FireAndForget); sub.Subscribe(_creds.RedisKey() + "_reload_bot_config", delegate { _bc.Reload(); }, CommandFlags.FireAndForget); Task.Run(async() => { await bot.Ready.Task.ConfigureAwait(false); _autoCommands = bc.BotConfig .StartupCommands .Where(x => x.Interval >= 5) .GroupBy(x => x.GuildId) .ToDictionary( x => x.Key, y => y.ToDictionary(x => x.Id, x => TimerFromStartupCommand((StartupCommand)x)) .ToConcurrent()) .ToConcurrent(); foreach (var cmd in bc.BotConfig.StartupCommands.Where(x => x.Interval <= 0)) { try { await ExecuteCommand(cmd); } catch { } } }); Task.Run(async() => { await bot.Ready.Task.ConfigureAwait(false); await Task.Delay(5000).ConfigureAwait(false); if (client.ShardId == 0) { await LoadOwnerChannels().ConfigureAwait(false); } }); }
public XpService(CommandHandler cmd, IBotConfigProvider bc, NadekoBot bot, DbService db, NadekoStrings strings, IDataCache cache, FontProvider fonts) { _db = db; _cmd = cmd; _bc = bc; _images = cache.LocalImages; _log = LogManager.GetCurrentClassLogger(); _strings = strings; _cache = cache; _fonts = fonts; //load settings var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null); _excludedChannels = allGuildConfigs .ToDictionary( x => x.GuildId, x => new ConcurrentHashSet<ulong>(x.XpSettings .ExclusionList .Where(ex => ex.ItemType == ExcludedItemType.Channel) .Select(ex => ex.ItemId) .Distinct())) .ToConcurrent(); _excludedRoles = allGuildConfigs .ToDictionary( x => x.GuildId, x => new ConcurrentHashSet<ulong>(x.XpSettings .ExclusionList .Where(ex => ex.ItemType == ExcludedItemType.Role) .Select(ex => ex.ItemId) .Distinct())) .ToConcurrent(); _excludedServers = new ConcurrentHashSet<ulong>( allGuildConfigs.Where(x => x.XpSettings.ServerExcluded) .Select(x => x.GuildId)); _cmd.OnMessageNoTrigger += _cmd_OnMessageNoTrigger; _updateXpTimer = new Timer(async _ => { try { var toNotify = new List<(IMessageChannel MessageChannel, IUser User, int Level, XpNotificationType NotifyType, NotifOf NotifOf)>(); var roleRewards = new Dictionary<ulong, List<XpRoleReward>>(); var toAddTo = new List<UserCacheItem>(); while (_addMessageXp.TryDequeue(out var usr)) toAddTo.Add(usr); var group = toAddTo.GroupBy(x => (GuildId: x.Guild.Id, User: x.User)); if (toAddTo.Count == 0) return; using (var uow = _db.UnitOfWork) { foreach (var item in group) { var xp = item.Select(x => bc.BotConfig.XpPerMessage).Sum(); var usr = uow.Xp.GetOrCreateUser(item.Key.GuildId, item.Key.User.Id); var du = uow.DiscordUsers.GetOrCreate(item.Key.User); if (du.LastXpGain + TimeSpan.FromMinutes(_bc.BotConfig.XpMinutesTimeout) > DateTime.UtcNow) continue; du.LastXpGain = DateTime.UtcNow; var globalXp = du.TotalXp; var oldGlobalLevelData = new LevelStats(globalXp); var newGlobalLevelData = new LevelStats(globalXp + xp); var oldGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp); usr.Xp += xp; du.TotalXp += xp; if (du.Club != null) du.Club.Xp += xp; var newGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp); if (oldGlobalLevelData.Level < newGlobalLevelData.Level) { du.LastLevelUp = DateTime.UtcNow; var first = item.First(); if (du.NotifyOnLevelUp != XpNotificationType.None) toNotify.Add((first.Channel, first.User, newGlobalLevelData.Level, du.NotifyOnLevelUp, NotifOf.Global)); } if (oldGuildLevelData.Level < newGuildLevelData.Level) { usr.LastLevelUp = DateTime.UtcNow; //send level up notification var first = item.First(); if (usr.NotifyOnLevelUp != XpNotificationType.None) toNotify.Add((first.Channel, first.User, newGuildLevelData.Level, usr.NotifyOnLevelUp, NotifOf.Server)); //give role if (!roleRewards.TryGetValue(usr.GuildId, out var rewards)) { rewards = uow.GuildConfigs.XpSettingsFor(usr.GuildId).RoleRewards.ToList(); roleRewards.Add(usr.GuildId, rewards); } var rew = rewards.FirstOrDefault(x => x.Level == newGuildLevelData.Level); if (rew != null) { var role = first.User.Guild.GetRole(rew.RoleId); if (role != null) { var __ = first.User.AddRoleAsync(role); } } } } uow.Complete(); } await Task.WhenAll(toNotify.Select(async x => { if (x.NotifOf == NotifOf.Server) { if (x.NotifyType == XpNotificationType.Dm) { var chan = await x.User.GetOrCreateDMChannelAsync().ConfigureAwait(false); if (chan != null) await chan.SendConfirmAsync(_strings.GetText("level_up_dm", (x.MessageChannel as ITextChannel)?.GuildId, "xp", x.User.Mention, Format.Bold(x.Level.ToString()), Format.Bold((x.MessageChannel as ITextChannel)?.Guild.ToString() ?? "-"))) .ConfigureAwait(false); } else // channel { await x.MessageChannel.SendConfirmAsync(_strings.GetText("level_up_channel", (x.MessageChannel as ITextChannel)?.GuildId, "xp", x.User.Mention, Format.Bold(x.Level.ToString()))) .ConfigureAwait(false); } } else { IMessageChannel chan; if (x.NotifyType == XpNotificationType.Dm) { chan = await x.User.GetOrCreateDMChannelAsync().ConfigureAwait(false); } else // channel { chan = x.MessageChannel; } await chan.SendConfirmAsync(_strings.GetText("level_up_global", (x.MessageChannel as ITextChannel)?.GuildId, "xp", x.User.Mention, Format.Bold(x.Level.ToString()))) .ConfigureAwait(false); } })); } catch (Exception ex) { _log.Warn(ex); } }, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5)); _clearRewardTimerTokenSource = new CancellationTokenSource(); var token = _clearRewardTimerTokenSource.Token; //just a first line, in order to prevent queries. But since other shards can try to do this too, //i'll check in the db too. _clearRewardTimer = Task.Run(async () => { while (!token.IsCancellationRequested) { _rewardedUsers.Clear(); await Task.Delay(TimeSpan.FromMinutes(_bc.BotConfig.XpMinutesTimeout)); } }, token); }
public StreamNotificationService(DbService db, DiscordSocketClient client, NadekoStrings strings) { _db = db; _client = client; _strings = strings; _http = new HttpClient(); #if !GLOBAL_NADEKO var _ = Task.Run(async() => { while (true) { await Task.Delay(60000); var oldCachedStatuses = new ConcurrentDictionary <string, IStreamResponse>(_cachedStatuses); _cachedStatuses.Clear(); IEnumerable <FollowedStream> streams; using (var uow = _db.UnitOfWork) { streams = uow.GuildConfigs.GetAllFollowedStreams(client.Guilds.Select(x => (long)x.Id).ToList()); } await Task.WhenAll(streams.Select(async fs => { try { var newStatus = await GetStreamStatus(fs).ConfigureAwait(false); if (firstStreamNotifPass) { return; } IStreamResponse oldResponse; if (oldCachedStatuses.TryGetValue(newStatus.Url, out oldResponse) && oldResponse.Live != newStatus.Live) { var server = _client.GetGuild(fs.GuildId); var channel = server?.GetTextChannel(fs.ChannelId); if (channel == null) { return; } try { await channel.EmbedAsync(GetEmbed(fs, newStatus, channel.Guild.Id)).ConfigureAwait(false); } catch { // ignored } } } catch { // ignored } })); firstStreamNotifPass = false; } }); #endif }
//private readonly Timer _updateTimer; public SelfService(DiscordSocketClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db, IBotConfigProvider bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds, IDataCache cache, IHttpClientFactory factory) { _redis = cache.Redis; _bot = bot; _cmdHandler = cmdHandler; _db = db; _log = LogManager.GetCurrentClassLogger(); _localization = localization; _strings = strings; _client = client; _creds = creds; _bc = bc; _cache = cache; _imgs = cache.LocalImages; _httpFactory = factory; var sub = _redis.GetSubscriber(); if (_client.ShardId == 0) { sub.Subscribe(_creds.RedisKey() + "_reload_images", delegate { _imgs.Reload(); }, CommandFlags.FireAndForget); //_updateTimer = new Timer(async _ => //{ // try // { // var ch = ownerChannels?.Values.FirstOrDefault(); // if (ch == null) // no owner channels // return; // var cfo = _bc.BotConfig.CheckForUpdates; // if (cfo == UpdateCheckType.None) // return; // string data; // if ((cfo == UpdateCheckType.Commit && (data = await GetNewCommit().ConfigureAwait(false)) != null) // || (cfo == UpdateCheckType.Release && (data = await GetNewRelease().ConfigureAwait(false)) != null)) // { // await ch.SendConfirmAsync("New Bot Update", data).ConfigureAwait(false); // } // } // catch (Exception ex) // { // _log.Warn(ex); // } //}, null, TimeSpan.FromHours(8), TimeSpan.FromHours(8)); } sub.Subscribe(_creds.RedisKey() + "_reload_bot_config", delegate { _bc.Reload(); }, CommandFlags.FireAndForget); sub.Subscribe(_creds.RedisKey() + "_leave_guild", async(ch, v) => { try { var guildStr = v.ToString()?.Trim().ToUpperInvariant(); if (string.IsNullOrWhiteSpace(guildStr)) { return; } var server = _client.Guilds.FirstOrDefault(g => g.Id.ToString() == guildStr) ?? _client.Guilds.FirstOrDefault(g => g.Name.Trim().ToUpperInvariant() == guildStr); if (server == null) { return; } if (server.OwnerId != _client.CurrentUser.Id) { await server.LeaveAsync().ConfigureAwait(false); _log.Info($"Left server {server.Name} [{server.Id}]"); } else { await server.DeleteAsync().ConfigureAwait(false); _log.Info($"Deleted server {server.Name} [{server.Id}]"); } } catch { } }, CommandFlags.FireAndForget); Task.Run(async() => { await bot.Ready.Task.ConfigureAwait(false); _autoCommands = bc.BotConfig .StartupCommands .Where(x => x.Interval >= 5) .GroupBy(x => x.GuildId) .ToDictionary( x => x.Key, y => y.ToDictionary(x => x.Id, x => TimerFromStartupCommand((StartupCommand)x)) .ToConcurrent()) .ToConcurrent(); foreach (var cmd in bc.BotConfig.StartupCommands.Where(x => x.Interval <= 0)) { try { await ExecuteCommand(cmd).ConfigureAwait(false); } catch { } } }); Task.Run(async() => { await bot.Ready.Task.ConfigureAwait(false); await Task.Delay(5000).ConfigureAwait(false); if (client.ShardId == 0) { await LoadOwnerChannels().ConfigureAwait(false); } }); }
public LogCommandService(DiscordSocketClient client, NadekoStrings strings, NadekoBot bot, DbService db, MuteService mute, ProtectionService prot, GuildTimezoneService tz) { _client = client; _log = LogManager.GetCurrentClassLogger(); _strings = strings; _db = db; _mute = mute; _prot = prot; _tz = tz; GuildLogSettings = bot.AllGuildConfigs .ToDictionary(g => g.GuildId, g => g.LogSetting) .ToConcurrent(); _timerReference = new Timer(async(state) => { try { var keys = PresenceUpdates.Keys.ToList(); await Task.WhenAll(keys.Select(key => { if (PresenceUpdates.TryRemove(key, out var msgs)) { var title = GetText(key.Guild, "presence_updates"); var desc = string.Join(Environment.NewLine, msgs); return(key.SendConfirmAsync(title, desc.TrimTo(2048))); } return(Task.CompletedTask); })); } catch (Exception ex) { _log.Warn(ex); } }, null, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); //_client.MessageReceived += _client_MessageReceived; _client.MessageUpdated += _client_MessageUpdated; _client.MessageDeleted += _client_MessageDeleted; _client.UserBanned += _client_UserBanned; _client.UserUnbanned += _client_UserUnbanned; _client.UserJoined += _client_UserJoined; _client.UserLeft += _client_UserLeft; //_client.UserPresenceUpdated += _client_UserPresenceUpdated; _client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated; _client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS; _client.GuildMemberUpdated += _client_GuildUserUpdated; #if !GLOBAL_NADEKO _client.UserUpdated += _client_UserUpdated; #endif _client.ChannelCreated += _client_ChannelCreated; _client.ChannelDestroyed += _client_ChannelDestroyed; _client.ChannelUpdated += _client_ChannelUpdated; _mute.UserMuted += MuteCommands_UserMuted; _mute.UserUnmuted += MuteCommands_UserUnmuted; _prot.OnAntiProtectionTriggered += TriggeredAntiProtection; }
public CustomReactionsService(PermissionService perms, DbService db, NadekoStrings strings, DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, IUnitOfWork uow, IDataCache cache) { _log = LogManager.GetCurrentClassLogger(); _db = db; _client = client; _perms = perms; _cmd = cmd; _bc = bc; _strings = strings; _cache = cache; var sub = _cache.Redis.GetSubscriber(); sub.Subscribe(_client.CurrentUser.Id + "_gcr.added", (ch, msg) => { Array.Resize(ref GlobalReactions, GlobalReactions.Length + 1); GlobalReactions[GlobalReactions.Length - 1] = JsonConvert.DeserializeObject <CustomReaction>(msg); }, StackExchange.Redis.CommandFlags.FireAndForget); sub.Subscribe(_client.CurrentUser.Id + "_gcr.deleted", (ch, msg) => { var id = int.Parse(msg); GlobalReactions = GlobalReactions.Where(cr => cr?.Id != id).ToArray(); }, StackExchange.Redis.CommandFlags.FireAndForget); sub.Subscribe(_client.CurrentUser.Id + "_gcr.edited", (ch, msg) => { var obj = new { Id = 0, Message = "" }; obj = JsonConvert.DeserializeAnonymousType(msg, obj); var gcr = GlobalReactions.FirstOrDefault(x => x.Id == obj.Id); if (gcr != null) { gcr.Response = obj.Message; } }, StackExchange.Redis.CommandFlags.FireAndForget); sub.Subscribe(_client.CurrentUser.Id + "_crad.toggle", (ch, msg) => { var obj = new { Id = 0, Value = false }; obj = JsonConvert.DeserializeAnonymousType(msg, obj); var gcr = GlobalReactions.FirstOrDefault(x => x.Id == obj.Id); if (gcr != null) { gcr.AutoDeleteTrigger = obj.Value; } }, StackExchange.Redis.CommandFlags.FireAndForget); sub.Subscribe(_client.CurrentUser.Id + "_crdm.toggle", (ch, msg) => { var obj = new { Id = 0, Value = false }; obj = JsonConvert.DeserializeAnonymousType(msg, obj); var gcr = GlobalReactions.FirstOrDefault(x => x.Id == obj.Id); if (gcr != null) { gcr.DmResponse = obj.Value; } }, StackExchange.Redis.CommandFlags.FireAndForget); sub.Subscribe(_client.CurrentUser.Id + "_crca.toggle", (ch, msg) => { var obj = new { Id = 0, Value = false }; obj = JsonConvert.DeserializeAnonymousType(msg, obj); var gcr = GlobalReactions.FirstOrDefault(x => x.Id == obj.Id); if (gcr != null) { gcr.ContainsAnywhere = obj.Value; } }, StackExchange.Redis.CommandFlags.FireAndForget); var items = uow.CustomReactions.GetAll(); GuildReactions = new ConcurrentDictionary <ulong, CustomReaction[]>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray())); GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray(); }
public PollService(DiscordSocketClient client, NadekoStrings strings) { _log = LogManager.GetCurrentClassLogger(); _client = client; _strings = strings; }
public StreamNotificationService(DbService db, DiscordSocketClient client, NadekoStrings strings, IDataCache cache, IBotCredentials creds, IHttpClientFactory httpFactory, NadekoBot bot) { _db = db; _client = client; _strings = strings; _multi = cache.Redis; _creds = creds; _streamTracker = new NotifChecker(httpFactory, cache.Redis, creds.RedisKey(), client.ShardId == 0); using (var uow = db.GetDbContext()) { var ids = client.GetGuildIds(); var guildConfigs = uow._context.Set <GuildConfig>() .AsQueryable() .Include(x => x.FollowedStreams) .Where(x => ids.Contains(x.GuildId)) .ToList(); _offlineNotificationServers = new ConcurrentHashSet <ulong>(guildConfigs .Where(gc => gc.NotifyStreamOffline) .Select(x => x.GuildId) .ToList()); var followedStreams = guildConfigs .SelectMany(x => x.FollowedStreams) .ToList(); _shardTrackedStreams = followedStreams .GroupBy(x => new { Type = x.Type, Name = x.Username.ToLower() }) .ToList() .ToDictionary( x => new StreamDataKey(x.Key.Type, x.Key.Name.ToLower()), x => x.GroupBy(y => y.GuildId) .ToDictionary(y => y.Key, y => y.AsEnumerable().ToHashSet())); // shard 0 will keep track of when there are no more guilds which track a stream if (client.ShardId == 0) { var allFollowedStreams = uow._context.Set <FollowedStream>() .AsQueryable() .ToList(); foreach (var fs in allFollowedStreams) { _streamTracker.CacheAddData(fs.CreateKey(), null, replace: false); } _trackCounter = allFollowedStreams .GroupBy(x => new { Type = x.Type, Name = x.Username.ToLower() }) .ToDictionary( x => new StreamDataKey(x.Key.Type, x.Key.Name), x => x.Select(fs => fs.GuildId).ToHashSet()); } } var sub = _multi.GetSubscriber(); sub.Subscribe($"{_creds.RedisKey()}_streams_offline", HandleStreamsOffline); sub.Subscribe($"{_creds.RedisKey()}_streams_online", HandleStreamsOnline); if (client.ShardId == 0) { // only shard 0 will run the tracker, // and then publish updates with redis to other shards _streamTracker.OnStreamsOffline += OnStreamsOffline; _streamTracker.OnStreamsOnline += OnStreamsOnline; _ = _streamTracker.RunAsync(); sub.Subscribe($"{_creds.RedisKey()}_follow_stream", HandleFollowStream); sub.Subscribe($"{_creds.RedisKey()}_unfollow_stream", HandleUnfollowStream); } bot.JoinedGuild += ClientOnJoinedGuild; client.LeftGuild += ClientOnLeftGuild; }