Ejemplo n.º 1
0
        public ProtectionService(DiscordSocketClient client, NadekoBot bot,
                                 MuteService mute, DbService db, UserPunishService punishService)
        {
            _client        = client;
            _mute          = mute;
            _db            = db;
            _punishService = punishService;

            var ids = client.GetGuildIds();

            using (var uow = db.GetDbContext())
            {
                var configs = uow._context.Set <GuildConfig>()
                              .AsQueryable()
                              .Include(x => x.AntiRaidSetting)
                              .Include(x => x.AntiSpamSetting)
                              .ThenInclude(x => x.IgnoredChannels)
                              .Include(x => x.AntiAltSetting)
                              .Where(x => ids.Contains(x.GuildId))
                              .ToList();

                foreach (var gc in configs)
                {
                    Initialize(gc);
                }
            }

            _client.MessageReceived += HandleAntiSpam;
            _client.UserJoined      += HandleUserJoined;

            bot.JoinedGuild   += _bot_JoinedGuild;
            _client.LeftGuild += _client_LeftGuild;

            _ = Task.Run(RunQueue);
        }
Ejemplo n.º 2
0
        public FilterService(DiscordSocketClient client, NadekoBot bot, DbService db)
        {
            _log = LogManager.GetCurrentClassLogger();
            _db  = db;

            using (var uow = db.GetDbContext())
            {
                var ids     = client.GetGuildIds();
                var configs = uow._context.Set <GuildConfig>()
                              .AsQueryable()
                              .Include(x => x.FilteredWords)
                              .Include(x => x.FilterLinksChannelIds)
                              .Include(x => x.FilterWordsChannelIds)
                              .Include(x => x.FilterInvitesChannelIds)
                              .Where(gc => ids.Contains(gc.GuildId))
                              .ToList();

                InviteFilteringServers  = new ConcurrentHashSet <ulong>(configs.Where(gc => gc.FilterInvites).Select(gc => gc.GuildId));
                InviteFilteringChannels = new ConcurrentHashSet <ulong>(configs.SelectMany(gc => gc.FilterInvitesChannelIds.Select(fci => fci.ChannelId)));

                LinkFilteringServers  = new ConcurrentHashSet <ulong>(configs.Where(gc => gc.FilterLinks).Select(gc => gc.GuildId));
                LinkFilteringChannels = new ConcurrentHashSet <ulong>(configs.SelectMany(gc => gc.FilterLinksChannelIds.Select(fci => fci.ChannelId)));

                var dict = configs.ToDictionary(gc => gc.GuildId, gc => new ConcurrentHashSet <string>(gc.FilteredWords.Select(fw => fw.Word)));

                ServerFilteredWords = new ConcurrentDictionary <ulong, ConcurrentHashSet <string> >(dict);

                var serverFiltering = configs.Where(gc => gc.FilterWords);
                WordFilteringServers  = new ConcurrentHashSet <ulong>(serverFiltering.Select(gc => gc.GuildId));
                WordFilteringChannels = new ConcurrentHashSet <ulong>(configs.SelectMany(gc => gc.FilterWordsChannelIds.Select(fwci => fwci.ChannelId)));
            }

            client.MessageUpdated += (oldData, newMsg, channel) =>
            {
                var _ = Task.Run(() =>
                {
                    var guild  = (channel as ITextChannel)?.Guild;
                    var usrMsg = newMsg as IUserMessage;

                    if (guild == null || usrMsg == null)
                    {
                        return(Task.CompletedTask);
                    }

                    return(RunBehavior(null, guild, usrMsg));
                });
                return(Task.CompletedTask);
            };
        }
Ejemplo n.º 3
0
        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;
        }
Ejemplo n.º 4
0
        public StreamNotificationService(DbService db, DiscordSocketClient client,
                                         IBotStrings 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();
                _notifCleanupTimer = new Timer(_ =>
                {
                    try
                    {
                        var errorLimit     = TimeSpan.FromHours(12);
                        var failingStreams = _streamTracker.GetFailingStreams(errorLimit, true)
                                             .ToList();

                        if (!failingStreams.Any())
                        {
                            return;
                        }

                        var deleteGroups = failingStreams.GroupBy(x => x.Type)
                                           .ToDictionary(x => x.Key, x => x.Select(x => x.Name).ToList());

                        using (var uow = _db.GetDbContext())
                        {
                            foreach (var kvp in deleteGroups)
                            {
                                Log.Information($"Deleting {kvp.Value.Count} {kvp.Key} streams because " +
                                                $"they've been erroring for more than {errorLimit}: {string.Join(", ", kvp.Value)}");

                                var toDelete = uow._context.Set <FollowedStream>()
                                               .AsQueryable()
                                               .Where(x => x.Type == kvp.Key && kvp.Value.Contains(x.Username))
                                               .ToList();

                                uow._context.RemoveRange(toDelete);
                                uow.SaveChanges();

                                foreach (var loginToDelete in kvp.Value)
                                {
                                    _streamTracker.UntrackStreamByKey(new StreamDataKey(kvp.Key, loginToDelete));
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Error cleaning up FollowedStreams");
                        Log.Error(ex.ToString());
                    }
                }, null, TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(30));

                sub.Subscribe($"{_creds.RedisKey()}_follow_stream", HandleFollowStream);
                sub.Subscribe($"{_creds.RedisKey()}_unfollow_stream", HandleUnfollowStream);
            }

            bot.JoinedGuild  += ClientOnJoinedGuild;
            client.LeftGuild += ClientOnLeftGuild;
        }