コード例 #1
0
ファイル: EspeonBot.cs プロジェクト: k-boyle/Espeon
 protected override async ValueTask AfterExecutedAsync(IResult result, DiscordCommandContext context)
 {
     if (result is FailedResult failedResult && !(result is ExecutionFailedResult))
     {
         await ExecutionFailedAsync((EspeonCommandContext)context, failedResult);
     }
 }
コード例 #2
0
ファイル: FetchClanCommand.cs プロジェクト: FAForever/faf-qai
        public override async Task ReplyAsync(DiscordCommandContext ctx, FetchClanResult data)
        {
            var embed = new DiscordEmbedBuilder();
            var desc  = !string.IsNullOrEmpty(data.Clan.Description) ? data.Clan.Description : "-";

            embed.WithTitle($"#{data.Clan.Id} {data.Clan.Name}")
            .WithUrl(data.Clan.URL)
            .WithColor(Context.DostyaRed)
            .AddField("Created", data.Clan.CreatedDate?.ToString("u"), true)
            .AddField("Clan Size", data.Clan.Size.ToString(), true)
            .AddField("Description", desc, false);

            var c = 0;

            foreach (var member in data.Members)
            {
                if (++c == 21 && data.Members.Count > 21)
                {
                    embed.AddField("Other:", $"{data.Members.Count - (c - 1)} more not listed...", true);
                    break;
                }
                else
                {
                    embed.AddField(member.Username, member.JoinDate?.ToShortDateString(), true);
                }
            }

            await ctx.Channel.SendMessageAsync(embed);
        }
コード例 #3
0
        private async Task CommandHandler(SocketMessage msg)
        {
            // Do not respond to bot accounts or system messages.
            if (!(msg is SocketUserMessage message) || msg.Author.IsBot)
            {
                return;
            }

            // Respond to both mentions and your prefix.
            #warning Ensure that this configuration variable is set.
            if (!CommandUtilities.HasPrefix(message.Content, _config["prefix"], out var output))
            {
                return;
            }

            var context = new DiscordCommandContext(_client, message, _services);

            IResult res = await _commands.ExecuteAsync(output, context);

            switch (res)
            {
            case FailedResult fRes:
                _logger.LogError("Command execution failed with reason: {0}", fRes.Reason);
                break;
            }
        }
コード例 #4
0
 public static async Task <bool> CanShowModuleAsync(DiscordCommandContext context, Module module)
 {
     if (!(await module.RunChecksAsync(context).ConfigureAwait(false)).IsSuccessful)
     {
         return(false);
     }
     return(!module.GetType().HasCustomAttribute <HiddenAttribute>());
 }
コード例 #5
0
        // TODO: Figure out how to do night shifts
        public override ValueTask <CheckResult> CheckAsync(DiscordCommandContext context)
        {
            if (DateTime.UtcNow.Hour > StartHour && DateTime.UtcNow.Hour < EndHour)
            {
                return(Success());
            }

            return(Failure($"This command is only usable between {StartHour} Hours and {EndHour} Hours"));
        }
コード例 #6
0
        protected override async ValueTask AfterExecutedAsync(IResult result, DiscordCommandContext ctx0)
        {
            var context = (GarlicBreadCommandContext)ctx0;

            if (!result.IsSuccessful && !(result is CommandNotFoundResult))
            {
                await context.Channel.SendMessageAsync(result.ToString());
            }
        }
コード例 #7
0
        public static IMember?GetCurrentMember(this DiscordCommandContext context)
        {
            if (context.Author == null || context.GuildId == null)
            {
                return(null);
            }

            return((IMember)context.Author);
        }
コード例 #8
0
ファイル: CommandProcessor.cs プロジェクト: Nufflee/NuffBot
        public static async Task ProcessCommand <TUser>(ChatMessage <TUser> chatMessage, Bot bot)
            where TUser : User
        {
            if (chatMessage.Sender.Id == bot.Id)
            {
                return;
            }

            string message = chatMessage.Content;
            string name    = message.TrimStart('!').Split(' ')[0].ToLower();

            DatabaseObject <CommandModel> commandToExecute = await DatabaseHelper.GetCommandByNameOrAlias(name);

            if (!commandToExecute.Exists())
            {
                return;
            }

            CommandContext context = new CommandContext(DiscordBot.CurrentGuild, TwitchBot.CurrentChannel);

            if (chatMessage is DiscordChatMessage discordChatMessage)
            {
                context = new DiscordCommandContext(context, discordChatMessage.Channel);
            }

            if (commandToExecute.Entity.IsStaticCommand)
            {
                Command staticCommands = StaticCommands.First((c) => c.Name == name);

                if (chatMessage.Sender.UserLevel < staticCommands.UserLevel)
                {
                    return;
                }

                staticCommands.DoExecute(chatMessage, bot, context);
            }
            else
            {
                bot.SendMessage(commandToExecute.Entity.Response, context);
            }

            DatabaseObject <CommandMetricsModel> dbMetrics = await DatabaseHelper.GetCommandMetricsByCommand(commandToExecute.Entity);

            if (dbMetrics.Exists())
            {
                dbMetrics.Entity.ExecutionCount++;

                await dbMetrics.UpdateInDatabase(SqliteDatabase.Instance);
            }
            else
            {
                CommandMetricsModel metrics = new CommandMetricsModel(commandToExecute.Entity);

                await metrics.SaveToDatabase(SqliteDatabase.Instance);
            }
        }
コード例 #9
0
ファイル: PlayerCommands.cs プロジェクト: FAForever/faf-qai
        public override Task ReplyAsync(DiscordCommandContext ctx, FetchPlayerStatsResult data)
        {
            List <string> toJoin;

            if (data.OldNames.Count > 5)
            {
                toJoin = data.OldNames.GetRange(0, 5);
                toJoin.Add("...");
            }
            else
            {
                toJoin = data.OldNames;
            }


            var embed = new DiscordEmbedBuilder()
                        .WithColor(Context.DostyaRed)
                        .WithTitle(data.Name)
                        .WithDescription($"**ID: {data.Id}**")
                        .WithColor(DiscordColor.Red);

            if (toJoin.Count != 0)
            {
                embed.AddField("Aliases", string.Join("\n", toJoin));
            }

            if (!(data.LadderStats is null))
            {
                embed.AddField("Ladder:", "```http\n" +
                               $"Rating  :: {data.LadderStats?.Rating.ToString("F0") ?? "0"}\n" +
                               $"Ranking :: {data.LadderStats?.Ranking ?? 0}\n" +
                               $"Games   :: {data.LadderStats?.GamesPlayed ?? 0}\n" +
                               "```");
            }

            if (!(data.GlobalStats is null))
            {
                embed.AddField("Global:", "```http\n" +
                               $"Rating  :: {data.GlobalStats?.Rating.ToString("F0") ?? "0"}\n" +
                               $"Ranking :: {data.GlobalStats?.Ranking ?? 0}\n" +
                               $"Games   :: {data.GlobalStats?.GamesPlayed ?? 0}\n" +
                               "```");
            }

            if (!(data.Clan is null))
            {
                embed.AddField($"Clan: {data.Clan?.Name}", "```http\n" +
                               $"Clan Size :: {data.Clan?.Size ?? 0}\n" +
                               $"URL       :: {data.Clan?.URL ?? "n/a"}\n" +
                               "```");
            }

            return(ctx.Channel.SendMessageAsync(embed: embed));
        }
コード例 #10
0
        public Response Execute(DiscordCommandContext commandContext)
        {
            if (!DiscordUtils.Main.IsUserBotOwner(commandContext.User))
            {
                return(new TextResponse(Response.Type.Error, "This command can only be used by a bot owner."));
            }

            string playingStatus = string.Join(" ", commandContext.Parameters);

            DiscordUtils.Main.BotActivity = new Game(playingStatus, ActivityType.Playing);
            return(new TextResponse(Response.Type.Executed, "Playing status changed."));
        }
コード例 #11
0
ファイル: Program.cs プロジェクト: zielo-hue/ConTracker
        protected override ValueTask AfterExecutedAsync(IResult result, DiscordCommandContext context)
        {
            if (result is CommandOnCooldownResult cooldownResult)
            {
                var cooldownTime = cooldownResult.Cooldowns;
                context.Channel.SendMessageAsync(embed: new LocalEmbedBuilder()
                                                 .WithTitle($"You are on cooldown!")
                                                 .WithColor(Color.Red).Build());
            }

            return(base.AfterExecutedAsync(result, context));
        }
コード例 #12
0
        public static async Task <CustomizableRole> RepairRole(DiscordCommandContext commandContext)
        {
            var user  = commandContext.User;
            var guild = commandContext.Guild;

            DatabaseContext.CustomizableRoles.RemoveRange(
                DatabaseContext.CustomizableRoles.Where(r =>
                                                        r.UserId == user.Id.RawValue && r.GuildId == guild.Id.RawValue));
            await DatabaseContext.SaveChangesAsync();

            return(await CreateRole(commandContext));
        }
コード例 #13
0
        /// <summary>
        /// Handles simple Http-apis for "reaction" commands
        ///
        /// The incoming argument 0 from context is a collection of IMember, but for later purposes
        /// that type is not required, as we simply use IUser's Mention property, as such converting
        /// down to the lower interface acceptable to allow for implicit targetting
        /// </summary>
        /// <param name="context"></param>
        public static async Task DoReaction(DiscordCommandContext context)
        {
            var          client = context.Services.GetRequiredService <HttpClient>();
            List <IUser> users  = ((IUser?[])context.Arguments[0]).Where(x => x != null).ToList() !;

            var embed = (new LocalEmbed())
                        .WithColor(Program.Color);
            var builder    = new LocalMessage();
            var apiCommand = Program.ApiCommands[context.Command.Name];

            // if no members are specified allow for implicit targeting via the reply system
            if (users.Count == 0 &&
                context.Message.ReferencedMessage.HasValue &&
                context.Message.ReferencedMessage.Value != null &&
                context.Message.ReferencedMessage.Value.Author != null)
            {
                users.Add(context.Message.ReferencedMessage.Value.Author);
            }

            // prepare reaction text if needed
            string?text = null;

            if (apiCommand.Actions.Ranges.Count > 0)
            {
                text = apiCommand.Actions.GetValue(users.Count)?.Random();
            }

            // insert the author as the first "mention"
            users = users.Prepend(context.Author).ToList();

            // insert mentions
            if (text != null)
            {
                // ReSharper disable once CoVariantArrayConversion
                text = string.Format(text, users.Select(x => x.Mention).ToArray());
                embed.WithDescription(text);
            }

            var response = await client.GetAsync(apiCommand.Url);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                await new DiscordResponseCommandResult(context, builder.WithEmbed(embed.WithDescription("An error occurred while fetching reaction!")));
                return;
            }

            // decode the json response, nothing else is supported for the time being
            // we also only care for one level of the response as of now.
            var decoded = JsonConvert.DeserializeObject <Dictionary <string, string> >(await response.Content.ReadAsStringAsync());

            embed.WithImageUrl(apiCommand.GetFixedImageUrl(decoded[apiCommand.Path]));
            await new DiscordResponseCommandResult(context, (new LocalMessage()).WithEmbed(embed));
        }
コード例 #14
0
        public static async Task SetRoleName(DiscordCommandContext commandContext, string name)
        {
            var userId  = commandContext.Member.Id.RawValue;
            var guildId = commandContext.Guild.Id.RawValue;
            var roleDto = DatabaseContext.CustomizableRoles.Where(r => r.GuildId == guildId && r.UserId == userId)
                          .FirstOrDefault() ?? CreateRole(commandContext).Result;

            if (!commandContext.Guild.Roles.ContainsKey(roleDto.RoleId))
            {
                roleDto = await RepairRole(commandContext);
            }
            await commandContext.Guild.Roles[roleDto.RoleId].ModifyAsync(r => r.Name = name);
        }
コード例 #15
0
        protected override async ValueTask OnCommandNotFound(DiscordCommandContext context)
        {
            var result = _searchService.GetMostRelevantItem(context.Input.Trim());

            if (result is null)
            {
                await Client.SendMessageAsync(context.ChannelId, new LocalMessageBuilder().WithContent("No results found").Build());
            }
            else
            {
                await Client.SendMessageAsync(context.ChannelId, new LocalMessageBuilder().WithEmbed(result.CreateInfoEmbed()).Build());
            }
        }
コード例 #16
0
        public override async Task ReplyAsync(DiscordCommandContext ctx, UnitDatabaseSerachResult data)
        {
            var embed = new DiscordEmbedBuilder();
            var desc  = data.GeneralData.UnitName is not null ? $@"""{data.GeneralData.UnitName}"" {data.Description}" : data.Description;

            embed.WithAuthor(desc, data.GetUnitDatabaseUrl(), data.GetStrategicIconUrl())
            .WithFooter($"{data.GeneralData.FactionName} - {data.Id}")
            .WithThumbnail(data.GetUnitImageUrl())
            .WithTitle("Click here to open unitDB")
            .WithUrl(data.GetUnitDatabaseUrl())
            .WithColor(data.GetFactionColor());

            await ctx.Channel.SendMessageAsync(embed : embed);
        }
コード例 #17
0
 internal async ValueTask HandleCommandNotFound(DiscordCommandContext context)
 {
     foreach (var service in CommandNotFoundServices)
     {
         try
         {
             await service.OnCommandNotFound(context).ConfigureAwait(false);
         }
         catch (Exception ex)
         {
             Logger.LogError(ex, "An exception occurred while executing {0}.{1}().", service.GetType().Name, nameof(DiscordBotService.OnCommandNotFound));
         }
     }
 }
コード例 #18
0
        public static async Task <CustomizableRole> CreateRole(DiscordCommandContext commandContext)
        {
            var user  = commandContext.User;
            var guild = commandContext.Guild;
            var role  = await guild.CreateRoleAsync();

            DatabaseContext.CustomizableRoles.Add(new CustomizableRole(guild.Id.RawValue, user.Id.RawValue,
                                                                       role.Id.RawValue));
            DatabaseContext.SaveChanges();
            await commandContext.Guild.GrantRoleAsync(user.Id, role.Id);

            await role.ModifyAsync(r => r.Name = $"{user.Name}'s Role");

            return(new CustomizableRole(guild.Id.RawValue, user.Id.RawValue, role.Id.RawValue));
        }
コード例 #19
0
ファイル: DiscordBot.cs プロジェクト: FAForever/faf-qai
        private Task QMmands_MessageCreated(DiscordClient sender, MessageCreateEventArgs e)
        {
            if (e.Author.IsBot)
            {
                return(Task.CompletedTask);                // ignore bots.
            }
            _ = Task.Run(async() =>
            {
                var ctx = new DiscordCommandContext(sender, e, Config.Prefix, _services);

                await _commands.MessageRecivedAsync(ctx, e.Message.Content);
            });

            return(Task.CompletedTask);
        }
コード例 #20
0
ファイル: HelpCommand.cs プロジェクト: Zaexides/ArnoBot
 public Response Execute(DiscordCommandContext commandContext)
 {
     if (helpReferenceSite == null || helpReferenceSite.Equals(string.Empty))
     {
         return(new TextResponse(Response.Type.Error, "The bot owner did not include a help reference site URL."));
     }
     else
     {
         return(new ExtendedResponse(Response.Type.Executed,
                                     new ExtendedResponse.Content.Builder()
                                     .AddParagraph("Help Reference Site:", helpReferenceSite)
                                     .Build()
                                     ));
     }
 }
コード例 #21
0
        public override async Task ReplyAsync(DiscordCommandContext ctx, TwitchStreamsResult data)
        {
            List <string> res = new();

            foreach (var s in data.Streams)
            {
                res.Add($"{s.UserLogin}: [{s.Title}]({s.StreamLink})");
            }

            var output = new DiscordEmbedBuilder()
                         .WithColor(Context.DostyaRed)
                         .WithTitle("Live Streams")
                         .WithUrl("https://www.twitch.tv/directory/game/Supreme%20Commander%3A%20Forged%20Alliance")
                         .WithDescription(string.Join("\n\n", res).Replace("*", "").Replace("_", "").Replace("`", ""));

            await ctx.Channel.SendMessageAsync(output);
        }
コード例 #22
0
        public override async Task ReplyAsync(DiscordCommandContext ctx, MapResult data)
        {
            var embed = new DiscordEmbedBuilder();

            embed.WithTitle("Download map")
            .WithColor(Context.DostyaRed)
            .WithUrl(data.DownloadUrl?.AbsoluteUri.Replace(" ", "%20"))
            .WithAuthor($"{data.Title} (ID #{data.Id})")
            .WithDescription(data.Description)
            .AddField("Size", data.Size, true)
            .AddField("Max Players", data.MaxPlayers.ToString(), true)
            .AddField("Ranked", data.Ranked.ToString(), true)
            .AddField("Created At", data.CreatedAt?.ToString("u"), true)
            .AddField("Author", data.Author)
            .WithImageUrl(data.PreviewUrl?.AbsoluteUri.Replace(" ", "%20"));

            await ctx.Channel.SendMessageAsync(embed);
        }
コード例 #23
0
ファイル: InviteCommand.cs プロジェクト: Zaexides/ArnoBot
 public Response Execute(DiscordCommandContext commandContext)
 {
     return(new TextResponse(Response.Type.Executed,
                             string.Format(INVITE_LINK_FORMAT, commandContext.Self.Id)
                             ));
 }
コード例 #24
0
 public EvalGlobals(DiscordCommandContext context)
 {
     Context = context;
 }
コード例 #25
0
        public async Task <LocalEmbedBuilder> CreateCommandEmbedAsync(Command command, DiscordCommandContext context)
        {
            var embed = new LocalEmbedBuilder
            {
                Title       = "Command information",
                Description =
                    $"{Markdown.Code(command.FullAliases.First())}: {command.Description ?? "No description provided."}",
                Color = Color.Pink
            };

            if (command.Remarks != null)
            {
                embed.Description += " " + command.Remarks;
            }

            if (command.FullAliases.Count > 1)
            {
                embed.AddField("Aliases", string.Join(", ", command.FullAliases.Skip(1)), true);
            }

            if (command.Parameters.Count > 0)
            {
                embed.AddField("Parameters",
                               string.Join("\n", command.Parameters.Select(p => FormatParameter(context, p))));
            }

            if (command.CustomArgumentParserType == null)
            {
                var cExecString =
                    $"{context.Prefix}{command.FullAliases.First()} {string.Join(" ", command.Parameters.Select(a => $"{(a.IsOptional ? "[" : "{")}{a.Name}{(a.IsOptional ? "]" : "}")}"))}";
                embed.AddField("Usage", cExecString);
            }
コード例 #26
0
        protected override async ValueTask AfterExecutedAsync(IResult result, DiscordCommandContext context)
        {
            var ctx = (AatroxCommandContext)context;

            if (result.IsSuccessful)
            {
                await ctx.EndAsync();

                return;
            }

            if (result is CommandNotFoundResult)
            {
                string?cmdName;
                var    index = 0;
                var    split = ctx.Message.Content.Substring(ctx.Prefix.ToString() !.Length)
                               .Split(Separator, StringSplitOptions.RemoveEmptyEntries);

                var maxIndex = split.Length;
                do
                {
                    string toLev = (index == 0 ? "" : Separator) + string.Join(Separator, split.Take(maxIndex));
                    maxIndex--;
                    //toLev += (index == 0 ? "" : Separator) + split[index];

                    cmdName = toLev.Levenshtein(this);
                    index++;
                } while (string.IsNullOrWhiteSpace(cmdName) && index < split.Length);

                if (string.IsNullOrWhiteSpace(cmdName))
                {
                    return;
                }

                maxIndex++;

                string?cmdParams = null;
                while (maxIndex < split.Length)
                {
                    cmdParams += " " + split[maxIndex++];
                }

                var tryResult = await ExecuteAsync(cmdName + cmdParams, ctx);

                if (tryResult.IsSuccessful)
                {
                    return;
                }

                result = tryResult;
            }

            await ctx.EndAsync();

            var str = new StringBuilder();

            switch (result)
            {
            case ChecksFailedResult err:
                str.AppendLine("The following check(s) failed:");
                foreach (var(check, error) in err.FailedChecks)
                {
                    str.AppendLine($"[`{(check as AatroxCheckAttribute)?.Name ?? check.GetType().Name}`]: `{error}`");
                }
                break;

            case TypeParseFailedResult err:
                str.AppendLine(err.Reason);
                break;

            case ArgumentParseFailedResult _:
                str.AppendLine($"The syntax of the command `{ctx.Command.FullAliases[0]}` was wrong.");
                break;

            case OverloadsFailedResult err:
                str.AppendLine($"I can't find any valid overload for the command `{ctx.Command.Name}`.");
                foreach (var overload in err.FailedOverloads)
                {
                    str.AppendLine($"[`{overload.Key.Name}`] -> `{overload.Value.Reason}`");
                }
                break;

            case ParameterChecksFailedResult err:
                str.AppendLine("The following parameter check(s) failed:");
                foreach (var(check, error) in err.FailedChecks)
                {
                    str.AppendLine($"[`{check.Parameter.Name}`]: `{error}`");
                }
                break;

            case ExecutionFailedResult _:     //this should be handled in the CommandErrored event or in the Custom Result case.
            case CommandNotFoundResult _:     //this is handled at the beginning of this method with levenshtein thing.
                break;

            case CommandOnCooldownResult err:
                var remainingTime = err.Cooldowns.OrderByDescending(x => x.RetryAfter).FirstOrDefault();
                str.AppendLine($"You're being rate limited! Please retry after {remainingTime.RetryAfter.Humanize()}.");
                break;

            default:
                str.AppendLine($"Unknown error: {result}");
                break;
            }

            if (str.Length == 0)
            {
                return;
            }

            var embed = new LocalEmbedBuilder
            {
                Color = _configuration.DefaultEmbedColor,
                Title = "Something went wrong!"
            };

            embed.WithFooter($"Type '{ctx.Prefix}help {ctx.Command?.FullAliases[0] ?? ctx.Command?.FullAliases[0] ?? ""}' for more information.");

            embed.AddField("__Command/Module__", ctx.Command?.Name ?? ctx.Command?.Module?.Name ?? "Unknown command...", true);
            embed.AddField("__Author__", ctx.User.FullName(), true);
            embed.AddField("__Error(s)__", str.ToString());

            _logger.Warn($"{ctx.User.Id} - {ctx.Guild.Id} ::> Command errored: {ctx.Command?.Name ?? "-unknown command-"}");
            await ctx.Channel.SendMessageAsync("", false, embed.Build());

            await ctx.DisposeAsync();
        }
コード例 #27
0
 public YieldDisposable(DiscordCommandContext context)
 {
     _context = context;
 }
コード例 #28
0
        public override ValueTask <TypeParserResult <FromUntilParameters> > ParseAsync(Parameter parameter, string value, DiscordCommandContext context)
        {
            string[] parameters = value.Split(new[] { " until ", " to " }, StringSplitOptions.RemoveEmptyEntries);
            if (parameters.Length != 2)
            {
                return(Failure("Please provide two valid DateTimes separated by \"until\" or \"to\". (eg. \"2pm until 5:30pm\")"));
            }

            string startsValue  = parameters[0];
            string expiresValue = parameters[1];

            if (DateTime.TryParse(startsValue, out DateTime starts) &&
                DateTime.TryParse(expiresValue, out DateTime expires))
            {
                starts  = starts.ToUniversalTime();
                expires = expires.ToUniversalTime();
                if (starts < DateTime.UtcNow || expires < DateTime.UtcNow)
                {
                    return(Failure("Both DateTimes must be in the future."));
                }
                if (starts < expires)
                {
                    return(Success(new FromUntilParameters(starts, expires)));
                }
                else
                {
                    return(Failure("The first DateTime must be earlier than the second DateTime."));
                }
            }
            else
            {
                return(Failure("Please provide two valid DateTimes separated by \"until\" or \"to\". (eg. \"2pm until 5:30pm\")"));
            }
        }
コード例 #29
0
 /// <inheritdoc/>
 public override ValueTask <TypeParserResult <Color> > ParseAsync(Parameter parameter, string value, DiscordCommandContext context)
 {
     // Checks for the following hex formats:
     // #FFF, #FFFFFF, 0xFFFFFF
     if (value.Length > 2 &&
         (value[0] == '#' && (value.Length == 4 || value.Length == 7) ||
          value[0] == '0' && (value[1] == 'x' || value[1] == 'X') && value.Length <= 8))
     {
         var valueSpan = value.AsSpan();
         if (valueSpan[0] == '#')
         {
             valueSpan = valueSpan[1..];
コード例 #30
0
 public override ValueTask <CheckResult> CheckAsync(object argument, DiscordCommandContext context)
 => Uri.IsWellFormedUriString(argument as string, UriKind.Absolute) ?
 Success() : Failure("The provided argument must be a url.");