Пример #1
0
        private async Task CmdListModsAsync(SocketCommandContext context, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            IOrderedEnumerable <StellarisMod> mods = (await _stellarisModsStore.GetAllAsync(cancellationToken).ConfigureAwait(false)).OrderBy(m => m.Name);

            if (!mods.Any())
            {
                await context.ReplyAsync($"{_einherjiOptions.FailureSymbol} You did not have any mod on the list.", cancellationToken).ConfigureAwait(false);

                return;
            }

            List <string> listStrings = new List <string>(mods.Count());

            foreach (StellarisMod mod in mods)
            {
                listStrings.Add(ModToListString(mod, listStrings.Count + 1));
            }
            EmbedBuilder embed = new EmbedBuilder()
                                 .WithDescription(string.Join('\n', listStrings))
                                 .WithFooter($"Currently you guys are using {listStrings.Count} mods.", context.Client.CurrentUser.GetAvatarUrl())
                                 .WithTimestamp(DateTimeOffset.Now)
                                 .WithAuthor("Your Stellaris mods", context.Client.CurrentUser.GetAvatarUrl());

            await context.ReplyAsync(null, false, embed.Build(), cancellationToken).ConfigureAwait(false);
        }
Пример #2
0
        private async Task CmdRandomizeStatus(SocketCommandContext context, CancellationToken cancellationToken = default)
        {
            EinherjiOptions einherjiOptions = this._einherjiOptions.CurrentValue;

            if (context.User.Id != einherjiOptions.AuthorID)
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} You have no rights to tell me ~~how to live my life~~ do this!",
                                         cancellationToken).ConfigureAwait(false);

                return;
            }

            Status status = await RandomizeStatusAsync(context.Client, cancellationToken).ConfigureAwait(false);

            if (status != null)
            {
                await context.ReplyAsync($"{einherjiOptions.SuccessSymbol} Status changed: `{status.Text.Replace("`", "\\`")}`", cancellationToken).ConfigureAwait(false);

                // restart loop
                StartBackgroundLoop();
            }
            else if (this._options.CurrentValue.Statuses?.Any() != true)
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Status not changed - ensure status list is not empty.", cancellationToken).ConfigureAwait(false);
            }
        }
Пример #3
0
        private Task CmdHelpAsync(SocketCommandContext context, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            PiholeOptions options = _piholeOptions.CurrentValue;
            IReadOnlyDictionary <string, PiholeInstanceOptions> instances = options.GetUserAuthorizedInstances(context.User);

            // check user is authorized to manage any instance
            if (instances?.Any() != true)
            {
                return(context.ReplyAsync($"{_einherjiOptions.CurrentValue.FailureSymbol} You are not authorized to manage any of Kathara PiHole instance.", cancellationToken));
            }

            string       prefix = _commandsOptions.CurrentValue.Prefix;
            EmbedBuilder embed  = new EmbedBuilder()
                                  .WithThumbnailUrl("https://upload.wikimedia.org/wikipedia/en/thumb/1/15/Pi-hole_vector_logo.svg/1200px-Pi-hole_vector_logo.svg.png")
                                  .WithDescription("Management utility for PiHoles present in Kathara network");

            embed.AddField("Commands",
                           $"**{prefix}pihole <instance id>** - show info on specific PiHole instance\n" +
                           $"**{prefix}pihole <instance id> enable** - enable a specific PiHole instance\n" +
                           $"**{prefix}pihole <instance id> disable** - disable a specific PiHole instance for {options.DefaultDisableTime.TotalMinutes} minutes\n" +
                           $"**{prefix}pihole <instance id> disable <minutes>** - disable a specific PiHole instance for custom amount of minutes\n" +
                           $"**{prefix}pihole** - display this message and check which instances you can manage");
            embed.AddField("Instances you can manage", string.Join(", ", instances.Keys));

            return(context.ReplyAsync(null, false, embed.Build(), cancellationToken));
        }
Пример #4
0
        public async Task SearchAsync(SocketCommandContext context, DbService db)
        {
            var user = await db.Users.FindAsync(context.User.Id)
                       ?? await StartAsync(context, db);

            var enemies = await db.Enemies.Where(x => x.ZoneId == user.ZoneId).ToListAsync();

            var found = _random.Next(100);

            if (found >= 40)
            {
                var enemy = enemies[_random.Next(enemies.Count)];
                var embed = new EmbedBuilder
                {
                    Color       = Color.Green,
                    Description = $"{context.User.Mention} encountered a wild {enemy.Name}!",
                    ImageUrl    = enemy.Image,
                    Footer      = new EmbedFooterBuilder {
                        Text = "Combat starting shortly..."
                    }
                };
                await context.ReplyAsync(embed);
                await BattleAsync(context, user, enemy, db);
            }
            else
            {
                await context.ReplyAsync($"{context.User.Mention} searched around and found no one",
                                         Color.Red.RawValue);
            }
        }
Пример #5
0
        private Task CmdIntelGuildAsync(SocketCommandContext context, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            if (context.IsPrivate)
            {
                return(context.ReplyAsync($"{_einherjiOptions.CurrentValue.FailureSymbol} This command can only be used in a guild channel.", cancellationToken));
            }

            EmbedBuilder embed = new EmbedBuilder();

            AddGuildInfo(embed, context.Guild);
            return(context.ReplyAsync(null, false, embed.Build(), cancellationToken));
        }
Пример #6
0
        private async Task CmdRemoveModAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            if (context.User.Id != _einherjiOptions.AuthorID)
            {
                await context.ReplyAsync($"{_einherjiOptions.FailureSymbol} You can't order me to do that.", cancellationToken).ConfigureAwait(false);

                return;
            }
            if (match.Groups.Count < 2)
            {
                await context.ReplyAsync($"{_einherjiOptions.FailureSymbol} Please specify numbers of mods to remove. Can be multiple numbers separated with spaces.\nTo get numbers of mods, use `{_commandsOptions.Prefix}stellaris mods`", cancellationToken).ConfigureAwait(false);

                return;
            }

            IOrderedEnumerable <StellarisMod> mods = (await _stellarisModsStore.GetAllAsync(cancellationToken).ConfigureAwait(false)).OrderBy(m => m.Name);

            string[]            idStrings        = match.Groups[1].Value.Split(' ', StringSplitOptions.RemoveEmptyEntries);
            List <string>       invalidIdStrings = new List <string>(idStrings.Length);
            List <StellarisMod> removalList      = new List <StellarisMod>(idStrings.Length);

            for (int i = 0; i < idStrings.Length; i++)
            {
                if (!int.TryParse(idStrings[i], out int id))
                {
                    invalidIdStrings.Add(idStrings[i]);
                }
                else
                {
                    removalList.Add(mods.ElementAt(id));
                }
            }

            string incompatibleString = invalidIdStrings.Count != 0 ? $"\nFollowing IDs are invalid: {string.Join(", ", invalidIdStrings.Select(s => $"`{s}`"))}." : null;

            if (removalList.Any())
            {
                _log.LogDebug("Removing {Count} stellaris mods: {ModNames}", removalList.Count, string.Join(", ", removalList.Select(s => s.Name)));
                await _stellarisModsStore.RemoveAsync(removalList, cancellationToken).ConfigureAwait(false);

                await context.ReplyAsync($"{_einherjiOptions.SuccessSymbol} Removed {removalList.Count} mods.{incompatibleString}", cancellationToken).ConfigureAwait(false);
            }
            else
            {
                await context.ReplyAsync($"No mods removed.{incompatibleString}", cancellationToken).ConfigureAwait(false);
            }
        }
Пример #7
0
        private async Task CmdRemoveGameAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            if (context.User.Id != _einherjiOptions.CurrentValue.AuthorID)
            {
                await SendInsufficientPermissionsAsync(context.Channel, cancellationToken).ConfigureAwait(false);

                return;
            }
            if (match.Groups.Count < 2 || match.Groups[1]?.Length < 1)
            {
                await SendNameRequiredAsync(context.Channel, cancellationToken).ConfigureAwait(false);

                return;
            }


            // check if game exists
            string gameName = match.Groups[1].Value.Trim();

            _log.LogDebug("Creating patchbot game {GameName}", gameName);
            PatchbotGame game = await _patchbotGamesStore.GetAsync(gameName, cancellationToken).ConfigureAwait(false);

            if (game == null)
            {
                _log.LogDebug("Patchbot game {GameName} not found", gameName);
                await SendGameNotFoundAsync(context.Channel, gameName, cancellationToken).ConfigureAwait(false);

                return;
            }

            await _patchbotGamesStore.DeleteAsync(game, cancellationToken).ConfigureAwait(false);

            await context.ReplyAsync($"{_einherjiOptions.CurrentValue.SuccessSymbol} Game `{game.Name}` removed.", cancellationToken).ConfigureAwait(false);
        }
Пример #8
0
        private async Task CmdUnsubscribeAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            if (match.Groups.Count < 2 || match.Groups[1]?.Length < 1)
            {
                await SendNameRequiredAsync(context.Channel, cancellationToken).ConfigureAwait(false);

                return;
            }
            string gameName = match.Groups[1].Value.Trim();

            _log.LogDebug("Unsubscribing user {UserID} to patchbot game {GameName}", context.User.Id, gameName);
            PatchbotGame game = await _patchbotGamesStore.GetAsync(gameName, cancellationToken).ConfigureAwait(false);

            if (game == null)
            {
                _log.LogDebug("Patchbot game {GameName} not found", gameName);
                await SendGameNotFoundAsync(context.Channel, gameName, cancellationToken).ConfigureAwait(false);

                return;
            }
            if (game.SubscriberIDs.Remove(context.User.Id))
            {
                await _patchbotGamesStore.DeleteAsync(game, cancellationToken).ConfigureAwait(false);
            }
            await context.ReplyAsync($"{_einherjiOptions.CurrentValue.SuccessSymbol} You will no longer be pinged about `{game.Name}` updates.", cancellationToken).ConfigureAwait(false);
        }
Пример #9
0
        private Task CmdCommandsAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            IOrderedEnumerable <IGrouping <string, CommandDescriptor> > commands = this.GetCommandDescriptors(context);

            if (commands.Any())
            {
                EmbedBuilder embed  = this.StartEmbed(context);
                string       prefix = this.GetPrefix(context);

                StringBuilder commandsList = new StringBuilder();
                foreach (IGrouping <string, CommandDescriptor> group in commands)
                {
                    commandsList.Clear();
                    foreach (CommandDescriptor cmd in group)
                    {
                        commandsList.Append($"***{prefix}{cmd.DisplayName}***: {cmd.Summary}\n");
                    }

                    embed.AddField(group.Key, commandsList.ToString(), inline: false);
                }

                return(context.ReplyAsync(null, false, embed.Build(), cancellationToken));
            }
            else
            {
                return(context.InlineReplyAsync($"{_einherjiOptions.FailureSymbol} Ooops, I detected no commands... this obviously isn't right. Please let {GetAuthorText(context)} know!", cancellationToken));
            }
        }
Пример #10
0
        private Task CmdGetAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            EmbedBuilder embed = this.StartEmbed(context);

            embed.AddField("Commands", $"Use **{this.GetPrefix(context)}commands** to get list of commands that you can use here!", inline: false);

            if (this.IsMainRestrictionGroup(context))
            {
                embed.AddField("Additional features",
                               "If you try to use an another bot in a wrong channel, I'll direct you to the correct channel.\n" +
                               $"I'll automatically post new or just finished Elite Dangerous Community Goals in {MentionUtils.MentionChannel(_eliteOptions.AutoNewsChannelID)}.\n" +
                               $"I'll post a message in {GetLeaveChannel(context)} when a user leaves the guild.",
                               inline: false);
            }
            else
            {
                embed.AddField("Additional features",
                               $"If I have permissions to post in {GetLeaveChannel(context)}, I'll post a message whenever a user leaves the guild.\n" +
                               $"More additional features are provided in {GetAuthorText(context)}'s server.", inline: false);
            }
            embed.AddField("Support",
                           $"To submit bugs or suggestions, please open an issue on [GitHub](https://github.com/TehGM/EinherjiBot/issues). Alternatively, you can message {GetAuthorText(context)}.\n" +
                           "To support the developer, consider donating on [GitHub Sponsors](https://github.com/sponsors/TehGM), [Patreon](https://patreon.com/TehGMdev) or [Buy Me A Coffee](https://www.buymeacoffee.com/TehGM). **Thank you!**",
                           inline: false);

            return(context.ReplyAsync(null, false, embed.Build(), cancellationToken));
        }
        private async Task PerformActionOnAllAsync(SocketCommandContext context, VoiceChannelMatch channelMatch, VoiceChannelAction action, CancellationToken cancellationToken)
        {
            if (!channelMatch.IsSuccess)
            {
                return;
            }

            // verify it's a guild message
            SocketTextChannel responseChannel = await this.VerifyGuildChannelAsync(context, cancellationToken).ConfigureAwait(false);

            if (responseChannel == null)
            {
                return;
            }

            // verify user's permissions
            _log.LogTrace("Verifying user {ID} has {Permission} permission in channel {ChannelName} ({ChannelFromID})", channelMatch.User.Id, action.RequiredPermission, channelMatch.Channel.Name, channelMatch.Channel.Id);
            if (!await this.VerifyUserPermissionsAsync(context, channelMatch.Channel, channelMatch.User.Id, action.RequiredPermission, cancellationToken).ConfigureAwait(false))
            {
                return;
            }

            // verify bot's permissions
            _log.LogTrace("Verifying the bot has {Permission} permission in channel {ChannelName} ({ChannelFromID})", action.RequiredPermission, channelMatch.Channel.Name, channelMatch.Channel.Id);
            if (!await this.VerifyUserPermissionsAsync(context, channelMatch.Channel, context.Client.CurrentUser.Id, action.RequiredPermission, cancellationToken).ConfigureAwait(false))
            {
                return;
            }

            // perform the action on the users
            SocketGuildUser[] users          = channelMatch.Channel.Users.ToArray();
            string            channelMention = GetVoiceChannelMention(channelMatch.Channel);

            _log.LogDebug($"{action.ModeWord} {{Count}} users from channel {{ChannelName}} ({{ChannelID}})", users.Length, channelMatch.Channel.Name, channelMatch.Channel.Id);
            RestUserMessage response = await context.ReplyAsync($"{action.ModeWord} {users.Length} user{(users.Length > 1 ? "s" : null)} in {channelMention}.", cancellationToken).ConfigureAwait(false);

            int errorCount = 0;

            foreach (SocketGuildUser user in users)
            {
                try
                {
                    await user.ModifyAsync(action.Action, cancellationToken).ConfigureAwait(false);
                }
                catch { errorCount++; }
            }
            // display confirmation
            StringBuilder builder      = new StringBuilder();
            int           successCount = users.Length - errorCount;

            builder.AppendFormat("{0} user{1} {2} in {3}.", successCount.ToString(), successCount > 1 || successCount == 0 ? "s" : null, action.ActionCompletedWord, channelMention);
            if (errorCount > 0)
            {
                builder.AppendFormat("\nFailed to {3} {0} user{2}. {1}", errorCount.ToString(), this._einherjiOptions.CurrentValue.FailureSymbol, errorCount > 1 ? "s" : null, action.ActionFailedWord);
            }
            await response.ModifyAsync(props => props.Content = builder.ToString(), cancellationToken).ConfigureAwait(false);
        }
Пример #12
0
        private async Task CmdAddModAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            Task CreateInvalidUseResponse()
            => context.ReplyAsync($"{_einherjiOptions.FailureSymbol} Please specify both name and URL of the mod.\nProper usage of this command:\n***{_commandsOptions.Prefix}stellaris mods add <name> | <url>***", cancellationToken);

            if (context.User.Id != _einherjiOptions.AuthorID)
            {
                await context.ReplyAsync($"{_einherjiOptions.FailureSymbol} You can't order me to do that.", cancellationToken).ConfigureAwait(false);

                return;
            }
            if (match.Groups.Count < 3)
            {
                await CreateInvalidUseResponse().ConfigureAwait(false);

                return;
            }

            string name = match.Groups[1].Value.Trim();
            string url  = match.Groups[2].Value.Trim();

            if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(url))
            {
                await CreateInvalidUseResponse().ConfigureAwait(false);

                return;
            }
            if (url.Contains(' ', StringComparison.Ordinal))
            {
                await context.ReplyAsync($"{_einherjiOptions.FailureSymbol} URL can't contain any spaces.", cancellationToken).ConfigureAwait(false);

                return;
            }

            StellarisMod mod = new StellarisMod(name, url);

            _log.LogDebug("Adding stellaris mod {ModName}", mod.Name);
            await _stellarisModsStore.AddAsync(mod, cancellationToken).ConfigureAwait(false);

            await context.ReplyAsync($"{_einherjiOptions.SuccessSymbol} Added mod:\n\n{ModToMessageString(mod)}", cancellationToken).ConfigureAwait(false);
        }
Пример #13
0
        private Task CmdIntelHelpAsync(SocketCommandContext context, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            string       prefix = _commandsOptions.CurrentValue.Prefix;
            EmbedBuilder embed  = new EmbedBuilder()
                                  .AddField("Intel Commands",
                                            $"**{prefix}intel on me** - get intel on yourself\n" +
                                            $"**{prefix}intel on** ***<user ping>*** - get intel on pinged user\n" +
                                            $"**{prefix}intel on guild** - *(guild only)* get intel on current guild");

            return(context.ReplyAsync(null, false, embed.Build(), cancellationToken));
        }
Пример #14
0
        private async Task CmdIntelUserAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            string idString = match.Groups[1].Value;

            if (!ulong.TryParse(idString, out ulong id))
            {
                await context.ReplyAsync($"{_einherjiOptions.CurrentValue.FailureSymbol} Could not parse user ID `{idString}`.", cancellationToken).ConfigureAwait(false);

                return;
            }
            IUser user = await _client.GetUserAsync(id).ConfigureAwait(false);

            if (user == null)
            {
                await context.ReplyAsync($"{_einherjiOptions.CurrentValue.FailureSymbol} Could not find user with ID `{id}`.", cancellationToken).ConfigureAwait(false);

                return;
            }
            await ProcessIntelUserAsync(context, user, cancellationToken).ConfigureAwait(false);
        }
Пример #15
0
        private async Task CmdAddGameAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            if (context.User.Id != _einherjiOptions.CurrentValue.AuthorID)
            {
                await SendInsufficientPermissionsAsync(context.Channel, cancellationToken).ConfigureAwait(false);

                return;
            }
            // get names
            if (match.Groups.Count < 2 || match.Groups[1]?.Length < 1)
            {
                await SendNameAndAliasesRequiredAsync(context.Channel, cancellationToken).ConfigureAwait(false);

                return;
            }
            string[] names = match.Groups[1].Value.Split(_namesSeparator, StringSplitOptions.RemoveEmptyEntries)
                             .Select(name => name.Trim()).Where(name => !string.IsNullOrWhiteSpace(name)).ToArray();
            if (names.Length == 0)
            {
                await SendNameAndAliasesRequiredAsync(context.Channel, cancellationToken).ConfigureAwait(false);

                return;
            }

            // check if game doesn't yet exist
            string       gameName = names.First();
            PatchbotGame game     = await _patchbotGamesStore.GetAsync(gameName, cancellationToken).ConfigureAwait(false);

            if (game == null)
            {
                _log.LogDebug("Creating patchbot game {GameName}", gameName);
                game = new PatchbotGame(names.First(), names.TakeLast(names.Length - 1));
            }
            // if it does, just add new aliases
            else
            {
                _log.LogDebug("Adding {AliasesCount} aliases to patchbot game {GameName}", names.Length, game.Name);
                for (int i = 0; i < names.Length; i++)
                {
                    if (game.Aliases.Contains(names[i], StringComparer.OrdinalIgnoreCase))
                    {
                        continue;
                    }
                    game.Aliases.Add(names[i]);
                }
            }

            await _patchbotGamesStore.SetAsync(game, cancellationToken).ConfigureAwait(false);

            await context.ReplyAsync($"{_einherjiOptions.CurrentValue.SuccessSymbol} Game `{game.Name}` updated.", cancellationToken).ConfigureAwait(false);
        }
Пример #16
0
        private async Task CmdCommunityGoals(SocketCommandContext context, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            if (!this._enabled)
            {
                _log.LogDebug("Unable to handle Elite Dangerous Community Goals command - Inara credentials missing");
                return;
            }
            IEnumerable <CommunityGoal> cgs = await QueryCommunityGoalsAsync(cancellationToken).ConfigureAwait(false);

            foreach (CommunityGoal cg in cgs)
            {
                await context.ReplyAsync(null, false, CommunityGoalToEmbed(cg).Build(), cancellationToken).ConfigureAwait(false);
            }
        }
Пример #17
0
        private async Task CmdRetrieveAccountAsync(SocketCommandContext context, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            _log.LogDebug("Retrieving Netlix account credentials");
            if (context.IsPrivate)
            {
                _log.LogTrace("Aborting Netflix account credentials retrieving: Group only");
                await SendErrorAsync($"{_einherjiOptions.FailureSymbol} You can't do this in private message.\nGo to {GetAllowedChannelsMentionsText()}.", context.Channel).ConfigureAwait(false);

                return;
            }
            SocketGuildUser user = await context.Guild.GetGuildUserAsync(context.User).ConfigureAwait(false);

            if (!_netflixAccountOptions.CanRetrieve(user))
            {
                _log.LogTrace("Aborting Netflix account credentials retrieving: User not privileged");
                await SendErrorAsync($"{_einherjiOptions.FailureSymbol} You need {GetAllowedRolesMentionsText()} role to do this.", context.Channel).ConfigureAwait(false);

                return;
            }
            if (!_netflixAccountOptions.IsChannelAllowed(context.Channel))
            {
                _log.LogTrace("Aborting Netflix account credentials retrieving: Wrong channel");
                await SendErrorAsync($"You can't do this here.\nGo to {GetAllowedChannelsMentionsText()}.", context.Channel).ConfigureAwait(false);

                return;
            }

            // retrieve info from store
            NetflixAccount account = await _netflixAccountStore.GetAsync(cancellationToken).ConfigureAwait(false);

            // create message
            IUser modifiedByUser = null;

            if (account.ModifiedByID != null)
            {
                modifiedByUser = await context.Client.GetUserAsync(account.ModifiedByID.Value).ConfigureAwait(false);
            }
            EmbedBuilder    embed   = CreateConfirmationEmbed(account, modifiedByUser);
            string          text    = this.IsAutoRemoving ? GetAutoremoveText() : null;
            RestUserMessage sentMsg = await context.ReplyAsync(text, false, embed.Build(), cancellationToken).ConfigureAwait(false);

            // auto remove
            if (this.IsAutoRemoving)
            {
                RemoveMessagesDelayed(_netflixAccountOptions.AutoRemoveDelay, cancellationToken, sentMsg, context.Message);
            }
        }
Пример #18
0
        private async Task ProcessIntelUserAsync(SocketCommandContext context, IUser user, CancellationToken cancellationToken)
        {
            UserData userData = await _userDataStore.GetAsync(user.Id, cancellationToken).ConfigureAwait(false);

            EmbedBuilder embed = new EmbedBuilder();

            AddUserInfo(embed, user, userData);
            if (!context.IsPrivate)
            {
                SocketGuildUser guildUser = await context.Guild.GetGuildUserAsync(user.Id).ConfigureAwait(false);

                if (guildUser != null)
                {
                    AddGuildUserInfo(embed, guildUser);
                }
            }
            await context.ReplyAsync(null, false, embed.Build(), cancellationToken).ConfigureAwait(false);
        }
Пример #19
0
        public async Task <User> StartAsync(SocketCommandContext context, DbService db)
        {
            var user = new User
            {
                UserId              = context.User.Id,
                Level               = 1,
                Exp                 = 0,
                TotalExp            = 0,
                Credit              = 0,
                AttackMode          = AttackType.Passive,
                ContinentId         = 1,
                ZoneId              = 1,
                UnspentTalentPoints = 0,
                DamageTalent        = 0,
                HealthTalent        = 0,
                WeaponId            = 1,
                ArmorId             = 2
            };
            await db.Users.AddAsync(user);

            await db.SaveChangesAsync();

            var firstContinent = await db.Continents.FindAsync(1);

            var firstZone = await db.Zones.FindAsync(1);

            await context.ReplyAsync($"Welcome to Wonderland {context.User.Mention}!\n" +
                                     $"You're starting off within the continent {firstContinent.Name} in {firstZone.Name} where you'll face off monsters to gain experience to level up and explore other zones. You can also send troops on missions or do quests to gain experience and loot!\n" +
                                     "For every second level you level up, you'll receive a new talent point which you can spend to increase your health, or damage.\n\n" +
                                     "Now, wait a bit and we'll resume back to the command and below is a list of basic commands to get started!\n" +
                                     "Commands:\n" +
                                     "-Search (Find an opponement)");

            await Task.Delay(2000);

            return(user);
        }
Пример #20
0
        private async Task handler(SocketMessage arg)
        {
            if (!_isReady)
            {
                return;
            }

            var msg = arg as SocketUserMessage;

            if (msg == null)
            {
                return;
            }

            if (msg.Author.IsBot)
            {
                return;
            }

            int argPos = 0;

            if (!msg.HasMentionPrefix(_client.CurrentUser, ref argPos))
            {
                return;
            }

            var context = new SocketCommandContext(_client, msg);

            _logger.Info($"Command ran by {context.User} in {context.Channel.Name} - {context.Message.Content}");

            var result = await _commandService.ExecuteAsync(context, argPos, _dependencyMap, MultiMatchHandling.Best);

            if (result.IsSuccess)
            {
                await _dependencyMap.Get <WelcomeDbContext>().SaveChangesAsync();

                return;
            }

            string response = null;

            switch (result)
            {
            case ParseResult parseResult:
                response = $":warning: There was an error parsing your command: `{parseResult.ErrorReason}`";
                break;

            case PreconditionResult preconditionResult:
                response = $":warning: A prerequisite of your command failed: `{preconditionResult.ErrorReason}`";
                break;

            case ExecuteResult executeResult:
                response = $":warning: Your command failed to execute. If this persists, contact a Discord Host.\n`{executeResult.Exception.Message}`";
                _logger.Error(executeResult.Exception);
                break;
            }

            if (response != null)
            {
                await context.ReplyAsync(response);
            }
        }
Пример #21
0
        private async Task CmdGetAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            // check if command has game name
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            if (match.Groups.Count < 2 || match.Groups[1]?.Length < 1)
            {
                await SendNameRequiredAsync(context.Channel, cancellationToken).ConfigureAwait(false);

                return;
            }

            // get server info
            string     gameName = match.Groups[1].Value.Trim();
            GameServer server   = await _gameServersStore.GetAsync(gameName, cancellationToken).ConfigureAwait(false);

            if (server == null)
            {
                _log.LogDebug("Server for game {Game} not found", gameName);
                await SendServerNotFoundAsync(context.Channel, gameName, cancellationToken).ConfigureAwait(false);

                return;
            }

            // check permissions
            if (!await IsAuthorizedAsync(context, server).ConfigureAwait(false))
            {
                _log.LogTrace("User {UserID} not authorized for server for game {Game} not found", context.User.Id, gameName);
                await SendUnatuthorizedAsync(context.Channel, server, cancellationToken).ConfigureAwait(false);

                return;
            }

            // build server info embed
            EmbedBuilder embed = new EmbedBuilder();

            embed.Title = $"{server.Game} Server Info";
            embed.Color = Color.Blue;
            StringBuilder builder = new StringBuilder();

            if (!string.IsNullOrWhiteSpace(server.RulesURL))
            {
                builder.AppendFormat("Before connecting, please read the [server rules]({0}).\n\n", server.RulesURL);
            }
            builder.AppendFormat("***Address***: `{0}`\n", server.Address);
            if (!string.IsNullOrWhiteSpace(server.Password))
            {
                builder.AppendFormat("***Password***: `{0}`\n", server.Password);
            }
            embed.Description = builder.ToString();

            // send response - directly if PM, or direct to user's PM if in guild
            string       text = this.IsAutoRemoving ? GetAutoremoveText() : null;
            IUserMessage sentMsg;

            if (context.IsPrivate)
            {
                sentMsg = await context.ReplyAsync(text, false, embed.Build(), cancellationToken).ConfigureAwait(false);
            }
            else
            {
                _ = context.InlineReplyAsync($"{_einherjiOptions.SuccessSymbol} I will send you a private message with info on how to connect to the server!");
                Task <IUserMessage> pmTask = context.User.SendMessageAsync(text, false, embed.Build(), new RequestOptions {
                    CancelToken = cancellationToken
                });
                sentMsg = await pmTask.ConfigureAwait(false);
            }

            // auto remove
            if (this.IsAutoRemoving)
            {
                RemoveMessagesDelayed(_gameServersOptions.AutoRemoveDelay, cancellationToken, sentMsg);
            }
        }
Пример #22
0
        private async Task CmdUpdateAccountAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            _log.LogDebug("Updating Netlix account credentials");
            if (context.IsPrivate)
            {
                _log.LogTrace("Aborting Netflix account credentials updating: Group only");
                await SendErrorAsync($"{_einherjiOptions.FailureSymbol} You can't do this in private message.\nGo to {GetAllowedChannelsMentionsText()}.", context.Channel).ConfigureAwait(false);

                return;
            }
            SocketGuildUser user = await context.Guild.GetGuildUserAsync(context.User).ConfigureAwait(false);

            if (!_netflixAccountOptions.CanModify(user))
            {
                _log.LogTrace("Aborting Netflix account credentials updating: User not privileged");
                await SendErrorAsync($"{_einherjiOptions.FailureSymbol} You need {GetAllowedRolesMentionsText()} role to do this.", context.Channel).ConfigureAwait(false);

                return;
            }
            if (!_netflixAccountOptions.IsChannelAllowed(context.Channel))
            {
                _log.LogTrace("Aborting Netflix account credentials updating: Wrong channel");
                await SendErrorAsync($"You can't do this here.\nGo to {GetAllowedChannelsMentionsText()}.", context.Channel).ConfigureAwait(false);

                return;
            }

            // retrieve info from store
            NetflixAccount account = await _netflixAccountStore.GetAsync(cancellationToken).ConfigureAwait(false);

            // update and save
            SetMode mode         = StringToSetMode(match.Groups[1].Value);
            string  value        = match.Groups[2].Value;
            string  responseText = null;

            if (mode == SetMode.Login)
            {
                account.SetLogin(value, context.User.Id);
                responseText = $"{_einherjiOptions.SuccessSymbol} You have set Netflix account login to `{value}`.";
            }
            if (mode == SetMode.Password)
            {
                account.SetPassword(value, context.User.Id);
                responseText = $"{_einherjiOptions.SuccessSymbol} You have set Netflix account password to `{value}`.";
            }

            await _netflixAccountStore.SetAsync(account, cancellationToken).ConfigureAwait(false);

            // create message
            EmbedBuilder embed = CreateConfirmationEmbed(account, context.User);

            embed.WithDescription(responseText);
            string          text    = this.IsAutoRemoving ? GetAutoremoveText() : null;
            RestUserMessage sentMsg = await context.ReplyAsync(text, false, embed.Build(), cancellationToken).ConfigureAwait(false);

            // auto remove
            if (this.IsAutoRemoving)
            {
                RemoveMessagesDelayed(_netflixAccountOptions.AutoRemoveDelay, cancellationToken, sentMsg, context.Message);
            }
        }
Пример #23
0
        private async Task CmdInstanceInfoAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            PiholeOptions   piholeOptions   = _piholeOptions.CurrentValue;
            EinherjiOptions einherjiOptions = _einherjiOptions.CurrentValue;
            string          instanceID      = match.Groups[1].Value;

            // check instance exists
            if (!piholeOptions.Instances.TryGetValue(instanceID, out PiholeInstanceOptions instance))
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Unknown PiHole instance `{instanceID}`.", cancellationToken).ConfigureAwait(false);

                return;
            }
            string instanceName = string.IsNullOrWhiteSpace(instance.DisplayName) ? instanceID : instance.DisplayName;

            // check user is authorized to manage that instance
            if (!instance.IsAuthorized(context.User))
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} You have no permissions to manage PiHole instance `{instanceName}`.", cancellationToken).ConfigureAwait(false);

                return;
            }

            // send notification to user that we're working on it
            RestUserMessage workingNotification = await context.ReplyAsync("Querying pihole API, please wait...", cancellationToken).ConfigureAwait(false);

            EmbedBuilder embed = new EmbedBuilder()
                                 .WithThumbnailUrl("https://upload.wikimedia.org/wikipedia/en/thumb/1/15/Pi-hole_vector_logo.svg/1200px-Pi-hole_vector_logo.svg.png")
                                 .WithDescription($"Information on **{instanceName}** Kathara PiHole instance");

            // add stored instance config
            if (!instance.HideURL)
            {
                embed.AddField("PiHole Address", instance.PiholeURL, false);
            }
            if (instance.AuthorizedUserIDs.Count > 0)
            {
                embed.AddField("Authorized users", string.Join(", ", instance.AuthorizedUserIDs.Select(uid => MentionUtils.MentionUser(uid))), true);
            }
            if (instance.AuthorizedRoleIDs.Count > 0)
            {
                embed.AddField("Authorized roles", string.Join(", ", instance.AuthorizedRoleIDs.Select(rid => MentionUtils.MentionRole(rid))), true);
            }
            if (instance.AuthorizedUserIDs.Count + instance.AuthorizedRoleIDs.Count == 0)
            {
                embed.AddField("Authorized users", "-", true);
            }

            // communicate with pihole API
            _log.LogDebug("Requesting status from Pihole API at {URL} (Instance: {Instance})", instance.PiholeURL, instanceName);
            HttpClient client = _httpClientFactory.CreateClient();

            using (HttpResponseMessage response = await client.GetAsync($"{instance.PiholeURL}/admin/api.php?summary", cancellationToken).ConfigureAwait(false))
            {
                if (!response.IsSuccessStatusCode)
                {
                    embed.WithColor(einherjiOptions.EmbedErrorColor);
                    await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Request to PiHole API failed: {response.ReasonPhrase} ({response.StatusCode})", false, embed.Build(), cancellationToken).ConfigureAwait(false);

                    await workingNotification.DeleteAsync(cancellationToken).ConfigureAwait(false);

                    return;
                }
                string responseContentRaw = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                if (!TryParseJObject(responseContentRaw, out JObject responseContentJson))
                {
                    embed.WithColor(einherjiOptions.EmbedErrorColor);
                    await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Failed to query PiHole. Please refer to bot logs.", false, embed.Build(), cancellationToken).ConfigureAwait(false);

                    await workingNotification.DeleteAsync(cancellationToken).ConfigureAwait(false);

                    _log.LogError("Failed querying PiHole instance {InstanceID}: {ResponseMessage}", instanceName, responseContentRaw);
                    return;
                }

                // deserialize response
                JsonSerializer serializer = JsonSerializer.CreateDefault();
                serializer.Culture = CultureInfo.InvariantCulture;
                PiholeApiStatusResponse data = responseContentJson.ToObject <PiholeApiStatusResponse>(serializer);

                // put into embed
                embed.AddField("Status", data.IsEnabled ? $"{einherjiOptions.SuccessSymbol} Enabled" : $"{einherjiOptions.FailureSymbol} Disabled", false);
                embed.WithColor(data.IsEnabled ? einherjiOptions.EmbedSuccessColor : einherjiOptions.EmbedErrorColor);
                embed.AddField("Domains on block list", data.DomainsBeingBlocked.ToString("N0"), true);
                embed.AddField("DNS queries today", data.DnsQueriesToday.ToString("N0"), true);
                embed.AddField("Ads blocked today", $"{data.AdsBlockedToday:N0} ({data.AdsPercentageToday}%)", true);
                embed.AddField("Unique clients", $"{data.UniqueRecentClients:N0} recently, {data.ClientsEverSeen:N0} all-time", true);
                embed.WithFooter("Gravity last updated");
                embed.WithTimestamp(data.GravityLastUpdated);
            }
            using (HttpResponseMessage response = await client.GetAsync($"{instance.PiholeURL}/admin/api.php?version"))
            {
                if (response.IsSuccessStatusCode &&
                    TryParseJObject(await response.Content.ReadAsStringAsync(), out JObject responseContentJson) &&
                    !string.IsNullOrWhiteSpace(responseContentJson["version"]?.ToString()))
                {
                    embed.AddField("PiHole version", responseContentJson["version"].ToString());
                }
            }

            await context.ReplyAsync(null, false, embed.Build(), cancellationToken).ConfigureAwait(false);

            await workingNotification.DeleteAsync(cancellationToken).ConfigureAwait(false);
        }
        private async Task CmdMoveAllAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            EinherjiOptions options = _einherjiOptions.CurrentValue;

            // verify it's a guild message
            SocketTextChannel channel = await this.VerifyGuildChannelAsync(context, cancellationToken).ConfigureAwait(false);

            if (channel == null)
            {
                return;
            }

            // verify command has proper arguments
            if (match.Groups.Count < 3)
            {
                string prefix = _commandsOptions.CurrentValue.Prefix;
                await context.ReplyAsync($"{options.FailureSymbol} Please specify __both__ channels IDs.\n***{_commandsOptions.CurrentValue.Prefix}move all from <original channel ID> to <target channel ID>***", cancellationToken).ConfigureAwait(false);

                return;
            }

            // verify channels exist
            // we can do both at once, it's okay if user gets warn about both at once, and it just simplifies the code
            SocketVoiceChannel channelFrom = await VerifyValidVoiceChannelAsync(match.Groups[1], context.Guild, context.Channel, cancellationToken).ConfigureAwait(false);

            SocketVoiceChannel channelTo = await VerifyValidVoiceChannelAsync(match.Groups[2], context.Guild, context.Channel, cancellationToken).ConfigureAwait(false);

            if (channelFrom == null || channelTo == null)
            {
                return;
            }

            // verify user can see both channels, and has move permission in both
            _log.LogTrace("Verifying user {ID} has permission to move users between channels {ChannelFromName} ({ChannelFromID}) and {ChannelToName} ({ChannelToID})",
                          context.User.Id, channelFrom.Name, channelFrom.Id, channelTo.Name, channelTo.Id);
            if (!await this.VerifyUserPermissionsAsync(context, channelFrom, context.User.Id, ChannelPermission.MoveMembers, cancellationToken).ConfigureAwait(false) ||
                !await this.VerifyUserPermissionsAsync(context, channelTo, context.User.Id, ChannelPermission.MoveMembers, cancellationToken).ConfigureAwait(false))
            {
                return;
            }

            // verify bot also has permissions
            _log.LogTrace("Verifying the bot has permission to move users between channels {ChannelFromName} ({ChannelFromID}) and {ChannelToName} ({ChannelToID})",
                          channelFrom.Name, channelFrom.Id, channelTo.Name, channelTo.Id);
            if (!await this.VerifyUserPermissionsAsync(context, channelFrom, context.Client.CurrentUser.Id, ChannelPermission.MoveMembers, cancellationToken).ConfigureAwait(false) ||
                !await this.VerifyUserPermissionsAsync(context, channelTo, context.Client.CurrentUser.Id, ChannelPermission.MoveMembers, cancellationToken).ConfigureAwait(false))
            {
                return;
            }

            // move the users
            SocketGuildUser[] users = channelFrom.Users.ToArray();
            string            channelFromMention = GetVoiceChannelMention(channelFrom);
            string            channelToMention   = GetVoiceChannelMention(channelTo);

            _log.LogDebug("Moving {Count} users from channel {ChannelFromName} ({ChannelFromID}) to {ChannelToName} ({ChannelToID})", users.Length, channelFrom.Name, channelFrom.Id, channelTo.Name, channelTo.Id);
            RestUserMessage response = await context.ReplyAsync($"Moving {users.Length} user{(users.Length > 1 ? "s" : null)} from {channelFromMention} to {channelToMention}.", cancellationToken).ConfigureAwait(false);

            int errorCount = 0;

            foreach (SocketGuildUser user in users)
            {
                try
                {
                    await user.ModifyAsync(props => props.Channel = channelTo, cancellationToken).ConfigureAwait(false);
                }
                catch { errorCount++; }
            }
            // display confirmation
            StringBuilder builder      = new StringBuilder();
            int           successCount = users.Length - errorCount;

            builder.AppendFormat("{0} user{3} moved from {1} to {2}.", successCount.ToString(), channelFromMention, channelToMention, successCount > 1 || successCount == 0 ? "s" : null);
            if (errorCount > 0)
            {
                builder.AppendFormat("\nFailed to move {0} user{2}. {1}", errorCount.ToString(), options.FailureSymbol, errorCount > 1 ? "s" : null);
            }
            await response.ModifyAsync(props => props.Content = builder.ToString(), cancellationToken).ConfigureAwait(false);
        }
Пример #25
0
        private async Task CmdDisableAsync(SocketCommandContext context, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(context, this);
            PiholeOptions   piholeOptions   = _piholeOptions.CurrentValue;
            EinherjiOptions einherjiOptions = _einherjiOptions.CurrentValue;
            string          instanceID      = match.Groups[1].Value;

            // check instance exists
            if (!piholeOptions.Instances.TryGetValue(instanceID, out PiholeInstanceOptions instance))
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Unknown PiHole instance `{instanceID}`.", cancellationToken).ConfigureAwait(false);

                return;
            }
            string instanceName = string.IsNullOrWhiteSpace(instance.DisplayName) ? instanceID : instance.DisplayName;

            // check user is authorized to access that instance
            if (!instance.IsAuthorized(context.User))
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} You have no permissions to access PiHole instance `{instanceName}`.", cancellationToken).ConfigureAwait(false);

                return;
            }

            // parse disable time, defaulting to 5 mins
            TimeSpan disableTime = piholeOptions.DefaultDisableTime;

            if (uint.TryParse(match.Groups[2]?.Value, out uint disableMinutes))
            {
                disableTime = TimeSpan.FromMinutes(disableMinutes);
            }
            if (disableTime <= TimeSpan.FromMinutes(1))
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Minimum disable time is 1 minute.", cancellationToken).ConfigureAwait(false);

                return;
            }

            // send notification to user that we're working on it
            RestUserMessage workingNotification = await context.ReplyAsync("Querying pihole API, please wait...", cancellationToken).ConfigureAwait(false);

            // communicate with pihole API
            _log.LogDebug("Disabling Pihole through API at {URL} for {Duration} (Instance: {Instance})", instance.PiholeURL, instanceName, disableTime);
            HttpClient client = _httpClientFactory.CreateClient();

            using HttpResponseMessage response =
                      await client.GetAsync($"{instance.PiholeURL}/admin/api.php?disable={disableMinutes * 60}&auth={instance.AuthToken}", cancellationToken).ConfigureAwait(false);

            if (!response.IsSuccessStatusCode)
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Request to PiHole API failed: {response.ReasonPhrase} ({response.StatusCode})", cancellationToken).ConfigureAwait(false);

                await workingNotification.DeleteAsync(cancellationToken).ConfigureAwait(false);

                return;
            }
            string responseContentRaw = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            if (!TryParseJObject(responseContentRaw, out JObject responseContentJson))
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Failed to disable PiHole. Please refer to bot logs.", cancellationToken).ConfigureAwait(false);

                await workingNotification.DeleteAsync(cancellationToken).ConfigureAwait(false);

                _log.LogError("Failed disabling PiHole instance {InstanceID}: {ResponseMessage}", instanceName, responseContentRaw);
                return;
            }
            if (!string.Equals(responseContentJson["status"]?.ToString(), "disabled", StringComparison.OrdinalIgnoreCase))
            {
                await context.ReplyAsync($"{einherjiOptions.FailureSymbol} Failed to disable PiHole. Please refer to bot logs.", cancellationToken).ConfigureAwait(false);

                await workingNotification.DeleteAsync(cancellationToken).ConfigureAwait(false);

                _log.LogError("Failed disabling PiHole instance {InstanceID}: 'status' is not 'disabled'", instanceName);
                return;
            }

            await context.ReplyAsync($"{einherjiOptions.FailureSymbol} PiHole instance `{instanceName}` has been disabled for {disableTime.TotalMinutes} minutes.", cancellationToken).ConfigureAwait(false);

            await workingNotification.DeleteAsync(cancellationToken).ConfigureAwait(false);
        }
Пример #26
0
        private async Task handler(SocketMessage arg)
        {
            if (!_isReady)
            {
                return;
            }

            var msg = arg as SocketUserMessage;

            if (msg == null)
            {
                return;
            }

            #if BETA
            if (!_ownerIds.Contains(msg.Author.Id))
            {
                return;
            }
            #endif

            if (msg.Author.IsBot)
            {
                return;
            }

            int argPos = 0;

            if (!msg.HasStringPrefix(_prefix, ref argPos))
            {
                return;
            }

            var context = new SocketCommandContext(_client, msg);

            var result = await _commandService.ExecuteAsync(context, argPos, _dependencyMap, MultiMatchHandling.Best);

            _logger.Info($"Command ran by {context.User} in {context.Channel.Name} - {context.Message.Content}");

            if (result.IsSuccess)
            {
                return;
            }


            string response = null;

            switch (result)
            {
            case SearchResult searchResult:
                // "Commnd not found" messages are frowned upon, but if you know your usage environment, this is where you would impliment the logic
                break;

            case ParseResult parseResult:
                response = $":warning: There was an error parsing your command: `{parseResult.ErrorReason}`";
                break;

            case PreconditionResult preconditionResult:
                response = $":warning: A precondition of your command failed: `{preconditionResult.ErrorReason}`";
                break;

            case ExecuteResult executeResult:
                response = $":warning: Your command failed to execute. If this persists, contact the Bot Developer.\n`{executeResult.Exception.Message}`";
                _logger.Error(executeResult.Exception);
                break;
            }

            if (response != null)
            {
                await context.ReplyAsync(response);
            }
        }
Пример #27
0
        public async Task BattleAsync(SocketCommandContext context, User userData, Enemy enemyData, DbService db)
        {
            var zone = await db.Zones.FirstOrDefaultAsync(x => x.Id == userData.ZoneId);

            var user = await BuildCombatUserAsync(context.User, userData, db);

            int lvl;

            if (userData.Level + 3 > zone.HighLevel)
            {
                lvl = zone.HighLevel;
            }
            else
            {
                lvl = userData.Level + 3;
            }
            var enemy = await BuildCombatUserAsync(enemyData, _random.Next(zone.LowLevel, lvl), db);

            var msgLog = new LinkedList <string>();

            msgLog.AddFirst($"{user.Name} VS {enemy.Name}");

            var Sendembed = new EmbedBuilder
            {
                Description = msgLog.ListToString(),
                Color       = Color.Purple,
                Fields      = new List <EmbedFieldBuilder>
                {
                    new EmbedFieldBuilder
                    {
                        Name     = "Your HP",
                        Value    = $"{user.Health - user.DmgTaken}/{user.Health}",
                        IsInline = true
                    },
                    new EmbedFieldBuilder
                    {
                        Name     = "Enemy HP",
                        Value    = $"{enemy.Health - enemy.DmgTaken}/{enemy.Health}",
                        IsInline = true
                    }
                }
            };

            var msg = await context.ReplyAsync(Sendembed);

            var inventory = await db.Inventories.Where(x => x.UserId == context.User.Id).ToListAsync();

            var winner = await CombatAsync(msg, user, enemy, db, msgLog, inventory);

            if (winner.Name == enemy.Name)
            {
                return;
            }
            var exp = _level.AddExpAndCredit(enemyData.Exp + _random.Next(0, enemyData.Credit), enemyData.Credit,
                                             userData,
                                             out var response);
            var embed  = msg.Embeds.First().ToEmbedBuilder();
            var update = false;

            if (exp)
            {
                update = true;
                embed.AddField("Exp", response, true);
            }

            if (enemyData.LootTableIds.Length != 0)
            {
                update = true;
                var loot         = new List <Item>();
                var lootResponse = "";
                if (enemyData.Credit != 0)
                {
                    lootResponse += $"{enemyData.Credit} credit\n";
                }
                var amount = enemyData.LootTableIds.Length > 2 ? 3 : enemyData.LootTableIds.Length;
                for (var i = 0; i < amount; i++)
                {
                    var item = await db.Items.FindAsync(
                        enemyData.LootTableIds.ElementAt(_random.Next(enemyData.LootTableIds.Length)));

                    if (!loot.Contains(item))
                    {
                        loot.Add(item);
                        lootResponse += $"{item.Name}\n";
                        var invItem = inventory.FirstOrDefault(x => x.ItemId == item.Id);
                        if (invItem != null)
                        {
                            if (!item.Unique)
                            {
                                invItem.Amount++;
                            }
                        }
                        else
                        {
                            await db.Inventories.AddAsync(new Inventory
                            {
                                UserId   = context.User.Id,
                                ItemId   = item.Id,
                                Amount   = 1,
                                ItemType = item.ItemType
                            });
                        }
                    }
                    else
                    {
                        i--;
                    }
                }

                embed.AddField("Loot", lootResponse, true);
            }

            if (update)
            {
                await msg.ModifyAsync(x => x.Embed = embed.Build());
            }
            await db.SaveChangesAsync();
        }
Пример #28
0
        private async Task CmdPurgeAsync(SocketCommandContext message, Match match, CancellationToken cancellationToken = default)
        {
            using IDisposable logScope = _log.BeginCommandScope(message, this);
            EinherjiOptions options = _einherjiOptions.CurrentValue;

            if (!(message.Channel is SocketTextChannel channel))
            {
                await message.ReplyAsync($"{options.FailureSymbol} Sir, this command is only applicable in guild channels.", cancellationToken).ConfigureAwait(false);

                return;
            }
            SocketGuildUser user = await message.Guild.GetGuildUserAsync(message.User).ConfigureAwait(false);

            if (!user.GetPermissions(channel).ManageMessages)
            {
                await channel.SendMessageAsync($"{options.FailureSymbol} You can't order me to do that.", cancellationToken).ConfigureAwait(false);

                return;
            }
            SocketGuildUser botUser = await message.Guild.GetGuildUserAsync(message.Client.CurrentUser.Id).ConfigureAwait(false);

            if (!botUser.GetPermissions(channel).ManageMessages)
            {
                await channel.SendMessageAsync($"{options.FailureSymbol} I am missing *Manage Messages* permission in this channel.", cancellationToken).ConfigureAwait(false);

                return;
            }
            if (match.Groups.Count == 1 || match.Groups[1]?.Length < 1)
            {
                await channel.SendMessageAsync($"{options.FailureSymbol} Sir, I need a positive number of messages to take down.", cancellationToken).ConfigureAwait(false);

                return;
            }
            string countString = match.Groups[1].Value;

            if (!int.TryParse(countString, out int count))
            {
                await channel.SendMessageAsync($"{options.FailureSymbol} Sir, `{countString} is not a valid number.", cancellationToken).ConfigureAwait(false);

                return;
            }
            if (count < 0)
            {
                await channel.SendMessageAsync($"{options.FailureSymbol} Sir, how am I supposed to execute removal of {count} messages?.", cancellationToken).ConfigureAwait(false);

                return;
            }

            // start a new task to prevent deletion from blocking gateway task
            _ = Task.Run(async() =>
            {
                try
                {
                    // get last X messages
                    IEnumerable <IMessage> msgs     = await channel.GetMessagesAsync(count + 1, cancellationToken).FlattenAsync().ConfigureAwait(false);
                    RestUserMessage confirmationMsg = null;
                    // bulk can only delete messages not older than 2 weeks
                    DateTimeOffset bulkMaxAge            = DateTimeOffset.UtcNow - TimeSpan.FromDays(14) - TimeSpan.FromSeconds(2);
                    IEnumerable <IMessage> newerMessages = msgs.Where(msg => msg.Timestamp >= bulkMaxAge);
                    IEnumerable <IMessage> olderMessages = msgs.Except(newerMessages);
                    int olderCount  = olderMessages.Count();
                    int actualCount = msgs.Count() - 1;
                    _log.LogDebug("Removing {TotalCount} messages. {BulkIncompatibleCount} messages cannot be removed in bulk", msgs.Count(), olderCount);
                    // first delete bulk-deletable
                    await channel.DeleteMessagesAsync(newerMessages, cancellationToken).ConfigureAwait(false);
                    // delete older msgs one by one
                    if (olderCount > 0)
                    {
                        await SendOrUpdateConfirmationAsync($"You are requesting deletion of {actualCount} messages, {olderCount} of which are older than 2 weeks.\n" +
                                                            "Deleting these messages may take a while due to Discord's rate limiting, so please be patient.").ConfigureAwait(false);
                        foreach (IMessage msg in olderMessages)
                        {
                            await Task.Delay(1500).ConfigureAwait(false);
                            await channel.DeleteMessageAsync(msg, cancellationToken).ConfigureAwait(false);
                        }
                    }
                    await SendOrUpdateConfirmationAsync(actualCount > 0 ?
                                                        $"{options.SuccessSymbol} Sir, your message and {actualCount} previous message{(actualCount > 1 ? "s were" : " was")} taken down." :
                                                        $"{options.SuccessSymbol} Sir, I deleted your message. Specify count greater than 0 to remove more than just that.").ConfigureAwait(false);
                    await Task.Delay(6 * 1000, cancellationToken).ConfigureAwait(false);
                    await channel.DeleteMessageAsync(confirmationMsg, cancellationToken).ConfigureAwait(false);

                    async Task SendOrUpdateConfirmationAsync(string text)
                    {
                        if (confirmationMsg == null)
                        {
                            confirmationMsg = await channel.SendMessageAsync(text, cancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            await confirmationMsg.ModifyAsync(props => props.Content = text, cancellationToken).ConfigureAwait(false);
                        }
                    }
                }
                catch (OperationCanceledException) { }
                catch (Exception ex) when(ex.LogAsError(_log, "Exception occured when purging messages"))
                {
                }
            }, cancellationToken).ConfigureAwait(false);
        }