コード例 #1
0
ファイル: AntiraidCommand.cs プロジェクト: mmattbtw/Kaguya
        public async Task Command(int users = 0, int seconds = 0, string action = null)
        {
            Server server = await DatabaseQueries.GetOrCreateServerAsync(Context.Guild.Id);

            AntiRaidConfig antiraid = server.AntiRaid;

            if (users == 0 && seconds == 0 && action == null)
            {
                if (antiraid != null)
                {
                    await DatabaseQueries.DeleteAllForServerAsync <AntiRaidConfig>(server.ServerId);
                    await SendBasicSuccessEmbedAsync("Successfully disabled this server's antiraid protection.");

                    return;
                }

                await SendBasicErrorEmbedAsync("This server has not setup the antiraid service, therefore " +
                                               "there is nothing to disable.");

                return;
            }

            if (users < 1 || seconds < 5 && action != null)
            {
                if (users < 3)
                {
                    throw new ArgumentOutOfRangeException(nameof(users), "There must be at least `3` users to action before " +
                                                          "it is classified as a raid.");
                }

                if (seconds < 5)
                {
                    throw new ArgumentOutOfRangeException(nameof(seconds), "The seconds parameter must be at least `5`.");
                }
            }

            if (users > 200)
            {
                throw new ArgumentOutOfRangeException(nameof(users), "The users count must not be greater than `200`.");
            }

            if (seconds > 999)
            {
                throw new ArgumentOutOfRangeException(nameof(seconds),
                                                      "The `seconds` duration must not be greater than `999`.");
            }

            if (action == null)
            {
                throw new ArgumentNullException(nameof(action), "The action must not be null and must be either " +
                                                "`mute`, `kick`, `shadowban`, or `ban`.");
            }

            string[] actions =
            {
                "mute",
                "kick",
                "shadowban",
                "ban"
            };

            if (!actions.Any(x => x.Equals(action.ToLower())))
            {
                throw new ArgumentOutOfRangeException(nameof(action),
                                                      "The action must be either `mute`, `kick`, `shadowban`, " +
                                                      "or `ban`.");
            }

            var ar = new AntiRaidConfig
            {
                ServerId = server.ServerId,
                Users    = users,
                Seconds  = seconds,
                Action   = action.ToLower(),
                Server   = server
            };

            await SendBasicSuccessEmbedAsync(
                $"Successfully enabled the antiraid service for `{Context.Guild.Name}`.\n\n" +
                $"I will `{action.ToUpper()}` anyone part of a raid. A raid is now defined as " +
                $"`{users.ToWords()}` users joining within `{seconds.ToWords()}` seconds " +
                $"of each other.");

            if (antiraid != null)
            {
                await DatabaseQueries.InsertOrReplaceAsync(ar);

                return;
            }

            await DatabaseQueries.InsertOrReplaceAsync(ar);
        }
コード例 #2
0
ファイル: AntiRaidService.cs プロジェクト: BitMasher/Kaguya
        public static async Task Initialize() => await Task.Run(() =>
        {
            DiscordShardedClient client = ConfigProperties.Client;
            client.UserJoined          += async u =>
            {
                SocketGuild guild = u.Guild;
                Server server     = await DatabaseQueries.GetOrCreateServerAsync(guild.Id);

                if (server.AntiRaid == null)
                {
                    return;
                }

                AntiRaidConfig ar = server.AntiRaid;

                if (!ActiveAntiraids.Raids.Any(x => x.ServerId == server.ServerId))
                {
                    var newRaidData = new RaidData
                    {
                        ServerId = server.ServerId,
                        UserIds  = new HashSet <ulong>
                        {
                            u.Id
                        }
                    };

                    ActiveAntiraids.SafeAdd(newRaidData);
                }
                else
                {
                    var newIds = new HashSet <ulong>();
                    HashSet <ulong> existingIds = ActiveAntiraids.Raids.First(x => x.ServerId == server.ServerId).UserIds;

                    // Copies existing IDs from the known / active raid into a new HashSet<ulong>.
                    foreach (ulong id in existingIds)
                    {
                        newIds.Add(id);
                    }

                    // Finally, add the current user's ID to the HashSet.
                    newIds.Add(u.Id);

                    // Replace the object in memory.
                    ActiveAntiraids.ReplaceRaidData(new RaidData
                    {
                        ServerId = server.ServerId,
                        UserIds  = newIds
                    });
                }

                var timer       = new Timer(ar.Seconds * 1000);
                timer.Enabled   = true;
                timer.AutoReset = false;
                timer.Elapsed  += async(sender, args) =>
                {
                    RaidData existingObj = ActiveAntiraids.Raids.FirstOrDefault(x => x.ServerId == server.ServerId);

                    if (existingObj == null)
                    {
                        return;
                    }

                    // Filter by distinct to fix the duplicate users issue.
                    existingObj.UserIds = existingObj.UserIds.Distinct().ToHashSet();

                    // This must be above ActionUsers() as it takes a few seconds for users to be actioned
                    // resulting in duplicate log messages and ban attempts.
                    ActiveAntiraids.RemoveAll(existingObj);
                    if (existingObj.UserIds.Count >= ar.Users)
                    {
                        await ActionUsers(existingObj.UserIds, server.ServerId, ar.Action);
                    }
                };
            };
        });