Exemple #1
0
        private static async void HandleAsTimer(object sender, ElapsedEventArgs e)
        {
            //Reading servers configuration
            JsonClasses.ServersConfig serversConfig;
            using (StreamReader streamReader = new StreamReader("serversconfig.json"))
            {
                serversConfig = JsonConvert.DeserializeObject <JsonClasses.ServersConfig>(streamReader.ReadToEnd());
            }

            //Iterate through all servers in configuration
            foreach (JsonClasses.Server server in serversConfig.Servers)
            {
                //Reading guild from Discord using id in configuration
                SocketGuild guild = Bot.GetGuild(server.Id);

                //Iterate through all categories in configuration
                foreach (JsonClasses.Category categoryDefinition in server.Categories)
                {
                    await ProcessChannels(guild.GetCategoryChannel(categoryDefinition.Id), categoryDefinition);
                }
            }

            //Start timer after work
            UpdateTimer.Start();
        }
Exemple #2
0
        /// <summary>
        /// Leave an opt-in channel.
        /// </summary>
        /// <param name="guildConnection">
        /// The connection to the guild the user is trying to join a channel in. May not be null.
        /// </param>
        /// <param name="guildData">Information about this guild. May not be null.</param>
        /// <param name="requestAuthor">The author of the join channel request. May not be null.</param>
        /// <param name="channelName">The name of the channel to join.</param>
        /// <returns>The result of the request.</returns>
        public static async Task <LeaveResult> Leave(
            SocketGuild guildConnection,
            Guild guildData,
            SocketGuildUser requestAuthor,
            string channelName)
        {
            if (!guildData.OptinParentCategory.HasValue)
            {
                return(LeaveResult.NoOptinCategory);
            }
            var optinsCategory = guildData.OptinParentCategory.GetValueOrDefault();

            var optinsCategoryConnection = guildConnection.GetCategoryChannel(optinsCategory.Value);
            var requestedChannel         = optinsCategoryConnection.Channels
                                           .FirstOrDefault(x => string.Compare(x.Name, channelName, ignoreCase: false) == 0);

            if (requestedChannel == null)
            {
                return(LeaveResult.NoSuchChannel);
            }

            var associatedRoleName = OptinChannel.GetRoleName(requestedChannel.Id);
            var role = guildConnection.Roles
                       .FirstOrDefault(x => string.Compare(x.Name, associatedRoleName, ignoreCase: false) == 0);

            if (role == null)
            {
                return(LeaveResult.RoleMissing);
            }

            await requestAuthor.RemoveRoleAsync(role).ConfigureAwait(false);

            return(LeaveResult.Success);
        }
Exemple #3
0
        private async Task BotClient_GuildAvailable(SocketGuild guild)
        {
            try
            {
                logger.LogInformation("{guildName} is available.", guild.Name);

                var serverOptions = discordOptions.Servers.SingleOrDefault(o => o.ServerId == guild.Id);

                if (serverOptions != null)
                {
                    var category = guild.GetCategoryChannel(serverOptions.ChannelCategoryId);
                    if (category != null)
                    {
                        var lounge = category.Channels.SingleOrDefault(o => o.Name == serverOptions.LoungeChannelName);
                        if (lounge == null)
                        {
                            logger.LogInformation("Create lounge channel named {lounge}.", serverOptions.LoungeChannelName);
                            var newLounge = await guild.CreateVoiceChannelAsync(serverOptions.LoungeChannelName, props =>
                            {
                                props.CategoryId = category.Id;
                            });

                            logger.LogInformation("Created lounge channel {loungeId}", newLounge.Id);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Cannot prepare server [{guildId}] {guildName}", guild.Id, guild.Name);
            }
        }
Exemple #4
0
        /// <summary>
        /// Creates an opt-in channel in the given guild.
        /// </summary>
        /// <param name="guildConnection">
        /// The connection to the guild this channel is being created in. May not be null.
        /// </param>
        /// <param name="guildData">Information about this guild. May not be null.</param>
        /// <param name="requestAuthor">The author of the channel create request. May not be null.</param>
        /// <param name="channelName">The requested name of the new channel. May not be null.</param>
        /// <param name="description">The requested description of the new channel.</param>
        /// <returns>The result of the request.</returns>
        public static async Task <CreateResult> Create(
            SocketGuild guildConnection,
            Guild guildData,
            SocketGuildUser requestAuthor,
            string channelName,
            string description)
        {
            ValidateArg.IsNotNullOrWhiteSpace(channelName, nameof(channelName));

            if (!guildData.OptinParentCategory.HasValue)
            {
                return(CreateResult.NoOptinCategory);
            }
            var optinsCategory = guildData.OptinParentCategory.GetValueOrDefault();

            // TODO: requestAuthor.Roles gets cached. How do I refresh this value so that it's accurate?

            var hasPermission = PermissionsUtilities.HasPermission(
                userRoles: requestAuthor.Roles.Select(x => new Snowflake(x.Id)),
                allowedRoles: guildData.OptinCreatorsRoles);

            if (!hasPermission)
            {
                return(CreateResult.NoPermissions);
            }

            var optinsCategoryConnection = guildConnection.GetCategoryChannel(optinsCategory.Value);
            var alreadyExists            = optinsCategoryConnection.Channels
                                           .Select(x => x.Name)
                                           .Any(x => string.Compare(x, channelName, ignoreCase: false) == 0);

            if (alreadyExists)
            {
                return(CreateResult.ChannelNameUsed);
            }

            var createdTextChannel = await guildConnection.CreateTextChannelAsync(channelName, settings =>
            {
                settings.CategoryId = optinsCategory.Value;
                settings.Topic      = description ?? string.Empty;
            }).ConfigureAwait(false);

            var createdRole = await guildConnection.CreateRoleAsync(
                name : OptinChannel.GetRoleName(createdTextChannel.Id),
                permissions : null,
                color : null,
                isHoisted : false,
                isMentionable : false)
                              .ConfigureAwait(false);

            var newPermissions = createdTextChannel.AddPermissionOverwriteAsync(
                role: createdRole,
                permissions: new OverwritePermissions(viewChannel: PermValue.Allow));

            await requestAuthor.AddRoleAsync(createdRole).ConfigureAwait(false);

            return(CreateResult.Success);
        }
Exemple #5
0
        /// <summary>
        /// Renames an opt-in channel in the given guild.
        /// </summary>
        /// <param name="guildConnection">
        /// The connection to the guild this channel is being created in. May not be null.
        /// </param>
        /// <param name="guildData">Information about this guild. May not be null.</param>
        /// <param name="requestAuthor">The author of the channel create request. May not be null.</param>
        /// <param name="currentChannelName">The current name of the channel to rename. May not be null.</param>
        /// <param name="newChannelName">The requested new name of the channel. May not be null.</param>
        /// <returns>The result of the request.</returns>
        public static async Task <RenameResult> Rename(
            SocketGuild guildConnection,
            Guild guildData,
            SocketGuildUser requestAuthor,
            string currentChannelName,
            string newChannelName)
        {
            ValidateArg.IsNotNullOrWhiteSpace(currentChannelName, nameof(currentChannelName));
            ValidateArg.IsNotNullOrWhiteSpace(newChannelName, nameof(newChannelName));

            if (!guildData.OptinParentCategory.HasValue)
            {
                return(RenameResult.NoOptinCategory);
            }
            var optinsCategory = guildData.OptinParentCategory.GetValueOrDefault();

            // Check that the request author has permission to create opt-ins (which means they can rename them as well)
            var hasPermission = PermissionsUtilities.HasPermission(
                userRoles: requestAuthor.Roles.Select(x => new Snowflake(x.Id)),
                allowedRoles: guildData.OptinCreatorsRoles);

            if (!hasPermission)
            {
                return(RenameResult.NoPermissions);
            }

            var optinsCategoryConnection = guildConnection.GetCategoryChannel(optinsCategory.Value);

            // Try to get the channel to rename and verify it exists
            var currentChannel = optinsCategoryConnection.Channels
                                 .Where(x => string.Compare(x.Name, currentChannelName, ignoreCase: false) == 0 && x is SocketTextChannel)
                                 .Cast <SocketTextChannel>()
                                 .SingleOrDefault();

            if (currentChannel == default)
            {
                return(RenameResult.NoSuchChannel);
            }

            // Verify the new channel name is not already in use
            var newChannelAlreadyExists = optinsCategoryConnection.Channels
                                          .Select(x => x.Name)
                                          .Any(x => string.Compare(x, newChannelName, ignoreCase: false) == 0);

            if (newChannelAlreadyExists)
            {
                return(RenameResult.NewChannelNameUsed);
            }

            // Modify the channel name
            await currentChannel.ModifyAsync(settings =>
            {
                settings.Name = newChannelName;
            }).ConfigureAwait(false);

            return(RenameResult.Success);
        }
        private Task BotClient_GuildAvailable(SocketGuild guild)
        {
            try
            {
                logger.LogInformation("{guildName} is available.", guild.Name);

                var serverOptions = discordOptions.Servers.SingleOrDefault(o => o.ServerId == guild.Id);

                if (serverOptions != null)
                {
                    Task.Run(async() =>
                    {
                        while (true)
                        {
                            var category = guild.GetCategoryChannel(serverOptions.ChannelCategoryId);
                            if (category != null)
                            {
                                var channels = category.Channels.Where(channel => channel.Name != serverOptions.LoungeChannelName);
                                foreach (var channel in channels)
                                {
                                    if (channel is SocketVoiceChannel voiceChannel && voiceChannel.CategoryId == serverOptions.ChannelCategoryId && voiceChannel.Name != serverOptions.LoungeChannelName)
                                    {
                                        var stopwatch = channelStopwatches.GetOrAdd(channel.Id, id =>
                                        {
                                            logger.LogInformation("Adding stopwatch for {channelName}.", voiceChannel.Name);
                                            var stopwatch = new Stopwatch();
                                            stopwatch.Start();
                                            return(stopwatch);
                                        });
                                        if (voiceChannel.Users.Count > 0)
                                        {
                                            stopwatch.Restart();
                                        }
                                        else if (stopwatch.ElapsedMilliseconds > 60000)
                                        {
                                            logger.LogInformation("Deleting {channelName}.", voiceChannel.Name);
                                            await voiceChannel.DeleteAsync();
                                        }
                                    }
                                }
                            }

                            await Task.Delay(1000);
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Cannot prepare server [{guildId}] {guildName}", guild.Id, guild.Name);
            }
            return(Task.CompletedTask);
        }
        public async Task Count()
        {
            Debug.Log("count");
            XPCJP = Client.GetGuild(Option.XPCJPGuildId);
            var now                 = DateTime.Now;
            var lastWeek            = now.AddDays(-7);
            var beforeLastWeek      = lastWeek.AddDays(-7);
            var notificationChannel = XPCJP.GetTextChannel(Option.NotificationChannelId);
            var alert               = new StringBuilder();
            var bakuha              = new StringBuilder();

            foreach (var optionFreeRoomCategoryId in Option.FreeRoomCategoryIds)
            {
                var category = XPCJP.GetCategoryChannel(optionFreeRoomCategoryId);
                Debug.Log($"カテゴリー:{category.Name}");
                foreach (SocketGuildChannel channel in category.Channels)
                {
                    if (channel is SocketTextChannel)
                    {
                        var textChannel = channel as SocketTextChannel;
                        Debug.Log($"チャンネル:{textChannel.Name}");

                        if (Count(lastWeek, now, channel.Id) >= 5)
                        {
                            // なし
                            Debug.Log($"なし {channel.Id}:{channel.Name}");
                            continue;
                        }

                        if (Count(beforeLastWeek, lastWeek, channel.Id) >= 5)
                        {
                            // アラート
                            Debug.Log($"アラート {channel.Id}:{channel.Name}");
                            await textChannel.SendMessageAsync("先週に書き込みをしたユニークユーザーが5人未満でした");

                            alert.AppendLine(textChannel.Mention);
                        }
                        else
                        {
                            // 爆破
                            Debug.Log($"爆破 {channel.Id}:{channel.Name}");
                            await textChannel.SendMessageAsync("先週,先々週に書き込みをしたユニークユーザーが5人未満でした");

                            bakuha.AppendLine(textChannel.Mention);
                        }
                    }
                }
            }

            await notificationChannel.SendMessageAsync($"アラート\n{alert.ToString()}\n爆破\n{bakuha.ToString()}");

            Completed = true;
        }
Exemple #8
0
        private async Task ConfigureGuild(SocketGuild guild)
        {
            _logger.LogDebug($"Configuring guild {guild.Name}");

            _logger.LogDebug($"Detecting language for guild {guild.Name}");
            var guildLang = guild.PreferredLocale;

            _logger.LogDebug($"PreferredLocale set to {guildLang}");
            var ci = new CultureInfo(guildLang);

            guildLang = ci.Parent?.Name;
            if (string.IsNullOrEmpty(guildLang))
            {
                guildLang = ci.Name;
            }

            if (!await _translationService.IsLangSupported(guildLang))
            {
                _logger.LogDebug($"Couldn't resolve guild language {guildLang}, defaulting to {TranslationConstants.StandardLanguage}");
                guildLang = TranslationConstants.StandardLanguage;
            }

            _logger.LogDebug($"Setting the translation language for {guild.Name} to {guildLang}");
            _guildLanguages[guild.Id] = guildLang;

            _logger.LogDebug(string.Join(", ", guild.CategoryChannels.Select(a => a.Name)));

            var category = guild.CategoryChannels.SingleOrDefault(a => a.Name == TranslationConstants.CategoryName) as ICategoryChannel;

            if (category == null)
            {
                _logger.LogDebug($"'{TranslationConstants.CategoryName}' category not found, creating.");
                _waitingForChannel = TranslationConstants.CategoryName;
                category           = await guild.CreateCategoryChannelAsync(TranslationConstants.CategoryName);

                _channelCreatedWaiter.WaitOne();
            }

            var tmpCat   = guild.GetCategoryChannel(category.Id);
            var tmpChans = tmpCat.Channels;

            var howtoChannel = await CreateOrUpdateChannel(guild, category, TranslationConstants.HowToChannelName, $"Use the ??translate create <your-language> command to start a session", 999);

            await PostStockMessages(howtoChannel);
            await CreateOrUpdateChannel(guild, category, TranslationConstants.HistoryChannelName, $"Use this channel to search past localized conversations", 0);

            _logger.LogDebug($"Done configuring guild {guild.Name}");
        }
Exemple #9
0
        /// <summary>
        /// Updates the description of an opt-in channel in the given guild.
        /// </summary>
        /// <param name="guildConnection">
        /// The connection to the guild this channel is being created in. May not be null.
        /// </param>
        /// <param name="guildData">Information about this guild. May not be null.</param>
        /// <param name="requestAuthor">The author of the channel create request. May not be null.</param>
        /// <param name="channelName">The current name of the channel to rename. May not be null.</param>
        /// <param name="description">The requested description of the channel.</param>
        /// <returns>The result of the request.</returns>
        public static async Task <UpdateDescriptionResult> UpdateDescription(
            SocketGuild guildConnection,
            Guild guildData,
            SocketGuildUser requestAuthor,
            string channelName,
            string description)
        {
            ValidateArg.IsNotNullOrWhiteSpace(channelName, nameof(channelName));

            if (!guildData.OptinParentCategory.HasValue)
            {
                return(UpdateDescriptionResult.NoOptinCategory);
            }
            var optinsCategory = guildData.OptinParentCategory.GetValueOrDefault();

            // Check that the request author has permission to create opt-ins (which means they can update their description as well)
            var hasPermission = PermissionsUtilities.HasPermission(
                userRoles: requestAuthor.Roles.Select(x => new Snowflake(x.Id)),
                allowedRoles: guildData.OptinCreatorsRoles);

            if (!hasPermission)
            {
                return(UpdateDescriptionResult.NoPermissions);
            }

            var optinsCategoryConnection = guildConnection.GetCategoryChannel(optinsCategory.Value);

            // Try to get the channel to update and verify it exists
            var currentChannel = optinsCategoryConnection.Channels
                                 .Where(x => string.Compare(x.Name, channelName, ignoreCase: false) == 0 && x is SocketTextChannel)
                                 .Cast <SocketTextChannel>()
                                 .SingleOrDefault();

            if (currentChannel == default)
            {
                return(UpdateDescriptionResult.NoSuchChannel);
            }

            // Modify the channel description
            await currentChannel.ModifyAsync(settings =>
            {
                settings.Topic = description ?? string.Empty;
            }).ConfigureAwait(false);

            return(UpdateDescriptionResult.Success);
        }
Exemple #10
0
        public DiscordBot(string key)
        {
            _bot.MessageReceived += OnMessageReceived;

            _bot.LoginAsync(TokenType.Bot, key);
            _bot.StartAsync();

            while (_bot.LoginState == LoginState.LoggingIn)
            {
                Thread.Sleep(1);
            }
            SetStatus(UserStatus.DoNotDisturb, "Setting everything up.");

            while ((_guild = _bot.GetGuild(GuildId)) == null)
            {
                Thread.Sleep(1);
            }

            while ((_categoryChannel = _guild.GetCategoryChannel(CategoryId)) == null)
            {
                Thread.Sleep(1);
            }

            IReadOnlyCollection <SocketGuildUser> sockets;

            while ((sockets = _guild.Users).Count <= 1)
            {
                Thread.Sleep(1);
            }

            _players = sockets.Where(user => user.Roles.Any(role => role.Id == RoleId))
                       .Select(user =>
            {
                var channelName = user.Nickname.ToLower() + "s-tattoo";
                if (_categoryChannel.Channels.FirstOrDefault(c => c.Name == channelName) is not ITextChannel channel)
                {
                    channel = _guild.CreateTextChannelAsync(channelName,
                                                            properties => properties.CategoryId = CategoryId).Result;
                    channel.AddPermissionOverwriteAsync(user, new OverwritePermissions(viewChannel: PermValue.Allow, sendMessages: PermValue.Allow));
                }
                var player = new Player(user, channel);
                _channelIdToPlayer.Add(channel.Id, player);
                return(player);
            }).ToArray();
            SetStatus(UserStatus.Online, "Working");
        }
Exemple #11
0
        /// <summary>
        /// Lists all of the opt-in channels.
        /// </summary>
        /// <param name="guildConnection">A connection to the guild. May not be null.</param>
        /// <param name="guildData">Information about this guild. May not be null.</param>
        /// <param name="recycleResult">A preallocated result that should be returned if passed in.</param>
        /// <returns>All of the names and descriptions opt-in channels.</returns>
        public static ListResult List(
            SocketGuild guildConnection,
            Guild guildData,
            ListResult recycleResult = null)
        {
            var retVal = recycleResult ?? new ListResult();

            if (!guildData.OptinParentCategory.HasValue)
            {
                retVal.ToNoOptinCategory();
                return(retVal);
            }
            var optinsCategory = guildData.OptinParentCategory.GetValueOrDefault();

            var optinsCategoryConnection = guildConnection.GetCategoryChannel(optinsCategory.Value);

            retVal.ToSuccess(
                optinsCategoryConnection.Channels
                .Select(x => new Tuple <string, string>(x.Name, x is SocketTextChannel textChannel ? textChannel.Topic : string.Empty)));
            return(retVal);
        }
        /// <summary>
        /// Gets the welcome message text.
        /// </summary>
        /// <param name="guildConnection">A connection to the guild.</param>
        /// <param name="guild">Guild data.</param>
        /// <param name="userId">The id representing the user.</param>
        /// <returns>The welcome message to send.</returns>
        private static string GetWelcomeMessage(SocketGuild guildConnection, Guild guild, Snowflake userId)
        {
            var builder = welcomeMessageBuilderPool.Get();

            builder.Clear();
            try
            {
                builder.AppendFormat("Hi <@{0}>!", userId);
                if (guild.OptinParentCategory.HasValue)
                {
                    var optinChannelCategoryId = guild.OptinParentCategory.GetValueOrDefault();
                    var optinChannelCategory   = guildConnection.GetCategoryChannel(optinChannelCategoryId.Value);
                    if (optinChannelCategory.Channels.Count > 0)
                    {
                        builder.Append(" This server has a bunch of channels that you can join that you can't see right now, but you are welcome to join.");
                        foreach (var channel in optinChannelCategory.Channels)
                        {
                            builder.AppendFormat("\n | {0}", channel.Name);

                            if (channel is SocketTextChannel textChannel && !string.IsNullOrEmpty(textChannel.Topic))
                            {
                                builder.AppendFormat(" - {0}", textChannel.Topic);
                            }
                        }
                        var exampleChannelName = optinChannelCategory.Channels.Last().Name;
                        builder.AppendFormat(
                            "\nLet me know if you're interested in any of them by sending me a message like, \"@Chill Bot join {0}\"",
                            exampleChannelName);
                    }
                }
                return(builder.ToString());
            }
            finally
            {
                welcomeMessageBuilderPool.Return(builder);
            }
        }
Exemple #13
0
        public async Task CreateRequest(SocketGuild guild, SocketGuildUser user, string authorName, string title, string text, SupportType supportType, int atLeastAdminLevel, bool fromDiscord)
        {
            GuildEntity guildEntity = _databaseHandler.Get <GuildEntity>(guild.Id);

            if (guildEntity is null)
            {
                return;
            }

            var categoryId = guildEntity.SupportRequestCategoryId;

            if (categoryId == 0)
            {
                return;
            }
            var supportRequestCategory = guild.GetCategoryChannel(categoryId);

            if (supportRequestCategory is null)
            {
                return;
            }

            var embed = EmbedHelper.GetSupportRequestEmbed(user, title, text, supportType);

            var textChannel = await ChannelHelper.CreateSupportChannel(guild, supportType.ToString() + "_discord", categoryId, fromDiscord);

            await textChannel.AddPermissionOverwriteAsync(user, new OverwritePermissions(
                                                              viewChannel : PermValue.Allow,
                                                              sendMessages : PermValue.Allow,
                                                              readMessageHistory : PermValue.Allow,
                                                              connect : PermValue.Allow,
                                                              speak : PermValue.Allow
                                                              ));

            if (atLeastAdminLevel > 1 && guildEntity.SupporterRoleId != 0)
            {
                await textChannel.DenyAccess(guild, guildEntity.SupporterRoleId);
            }
            if (atLeastAdminLevel > 2 && guildEntity.AdministratorRoleId != 0)
            {
                await textChannel.DenyAccess(guild, guildEntity.AdministratorRoleId);
            }

            var message = await textChannel.SendMessageAsync(user.Mention, embed : embed.Build());

            await message.PinAsync();

            await user.SendMessageAsync($"Your support request has been sent, a channel has been created:{Environment.NewLine}{message.GetJumpUrl()}");

            if (fromDiscord)
            {
                var reply = await _tdsClient.SupportRequest.Create(user.Id, title, text, supportType, atLeastAdminLevel);

                if (int.TryParse(reply, out int requestId))
                {
                    await textChannel.ModifyAsync(c => c.Name = supportType.ToString() + "_" + requestId);

                    await user.SendMessageAsync($"The support request was successfully added to TDS-V.");
                }
                else
                {
                    await user.SendMessageAsync($"The support request could not be added to TDS-V." +
                                                $"{Environment.NewLine}You either don't have an account yet or have not set your Discord-ID in your settings (correctly)." +
                                                $"{Environment.NewLine}If you've set the wrong id: You need to set your ID to '{user.Id}'");
                }
            }
        }
 private void deleteCategoryChannel(SocketGuild _g, ulong catID)
 {
     if (catID != 0)
         _g.GetCategoryChannel(catID).DeleteAsync();
     System.Threading.Thread.Sleep(300);
 }
 public virtual SocketCategoryChannel GetCategoryChannel(ulong id)
 {
     return(_socketGuild.GetCategoryChannel(id));
 }
Exemple #16
0
        private async Task MessageReceived(SocketMessage arg)
        {
            SocketRole infectedRole = null;

            if (arg is SocketUserMessage message && !message.Author.IsBot && !message.Author.IsWebhook && message.Author is SocketGuildUser user1 && message.Channel is SocketGuildChannel channel)
            {
                if (!configs.Guilds.ContainsKey(user1.Guild.Id.ToString()))
                {
                    return;
                }
                if (!databases.Guilds.ContainsKey(user1.Guild.Id.ToString()))
                {
                    databases.Guilds.Add(user1.Guild.Id.ToString(), new GuildDatabase());
                }
                GuildConfig config = (configs.Guilds[user1.Guild.Id.ToString()]);
                if (infectedRole == null)
                {
                    infectedRole = user1.Guild.GetRole(config.InfectedRoleId);
                }
                SocketGuild guild = user1.Guild;
                if (infectedRole != null && !config.SafeChannelIds.Contains(message.Channel.Id) && !config.SuperSafeChannelIds.Contains(message.Channel.Id) && message.Content.ToLower().Contains("*cough*") && user1.Roles.Contains(infectedRole))
                {
                    bool found = false;
                    foreach (var item in config.SafeChannelIds)
                    {
                        var cat = guild.GetCategoryChannel(item);
                        if (cat == null || !cat.Channels.Contains(channel))
                        {
                            continue;
                        }
                        found = true;
                        break;
                    }
                    if (!found)
                    {
                        foreach (var item in config.SuperSafeChannelIds)
                        {
                            var cat = guild.GetCategoryChannel(item);
                            if (cat == null || !cat.Channels.Contains(channel))
                            {
                                continue;
                            }
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        var msgsa = message.Channel.GetMessagesAsync(config.InfectMessageLimit);
                        var msgs  = await msgsa.FlattenAsync();

                        // if (msgs.Where(p => p.Content.Contains("*cough*") && p.Author.Id == user1.Id).Count() == 0)
                        {
                            IMessage[] array = msgs.Where(p => !p.Author.IsBot && !p.Author.IsWebhook && p.Author.Id != user1.Id && p.Timestamp.UtcDateTime.Add(TimeSpan.FromSeconds(config.SafeTimeSeconds)) >= DateTime.UtcNow && p.Author is SocketGuildUser user && !user.Roles.Contains(infectedRole)).ToArray();
                            if (array.Length != 0)
                            {
                                IMessage msg2 = array[rng.Next(array.Length)];
                                if (msg2 is RestUserMessage message2 && message2.Author is SocketGuildUser user2)
                                {
                                    await InfectUser(user2, infectedRole, user1);
                                    await SaveData();

                                    string name = string.IsNullOrWhiteSpace(user1.Nickname) ? user1.Username : user1.Nickname;
                                    await message2.ReplyAsync($"{name} infected you with {config.VirusName}!");
                                }
                            }
                        }
                    }
                }
                if (infectedRole != null && !user1.Roles.Contains(infectedRole) && !config.SuperSafeChannelIds.Contains(message.Channel.Id) && rng.Next(100) < config.AutoInfectPercent)
                {
                    bool found = false;
                    foreach (var item in config.SuperSafeChannelIds)
                    {
                        var cat = guild.GetCategoryChannel(item);
                        if (cat == null || !cat.Channels.Contains(channel))
                        {
                            continue;
                        }
                        found = true;
                        break;
                    }
                    if (!found)
                    {
                        await InfectUser(user1, infectedRole);
                        await SaveData();

                        await message.ReplyAsync($"Somehow, you were infected with {config.VirusName}!");
                    }
                }
                if (infectedRole != null && message.Content.ToLower().StartsWith(config.StatsCommand.ToLower()))
                {
                    string[] infected = infectedRole.Members.OrderByDescending(p =>
                    {
                        if (databases.Guilds[user1.Guild.Id.ToString()].InfectedTimestamps.ContainsKey(p.Id.ToString()))
                        {
                            return(databases.Guilds[user1.Guild.Id.ToString()].InfectedTimestamps[p.Id.ToString()]);
                        }
                        return(long.MinValue);
                    }).Select(p =>
                    {
                        string time = "N/A";
                        if (databases.Guilds[user1.Guild.Id.ToString()].InfectedTimestamps.ContainsKey(p.Id.ToString()))
                        {
                            time = DateTime.MinValue.AddTicks(databases.Guilds[user1.Guild.Id.ToString()].InfectedTimestamps[p.Id.ToString()]).ToString();
                        }
                        return($"{p.Username}#{p.Discriminator} was infected at {time}");
                    }).ToArray();
                    string output = "";
                    for (int i = 0; i < infected.Length && i < config.StatsMaxInfectedListings; i++)
                    {
                        if (i != 0)
                        {
                            output += "\n";
                        }
                        output += infected[i];
                    }
                    EmbedBuilder emb = new EmbedBuilder();
                    emb.WithColor(config.InfectedRoleColorRed, config.InfectedRoleColorGreen, config.InfectedRoleColorBlue);
                    emb.WithTitle(config.VirusName);
                    emb.WithDescription(output);
                    await message.ReplyAsync(embed : emb.Build());

                    // string path = Path.GetTempFileName();
                    string path = Path.GetRandomFileName() + ".png";
                    StatsDraw.Draw(path, user1.Guild, databases.Guilds[user1.Guild.Id.ToString()].InfectedWho, config.StatsMaxInfectedListings);
                    await message.Channel.SendFileAsync(path);

                    File.Delete(path);
                }
                if (user1.GuildPermissions.ManageRoles && message.Content.ToLower().StartsWith(config.ResetCommand.ToLower()))
                {
                    if (infectedRole != null)
                    {
                        await infectedRole.DeleteAsync();
                    }
                    RestRole role = await user1.Guild.CreateRoleAsync(config.InfectedRoleName, GuildPermissions.None, new Discord.Color(config.InfectedRoleColorRed, config.InfectedRoleColorGreen, config.InfectedRoleColorBlue), false, false);

                    configs.Guilds[user1.Guild.Id.ToString()].InfectedRoleId = role.Id;
                    databases.Guilds[user1.Guild.Id.ToString()].InfectedTimestamps.Clear();
                    databases.Guilds[user1.Guild.Id.ToString()].InfectedWho.Clear();
                    await SaveData();

                    await message.ReplyAsync($"{config.VirusName} has been contained.");
                }
            }
        }
        private async Task MessageReceived(SocketMessage arg)
        {
            SocketRole infectedRole = null;

            if (arg is SocketUserMessage message && !message.Author.IsBot && !message.Author.IsWebhook && message.Author is SocketGuildUser user1 && message.Channel is SocketGuildChannel channel)
            {
                if (!configs.Guilds.ContainsKey(user1.Guild.Id.ToString()))
                {
                    await RunCommandService(message);

                    return;
                }
                if (!databases.Guilds.ContainsKey(user1.Guild.Id.ToString()))
                {
                    databases.Guilds.Add(user1.Guild.Id.ToString(), new GuildDatabase());
                }
                GuildConfig config = (configs.Guilds[user1.Guild.Id.ToString()]);
                if (infectedRole == null)
                {
                    infectedRole = user1.Guild.GetRole(config.InfectedRoleId);
                }
                SocketGuild guild = user1.Guild;
                if (infectedRole != null && !config.SafeChannelIds.Contains(message.Channel.Id) && !config.SuperSafeChannelIds.Contains(message.Channel.Id) && message.Content.ToLower().Contains("*cough*") && user1.Roles.Contains(infectedRole))
                {
                    bool found = false;
                    foreach (var item in config.SafeChannelIds)
                    {
                        var cat = guild.GetCategoryChannel(item);
                        if (cat == null || !cat.Channels.Contains(channel))
                        {
                            continue;
                        }
                        found = true;
                        break;
                    }
                    if (!found)
                    {
                        foreach (var item in config.SuperSafeChannelIds)
                        {
                            var cat = guild.GetCategoryChannel(item);
                            if (cat == null || !cat.Channels.Contains(channel))
                            {
                                continue;
                            }
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        var msgsa = message.Channel.GetMessagesAsync(config.InfectMessageLimit);
                        var msgs  = await msgsa.FlattenAsync();

                        {
                            IMessage[] array = msgs.Where(p => !p.Author.IsBot && !p.Author.IsWebhook && p.Author.Id != user1.Id && p.Timestamp.UtcDateTime.Add(TimeSpan.FromSeconds(config.SafeTimeSeconds)) >= DateTime.UtcNow && p.Author is SocketGuildUser user && !user.Roles.Contains(infectedRole)).ToArray();
                            if (array.Length != 0)
                            {
                                IMessage msg2 = array[rng.Next(array.Length)];
                                if (msg2 is RestUserMessage message2 && message2.Author is SocketGuildUser user2)
                                {
                                    await InfectUser(user2, infectedRole, user1);
                                    await SaveData();

                                    string name = string.IsNullOrWhiteSpace(user1.Nickname) ? user1.Username : user1.Nickname;
                                    await message2.ReplyAsync($"{name} infected you with {config.VirusName}!");
                                }
                            }
                        }
                    }
                    return;
                }
                if (infectedRole != null && !user1.Roles.Contains(infectedRole) && !config.SuperSafeChannelIds.Contains(message.Channel.Id) && rng.Next(100) < config.AutoInfectPercent)
                {
                    bool found = false;
                    foreach (var item in config.SuperSafeChannelIds)
                    {
                        var cat = guild.GetCategoryChannel(item);
                        if (cat == null || !cat.Channels.Contains(channel))
                        {
                            continue;
                        }
                        found = true;
                        break;
                    }
                    if (!found && databases.Guilds[user1.Guild.Id.ToString()].GuildUsers.Where(p => p.Infection >= config.InfectionMin).Count() < config.InfectionMaxPeopleRandom)
                    {
                        await InfectUser(user1, infectedRole);

                        await message.ReplyAsync($"Somehow, you were infected with {config.VirusName}!");
                    }
                    return;
                }
                await RunCommandService(message);
            }
        }
 public static SocketCategoryChannel GetFeedbackArchiveCategory(this SocketGuild guild)
 {
     return(guild.GetCategoryChannel(FeedbackCategoryId));
 }
        private Task BotClient_GuildAvailable(SocketGuild guild)
        {
            try
            {
                logger.LogInformation("{guildName} is available.", guild.Name);

                var serverOptions = discordOptions.Servers.SingleOrDefault(o => o.ServerId == guild.Id);

                if (serverOptions != null)
                {
                    Task.Run(async() =>
                    {
                        while (true)
                        {
                            var category = guild.GetCategoryChannel(serverOptions.ChannelCategoryId);
                            if (category != null)
                            {
                                var channels = category.Channels
                                               .Where(channel => channel is SocketVoiceChannel voiceChannel)
                                               .Cast <SocketVoiceChannel>()
                                               .Where(channel => IsExtraChannel(channel, serverOptions));

                                logger.LogTrace("{guildName}: {allChannels}", guild.Name, string.Join(" | ", channels.Select(o => o.Name)));

                                foreach (var voiceChannel in channels)
                                {
                                    var stopwatch = AddOrGetStopwatch(voiceChannel);
                                    if (voiceChannel.Users.Count > 0)
                                    {
                                        stopwatch.Restart();
                                    }
                                    else if (stopwatch.ElapsedMilliseconds > 60000)
                                    {
                                        try
                                        {
                                            logger.LogInformation("Deleting {channelName} of guild {guildName}.", voiceChannel.Name, guild.Name);
                                            await voiceChannel.DeleteAsync();
                                        }
                                        catch (Exception ex)
                                        {
                                            logger.LogError(ex, "Cannot delete channel {channelName} of guild {guildName}!", voiceChannel.Name, guild.Name);
                                        }
                                        finally
                                        {
                                            channelStopwatches.TryRemove(voiceChannel.Id, out _);
                                        }
                                    }
                                }
                            }

                            await Task.Delay(1000);
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Cannot prepare server [{guildId}] {guildName}", guild.Id, guild.Name);
            }
            return(Task.CompletedTask);
        }