From cd07022b2bb28743f1df8939f0c2aa3627e0d99b Mon Sep 17 00:00:00 2001 From: Robin Bourachot Date: Sun, 27 Mar 2022 21:30:15 +0200 Subject: [PATCH] rework: slash commands and components --- .dockerignore | 0 .env.example | 1 - .eslintrc | 0 .github/ISSUE_TEMPLATE/bug_report.md | 0 .github/ISSUE_TEMPLATE/feature_request.md | 0 .gitignore | 0 Dockerfile | 0 LICENSE | 0 README.md | 0 assets/data/actiontext.json | 0 assets/data/aldebaranPermissions.json | 0 assets/data/categories.json | 0 assets/data/drpg/bases.json | 0 assets/data/drpg/itemList.json | 0 assets/data/drpg/locations.json | 0 assets/data/drpgbasexp.json | 0 assets/data/drpgquestinfo.json | 0 assets/data/imageurls.json | 0 assets/data/staffRoles.json | 0 assets/data/variables.json | 0 assets/emojis/fish.png | Bin assets/emojis/leaves.png | Bin assets/emojis/pickaxe.png | Bin assets/emojis/tree.png | Bin assets/fonts/Exo2-Regular.ttf | Bin assets/locales/en.json | 0 assets/locales/fr.json | 0 config/aldebaranTeam.json | 0 config/presence.json | 0 docker-compose.yml | 0 package.json | 2 +- src/api/api.ts | 0 src/api/graphql/schema.graphql | 0 src/api/graphql/types/PageInfo.ts | 0 src/api/graphql/types/SocialProfile.ts | 0 .../types/common/DiscordStructWithSettings.ts | 0 src/api/graphql/types/guild/Guild.ts | 0 .../graphql/types/guild/GuildsConnection.ts | 0 .../types/guild/GuildsConnectionEdge.ts | 0 src/api/graphql/types/user/User.ts | 0 src/api/graphql/types/user/UsersConnection.ts | 0 .../graphql/types/user/UsersConnectionEdge.ts | 0 src/api/graphql/utils/fetchDBValue.ts | 0 src/api/graphql/utils/fetchDSMValue.ts | 0 src/api/interfaces/OAuth2Client.ts | 0 src/api/middlewares/oauth2/model.ts | 0 src/api/public/css/style.css | 0 src/api/public/img/alde.png | Bin src/api/public/img/aldebg.png | Bin src/api/routes/discord/callback.ts | 0 src/api/routes/oauth/authorize.ts | 0 src/api/routes/oauth/token.ts | 0 src/api/util/Constants.ts | 0 src/api/util/validateSession.ts | 0 src/api/views/authorize.pug | 0 src/bot.ts | 0 src/commands/commands.ts | 23 +- src/commands/developer/admin.ts | 11 +- src/commands/developer/admin/mod.ts | 26 +- src/commands/developer/admin/restart.ts | 2 +- src/commands/developer/admin/serverlist.ts | 8 +- src/commands/developer/admin/setperm.ts | 34 +-- src/commands/developer/admin/timeout.ts | 12 +- src/commands/developer/admin/view.ts | 25 +- src/commands/drpg/glead.ts | 39 ++- src/commands/drpg/gold.ts | 99 ++++---- src/commands/drpg/plant.ts | 25 +- src/commands/drpg/plantcalc.ts | 57 +++-- src/commands/drpg/skills.ts | 11 +- src/commands/drpg/stats.ts | 17 +- src/commands/drpg/trap.ts | 14 +- src/commands/drpg/upgradecalc.ts | 26 +- src/commands/drpg/walls.ts | 239 ++++++++---------- src/commands/drpg/weapon.ts | 19 +- src/commands/drpg/xp.ts | 119 +++++---- src/commands/fun/8ball.ts | 25 +- src/commands/fun/emojilist.ts | 4 +- src/commands/fun/fact.ts | 2 +- src/commands/fun/kaomoji.ts | 2 +- src/commands/fun/owoify.ts | 10 +- src/commands/fun/say.ts | 15 +- src/commands/fun/timecompletion.ts | 2 +- src/commands/games/rps.ts | 183 +++++++------- src/commands/general/avatar.ts | 11 +- src/commands/general/bstats.ts | 2 +- src/commands/general/bugreport.ts | 20 +- src/commands/general/commands.ts | 45 ++-- src/commands/general/credits.ts | 2 +- src/commands/general/help.ts | 42 +-- src/commands/general/info.ts | 9 +- src/commands/general/invite.ts | 28 +- src/commands/general/ping.ts | 23 +- src/commands/general/profile.ts | 17 +- src/commands/general/suggest.ts | 24 +- src/commands/general/time.ts | 12 +- src/commands/general/user.ts | 37 ++- src/commands/image/birb.ts | 8 +- src/commands/image/bunny.ts | 2 +- src/commands/image/cat.ts | 2 +- src/commands/image/cuteag.ts | 24 -- src/commands/image/dog.ts | 2 +- src/commands/image/duck.ts | 2 +- src/commands/image/hedgehog.ts | 2 +- src/commands/image/lizard.ts | 4 +- src/commands/image/neko.ts | 4 +- src/commands/image/panda.ts | 2 +- src/commands/image/pepe.ts | 2 +- src/commands/image/randimal.ts | 2 +- src/commands/image/rcgp.ts | 24 ++ src/commands/nsfw/lewd.ts | 7 +- src/commands/nsfw/xboobs.ts | 4 +- src/commands/nsfw/xkitty.ts | 4 +- src/commands/nsfw/xlesbian.ts | 4 +- src/commands/nsfw/xneko.ts | 4 +- src/commands/nsfw/xrandom.ts | 4 +- src/commands/osu!/osu.ts | 18 +- src/commands/osu!/osubest.ts | 18 +- src/commands/osu!/osumap.ts | 3 +- src/commands/osu!/osurecent.ts | 18 +- src/commands/settings/enabledrpg.ts | 115 ++++----- src/commands/settings/gconfig.ts | 65 ++--- src/commands/settings/setprofile.ts | 40 ++- src/commands/settings/uconfig.ts | 124 ++++----- src/commands/social/poke.ts | 4 +- src/commands/social/tickle.ts | 15 +- src/commands/utilities/curconv.ts | 30 +-- src/commands/utilities/math.ts | 43 ++-- src/commands/utilities/translate.ts | 76 ------ src/events/interactionCreate.ts | 14 + src/events/message.ts | 66 ++--- src/events/ready.ts | 2 +- src/global.d.ts | 0 src/groups/Command.ts | 55 ++-- src/groups/DRPGCommand.ts | 0 src/groups/DeveloperCommand.ts | 0 src/groups/FunCommand.ts | 0 src/groups/GamesCommand.ts | 0 src/groups/ImageCommand.ts | 0 src/groups/NSFWCommand.ts | 2 +- src/groups/OsuCommand.ts | 0 src/groups/SettingsCommand.ts | 0 src/groups/SocialCommand.ts | 5 +- src/groups/UtilitiesCommand.ts | 0 src/groups/multi/NekoslifeSubcategory.ts | 2 +- src/handlers/CommandHandler.ts | 120 ++++----- src/handlers/DatabaseProvider.ts | 0 src/handlers/GenericDatabaseProvider.ts | 0 src/interfaces/Arg.ts | 14 - src/interfaces/Command.ts | 21 +- src/interfaces/DiscordRPG.ts | 0 .../aldebaran/AldebaranPermissions.ts | 0 .../aldebaran/CustomGuildManager.ts | 0 .../aldebaran/CustomProfileManager.ts | 0 src/structures/aldebaran/CustomUserManager.ts | 0 src/structures/aldebaran/MessageContext.ts | 181 ------------- src/structures/aldebaran/SocialProfile.ts | 0 .../contexts/DiscordMessageContext.ts | 94 +++++++ .../contexts/DiscordSlashMessageContext.ts | 103 ++++++++ src/structures/contexts/MessageContext.ts | 54 ++++ src/structures/djs/Client.ts | 13 + src/structures/djs/Guild.ts | 0 src/structures/djs/User.ts | 4 + src/utils/Args.ts | 155 ++++++++++++ src/utils/Constants.ts | 4 + src/utils/Methods.ts | 19 +- src/utils/bots/DiscordRPG.ts | 4 +- src/utils/executeSocial.ts | 21 +- src/utils/osu!/ppv2Results.ts | 0 src/utils/osu!/retrieveBeatmapFile.ts | 0 src/utils/timer/DiscordRPG/adv.ts | 42 ++- src/utils/timer/DiscordRPG/padv.ts | 40 ++- src/utils/timer/DiscordRPG/sides.ts | 54 ++-- tsconfig.json | 0 173 files changed, 1658 insertions(+), 1431 deletions(-) mode change 100644 => 100755 .dockerignore mode change 100644 => 100755 .env.example mode change 100644 => 100755 .eslintrc mode change 100644 => 100755 .github/ISSUE_TEMPLATE/bug_report.md mode change 100644 => 100755 .github/ISSUE_TEMPLATE/feature_request.md mode change 100644 => 100755 .gitignore mode change 100644 => 100755 Dockerfile mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 assets/data/actiontext.json mode change 100644 => 100755 assets/data/aldebaranPermissions.json mode change 100644 => 100755 assets/data/categories.json mode change 100644 => 100755 assets/data/drpg/bases.json mode change 100644 => 100755 assets/data/drpg/itemList.json mode change 100644 => 100755 assets/data/drpg/locations.json mode change 100644 => 100755 assets/data/drpgbasexp.json mode change 100644 => 100755 assets/data/drpgquestinfo.json mode change 100644 => 100755 assets/data/imageurls.json mode change 100644 => 100755 assets/data/staffRoles.json mode change 100644 => 100755 assets/data/variables.json mode change 100644 => 100755 assets/emojis/fish.png mode change 100644 => 100755 assets/emojis/leaves.png mode change 100644 => 100755 assets/emojis/pickaxe.png mode change 100644 => 100755 assets/emojis/tree.png mode change 100644 => 100755 assets/fonts/Exo2-Regular.ttf mode change 100644 => 100755 assets/locales/en.json mode change 100644 => 100755 assets/locales/fr.json mode change 100644 => 100755 config/aldebaranTeam.json mode change 100644 => 100755 config/presence.json mode change 100644 => 100755 docker-compose.yml mode change 100644 => 100755 src/api/api.ts mode change 100644 => 100755 src/api/graphql/schema.graphql mode change 100644 => 100755 src/api/graphql/types/PageInfo.ts mode change 100644 => 100755 src/api/graphql/types/SocialProfile.ts mode change 100644 => 100755 src/api/graphql/types/common/DiscordStructWithSettings.ts mode change 100644 => 100755 src/api/graphql/types/guild/Guild.ts mode change 100644 => 100755 src/api/graphql/types/guild/GuildsConnection.ts mode change 100644 => 100755 src/api/graphql/types/guild/GuildsConnectionEdge.ts mode change 100644 => 100755 src/api/graphql/types/user/User.ts mode change 100644 => 100755 src/api/graphql/types/user/UsersConnection.ts mode change 100644 => 100755 src/api/graphql/types/user/UsersConnectionEdge.ts mode change 100644 => 100755 src/api/graphql/utils/fetchDBValue.ts mode change 100644 => 100755 src/api/graphql/utils/fetchDSMValue.ts mode change 100644 => 100755 src/api/interfaces/OAuth2Client.ts mode change 100644 => 100755 src/api/middlewares/oauth2/model.ts mode change 100644 => 100755 src/api/public/css/style.css mode change 100644 => 100755 src/api/public/img/alde.png mode change 100644 => 100755 src/api/public/img/aldebg.png mode change 100644 => 100755 src/api/routes/discord/callback.ts mode change 100644 => 100755 src/api/routes/oauth/authorize.ts mode change 100644 => 100755 src/api/routes/oauth/token.ts mode change 100644 => 100755 src/api/util/Constants.ts mode change 100644 => 100755 src/api/util/validateSession.ts mode change 100644 => 100755 src/api/views/authorize.pug mode change 100644 => 100755 src/bot.ts mode change 100644 => 100755 src/commands/commands.ts mode change 100644 => 100755 src/commands/developer/admin.ts mode change 100644 => 100755 src/commands/developer/admin/mod.ts mode change 100644 => 100755 src/commands/developer/admin/restart.ts mode change 100644 => 100755 src/commands/developer/admin/serverlist.ts mode change 100644 => 100755 src/commands/developer/admin/setperm.ts mode change 100644 => 100755 src/commands/developer/admin/timeout.ts mode change 100644 => 100755 src/commands/developer/admin/view.ts mode change 100644 => 100755 src/commands/drpg/glead.ts mode change 100644 => 100755 src/commands/drpg/gold.ts mode change 100644 => 100755 src/commands/drpg/plant.ts mode change 100644 => 100755 src/commands/drpg/plantcalc.ts mode change 100644 => 100755 src/commands/drpg/skills.ts mode change 100644 => 100755 src/commands/drpg/stats.ts mode change 100644 => 100755 src/commands/drpg/trap.ts mode change 100644 => 100755 src/commands/drpg/upgradecalc.ts mode change 100644 => 100755 src/commands/drpg/walls.ts mode change 100644 => 100755 src/commands/drpg/weapon.ts mode change 100644 => 100755 src/commands/drpg/xp.ts mode change 100644 => 100755 src/commands/fun/8ball.ts mode change 100644 => 100755 src/commands/fun/emojilist.ts mode change 100644 => 100755 src/commands/fun/fact.ts mode change 100644 => 100755 src/commands/fun/kaomoji.ts mode change 100644 => 100755 src/commands/fun/owoify.ts mode change 100644 => 100755 src/commands/fun/say.ts mode change 100644 => 100755 src/commands/fun/timecompletion.ts mode change 100644 => 100755 src/commands/games/rps.ts mode change 100644 => 100755 src/commands/general/avatar.ts mode change 100644 => 100755 src/commands/general/bstats.ts mode change 100644 => 100755 src/commands/general/bugreport.ts mode change 100644 => 100755 src/commands/general/commands.ts mode change 100644 => 100755 src/commands/general/credits.ts mode change 100644 => 100755 src/commands/general/help.ts mode change 100644 => 100755 src/commands/general/info.ts mode change 100644 => 100755 src/commands/general/invite.ts mode change 100644 => 100755 src/commands/general/ping.ts mode change 100644 => 100755 src/commands/general/profile.ts mode change 100644 => 100755 src/commands/general/suggest.ts mode change 100644 => 100755 src/commands/general/time.ts mode change 100644 => 100755 src/commands/general/user.ts mode change 100644 => 100755 src/commands/image/birb.ts mode change 100644 => 100755 src/commands/image/bunny.ts mode change 100644 => 100755 src/commands/image/cat.ts delete mode 100644 src/commands/image/cuteag.ts mode change 100644 => 100755 src/commands/image/dog.ts mode change 100644 => 100755 src/commands/image/duck.ts mode change 100644 => 100755 src/commands/image/hedgehog.ts mode change 100644 => 100755 src/commands/image/lizard.ts mode change 100644 => 100755 src/commands/image/neko.ts mode change 100644 => 100755 src/commands/image/panda.ts mode change 100644 => 100755 src/commands/image/pepe.ts mode change 100644 => 100755 src/commands/image/randimal.ts create mode 100755 src/commands/image/rcgp.ts mode change 100644 => 100755 src/commands/nsfw/lewd.ts mode change 100644 => 100755 src/commands/nsfw/xboobs.ts mode change 100644 => 100755 src/commands/nsfw/xkitty.ts mode change 100644 => 100755 src/commands/nsfw/xlesbian.ts mode change 100644 => 100755 src/commands/nsfw/xneko.ts mode change 100644 => 100755 src/commands/nsfw/xrandom.ts mode change 100644 => 100755 src/commands/osu!/osu.ts mode change 100644 => 100755 src/commands/osu!/osubest.ts mode change 100644 => 100755 src/commands/osu!/osumap.ts mode change 100644 => 100755 src/commands/osu!/osurecent.ts mode change 100644 => 100755 src/commands/settings/enabledrpg.ts mode change 100644 => 100755 src/commands/settings/gconfig.ts mode change 100644 => 100755 src/commands/settings/setprofile.ts mode change 100644 => 100755 src/commands/settings/uconfig.ts mode change 100644 => 100755 src/commands/social/poke.ts mode change 100644 => 100755 src/commands/social/tickle.ts mode change 100644 => 100755 src/commands/utilities/curconv.ts mode change 100644 => 100755 src/commands/utilities/math.ts delete mode 100644 src/commands/utilities/translate.ts create mode 100755 src/events/interactionCreate.ts mode change 100644 => 100755 src/events/message.ts mode change 100644 => 100755 src/events/ready.ts mode change 100644 => 100755 src/global.d.ts mode change 100644 => 100755 src/groups/Command.ts mode change 100644 => 100755 src/groups/DRPGCommand.ts mode change 100644 => 100755 src/groups/DeveloperCommand.ts mode change 100644 => 100755 src/groups/FunCommand.ts mode change 100644 => 100755 src/groups/GamesCommand.ts mode change 100644 => 100755 src/groups/ImageCommand.ts mode change 100644 => 100755 src/groups/NSFWCommand.ts mode change 100644 => 100755 src/groups/OsuCommand.ts mode change 100644 => 100755 src/groups/SettingsCommand.ts mode change 100644 => 100755 src/groups/SocialCommand.ts mode change 100644 => 100755 src/groups/UtilitiesCommand.ts mode change 100644 => 100755 src/groups/multi/NekoslifeSubcategory.ts mode change 100644 => 100755 src/handlers/CommandHandler.ts mode change 100644 => 100755 src/handlers/DatabaseProvider.ts mode change 100644 => 100755 src/handlers/GenericDatabaseProvider.ts delete mode 100644 src/interfaces/Arg.ts mode change 100644 => 100755 src/interfaces/Command.ts mode change 100644 => 100755 src/interfaces/DiscordRPG.ts mode change 100644 => 100755 src/structures/aldebaran/AldebaranPermissions.ts mode change 100644 => 100755 src/structures/aldebaran/CustomGuildManager.ts mode change 100644 => 100755 src/structures/aldebaran/CustomProfileManager.ts mode change 100644 => 100755 src/structures/aldebaran/CustomUserManager.ts delete mode 100644 src/structures/aldebaran/MessageContext.ts mode change 100644 => 100755 src/structures/aldebaran/SocialProfile.ts create mode 100755 src/structures/contexts/DiscordMessageContext.ts create mode 100755 src/structures/contexts/DiscordSlashMessageContext.ts create mode 100755 src/structures/contexts/MessageContext.ts mode change 100644 => 100755 src/structures/djs/Client.ts mode change 100644 => 100755 src/structures/djs/Guild.ts mode change 100644 => 100755 src/structures/djs/User.ts create mode 100755 src/utils/Args.ts mode change 100644 => 100755 src/utils/Constants.ts mode change 100644 => 100755 src/utils/Methods.ts mode change 100644 => 100755 src/utils/bots/DiscordRPG.ts mode change 100644 => 100755 src/utils/executeSocial.ts mode change 100644 => 100755 src/utils/osu!/ppv2Results.ts mode change 100644 => 100755 src/utils/osu!/retrieveBeatmapFile.ts mode change 100644 => 100755 src/utils/timer/DiscordRPG/adv.ts mode change 100644 => 100755 src/utils/timer/DiscordRPG/padv.ts mode change 100644 => 100755 src/utils/timer/DiscordRPG/sides.ts mode change 100644 => 100755 tsconfig.json diff --git a/.dockerignore b/.dockerignore old mode 100644 new mode 100755 diff --git a/.env.example b/.env.example old mode 100644 new mode 100755 index 082333ab..5a91322d --- a/.env.example +++ b/.env.example @@ -17,7 +17,6 @@ API_OMDB= API_OSU= API_PEXELS= API_TENOR= -API_YANDEX= MYSQL_HOST= MYSQL_USER= diff --git a/.eslintrc b/.eslintrc old mode 100644 new mode 100755 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md old mode 100644 new mode 100755 diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/Dockerfile b/Dockerfile old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/assets/data/actiontext.json b/assets/data/actiontext.json old mode 100644 new mode 100755 diff --git a/assets/data/aldebaranPermissions.json b/assets/data/aldebaranPermissions.json old mode 100644 new mode 100755 diff --git a/assets/data/categories.json b/assets/data/categories.json old mode 100644 new mode 100755 diff --git a/assets/data/drpg/bases.json b/assets/data/drpg/bases.json old mode 100644 new mode 100755 diff --git a/assets/data/drpg/itemList.json b/assets/data/drpg/itemList.json old mode 100644 new mode 100755 diff --git a/assets/data/drpg/locations.json b/assets/data/drpg/locations.json old mode 100644 new mode 100755 diff --git a/assets/data/drpgbasexp.json b/assets/data/drpgbasexp.json old mode 100644 new mode 100755 diff --git a/assets/data/drpgquestinfo.json b/assets/data/drpgquestinfo.json old mode 100644 new mode 100755 diff --git a/assets/data/imageurls.json b/assets/data/imageurls.json old mode 100644 new mode 100755 diff --git a/assets/data/staffRoles.json b/assets/data/staffRoles.json old mode 100644 new mode 100755 diff --git a/assets/data/variables.json b/assets/data/variables.json old mode 100644 new mode 100755 diff --git a/assets/emojis/fish.png b/assets/emojis/fish.png old mode 100644 new mode 100755 diff --git a/assets/emojis/leaves.png b/assets/emojis/leaves.png old mode 100644 new mode 100755 diff --git a/assets/emojis/pickaxe.png b/assets/emojis/pickaxe.png old mode 100644 new mode 100755 diff --git a/assets/emojis/tree.png b/assets/emojis/tree.png old mode 100644 new mode 100755 diff --git a/assets/fonts/Exo2-Regular.ttf b/assets/fonts/Exo2-Regular.ttf old mode 100644 new mode 100755 diff --git a/assets/locales/en.json b/assets/locales/en.json old mode 100644 new mode 100755 diff --git a/assets/locales/fr.json b/assets/locales/fr.json old mode 100644 new mode 100755 diff --git a/config/aldebaranTeam.json b/config/aldebaranTeam.json old mode 100644 new mode 100755 diff --git a/config/presence.json b/config/presence.json old mode 100644 new mode 100755 diff --git a/docker-compose.yml b/docker-compose.yml old mode 100644 new mode 100755 diff --git a/package.json b/package.json index bed837eb..70064d40 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aldebaran", - "version": "3.1.0", + "version": "3.2.0", "description": "Utility", "main": "src/app.ts", "dependencies": { diff --git a/src/api/api.ts b/src/api/api.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/schema.graphql b/src/api/graphql/schema.graphql old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/PageInfo.ts b/src/api/graphql/types/PageInfo.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/SocialProfile.ts b/src/api/graphql/types/SocialProfile.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/common/DiscordStructWithSettings.ts b/src/api/graphql/types/common/DiscordStructWithSettings.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/guild/Guild.ts b/src/api/graphql/types/guild/Guild.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/guild/GuildsConnection.ts b/src/api/graphql/types/guild/GuildsConnection.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/guild/GuildsConnectionEdge.ts b/src/api/graphql/types/guild/GuildsConnectionEdge.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/user/User.ts b/src/api/graphql/types/user/User.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/user/UsersConnection.ts b/src/api/graphql/types/user/UsersConnection.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/types/user/UsersConnectionEdge.ts b/src/api/graphql/types/user/UsersConnectionEdge.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/utils/fetchDBValue.ts b/src/api/graphql/utils/fetchDBValue.ts old mode 100644 new mode 100755 diff --git a/src/api/graphql/utils/fetchDSMValue.ts b/src/api/graphql/utils/fetchDSMValue.ts old mode 100644 new mode 100755 diff --git a/src/api/interfaces/OAuth2Client.ts b/src/api/interfaces/OAuth2Client.ts old mode 100644 new mode 100755 diff --git a/src/api/middlewares/oauth2/model.ts b/src/api/middlewares/oauth2/model.ts old mode 100644 new mode 100755 diff --git a/src/api/public/css/style.css b/src/api/public/css/style.css old mode 100644 new mode 100755 diff --git a/src/api/public/img/alde.png b/src/api/public/img/alde.png old mode 100644 new mode 100755 diff --git a/src/api/public/img/aldebg.png b/src/api/public/img/aldebg.png old mode 100644 new mode 100755 diff --git a/src/api/routes/discord/callback.ts b/src/api/routes/discord/callback.ts old mode 100644 new mode 100755 diff --git a/src/api/routes/oauth/authorize.ts b/src/api/routes/oauth/authorize.ts old mode 100644 new mode 100755 diff --git a/src/api/routes/oauth/token.ts b/src/api/routes/oauth/token.ts old mode 100644 new mode 100755 diff --git a/src/api/util/Constants.ts b/src/api/util/Constants.ts old mode 100644 new mode 100755 diff --git a/src/api/util/validateSession.ts b/src/api/util/validateSession.ts old mode 100644 new mode 100755 diff --git a/src/api/views/authorize.pug b/src/api/views/authorize.pug old mode 100644 new mode 100755 diff --git a/src/bot.ts b/src/bot.ts old mode 100644 new mode 100755 diff --git a/src/commands/commands.ts b/src/commands/commands.ts old mode 100644 new mode 100755 index 050c6021..ff66add4 --- a/src/commands/commands.ts +++ b/src/commands/commands.ts @@ -1,5 +1,7 @@ import CommandHandler from "../handlers/CommandHandler.js"; +import DiscordMessageContext from "../structures/contexts/DiscordMessageContext.js"; import AldebaranClient from "../structures/djs/Client.js"; +import { Platform } from "../utils/Constants.js"; import executeSocial from "../utils/executeSocial.js"; // Developer @@ -49,7 +51,6 @@ import UserCommand from "./general/user.js"; import BirbCommand from "./image/birb.js"; import BunnyCommand from "./image/bunny.js"; import CatCommand from "./image/cat.js"; -import CuteagCommand from "./image/cuteag.js"; import DogCommand from "./image/dog.js"; import DuckCommand from "./image/duck.js"; import HedgehogCommand from "./image/hedgehog.js"; @@ -58,6 +59,7 @@ import NekoCommand from "./image/neko.js"; import PandaCommand from "./image/panda.js"; import PepeCommand from "./image/pepe.js"; import RandimalCommand from "./image/randimal.js"; +import RCGPCommand from "./image/rcgp.js"; // NSFW import LewdCommand from "./nsfw/lewd.js"; @@ -87,8 +89,6 @@ import TickleCommand from "./social/tickle.js"; // Utilities import CurconvCommand from "./utilities/curconv.js"; import MathCommand from "./utilities/math.js"; -import TranslateCommand from "./utilities/translate.js"; -import MessageContext from "../structures/aldebaran/MessageContext.js"; export default () => { const commandHandler = CommandHandler.getInstance(); @@ -116,13 +116,18 @@ export default () => { super(client, { name, description, - args: { user: { as: "user" } } + args: { user: { + as: "user", + desc: "The user you want to socialize with", + optional: true + } }, + platforms: ["DISCORD"] }); } // eslint-disable-next-line class-methods-use-this - run(ctx: MessageContext) { - executeSocial(ctx); + run(ctx: DiscordMessageContext, platform: Platform) { + executeSocial(ctx, platform); } }); } @@ -149,11 +154,11 @@ export default () => { TimeCommand, UserCommand, BirbCommand, - CuteagCommand, DogCommand, LizardCommand, NekoCommand, PandaCommand, + RCGPCommand, LewdCommand, XboobsCommand, XkittyCommand, @@ -224,8 +229,4 @@ export default () => { if (process.env.API_FIXER) { commandHandler.register(CurconvCommand); } - - if (process.env.API_YANDEX) { - commandHandler.register(TranslateCommand); - } }; diff --git a/src/commands/developer/admin.ts b/src/commands/developer/admin.ts old mode 100644 new mode 100755 index 903f4d5c..f9a72cba --- a/src/commands/developer/admin.ts +++ b/src/commands/developer/admin.ts @@ -1,5 +1,5 @@ import { MessageEmbed } from "discord.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import { Command } from "../../groups/DeveloperCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; @@ -14,8 +14,8 @@ export default class AdminCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Admin Portal Command", - allowIndexCommand: true, - perms: { aldebaran: ["EDIT_USERS"] } + perms: { aldebaran: ["EDIT_USERS"] }, + platforms: ["DISCORD"] }); this.registerSubcommands( mod, @@ -30,10 +30,7 @@ export default class AdminCommand extends Command { // eslint-disable-next-line class-methods-use-this async run(ctx: MessageContext) { const embed = new MessageEmbed() - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) + .setAuthor(ctx.author.username, ctx.author.avatarURL) .setTitle("Warning") .setDescription("The admin action specified is invalid.") .setColor("ORANGE"); diff --git a/src/commands/developer/admin/mod.ts b/src/commands/developer/admin/mod.ts old mode 100644 new mode 100755 index 1631ce15..0314c721 --- a/src/commands/developer/admin/mod.ts +++ b/src/commands/developer/admin/mod.ts @@ -1,5 +1,5 @@ import { MessageEmbed } from "discord.js"; -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../../structures/contexts/MessageContext.js"; import { Command } from "../../../groups/DeveloperCommand.js"; import AldebaranClient from "../../../structures/djs/Client.js"; import { SettingsModel, GuildSetting, UserSetting } from "../../../utils/Constants.js"; @@ -25,8 +25,8 @@ export default class ModSubcommand extends Command { await user.changeSetting(args[1] as UserSetting, args[2]); const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Changes Done") .setDescription("The changes have successfully been applied. Please note that this command does not check for valid properties/values, make sure the user modded has the correct settings.") @@ -38,8 +38,8 @@ export default class ModSubcommand extends Command { await guild.changeSetting(args[1] as GuildSetting, args[2]); const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Changes Done") .setDescription("The changes have successfully been applied. Please note that this command does not check for valid properties/values, make sure the guild modded has the correct settings.") @@ -48,8 +48,8 @@ export default class ModSubcommand extends Command { } else { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription(`The ID specified does not correspond to a valid user or a guild where ${ctx.client.user!.username} is.`) @@ -60,8 +60,8 @@ export default class ModSubcommand extends Command { } else { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription("You need to specify the value of the settings you want to change.") @@ -71,8 +71,8 @@ export default class ModSubcommand extends Command { } else { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription("You need to specify the property of the settings you want to change.") @@ -82,8 +82,8 @@ export default class ModSubcommand extends Command { } else { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription("You need to specify the ID of the user or the guild you want to change the settings of.") diff --git a/src/commands/developer/admin/restart.ts b/src/commands/developer/admin/restart.ts old mode 100644 new mode 100755 index ee7c29d6..48f02d29 --- a/src/commands/developer/admin/restart.ts +++ b/src/commands/developer/admin/restart.ts @@ -1,5 +1,5 @@ import { MessageEmbed } from "discord.js"; -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../../structures/contexts/MessageContext.js"; import { Command } from "../../../groups/DeveloperCommand.js"; import AldebaranClient from "../../../structures/djs/Client.js"; diff --git a/src/commands/developer/admin/serverlist.ts b/src/commands/developer/admin/serverlist.ts old mode 100644 new mode 100755 index 31cd46cc..42f9cac4 --- a/src/commands/developer/admin/serverlist.ts +++ b/src/commands/developer/admin/serverlist.ts @@ -1,19 +1,21 @@ import { Collection, Guild, Snowflake } from "discord.js"; -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; import { Command, Embed } from "../../../groups/DeveloperCommand.js"; import AldebaranClient from "../../../structures/djs/Client.js"; import { paginate } from "../../../utils/Methods.js"; +import DiscordMessageContext from "../../../structures/contexts/DiscordMessageContext.js"; +import DiscordSlashMessageContext from "../../../structures/contexts/DiscordSlashMessageContext.js"; export default class ServerlistSubcommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Lists the servers the bot is in", - perms: { aldebaran: ["VIEW_SERVERLIST"] } + perms: { aldebaran: ["VIEW_SERVERLIST"] }, + platforms: ["DISCORD", "DISCORD_SLASH"] }); } // eslint-disable-next-line class-methods-use-this - async run(ctx: MessageContext) { + async run(ctx: DiscordMessageContext | DiscordSlashMessageContext) { const list: string[] = []; ctx.client.shard!.fetchClientValues("guilds.cache").then(collected => { (collected as Collection[]) diff --git a/src/commands/developer/admin/setperm.ts b/src/commands/developer/admin/setperm.ts old mode 100644 new mode 100755 index e4bea367..d412f527 --- a/src/commands/developer/admin/setperm.ts +++ b/src/commands/developer/admin/setperm.ts @@ -1,5 +1,5 @@ import { MessageEmbed } from "discord.js"; -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../../structures/contexts/MessageContext.js"; import { PermissionString } from "../../../utils/Constants.js"; import { Command } from "../../../groups/DeveloperCommand.js"; import AldebaranPermissions from "../../../structures/aldebaran/AldebaranPermissions.js"; @@ -19,8 +19,8 @@ export default class SetpermSubcommand extends Command { if (args[0] === undefined) { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription("You need to specify the ID of the user you want to change the permissions of.") @@ -30,8 +30,8 @@ export default class SetpermSubcommand extends Command { if (args[1] === undefined) { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription("You need to specify the operation you want to perform (ADD or REMOVE)") @@ -41,8 +41,8 @@ export default class SetpermSubcommand extends Command { if (args[1].toLowerCase() !== "add" && args[1].toLowerCase() !== "remove") { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription("You need to specify either ADD or REMOVE as the operation.") @@ -52,8 +52,8 @@ export default class SetpermSubcommand extends Command { if (args[2] === undefined) { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription(`You need to specify the ${ctx.client.name} permissions you want to set (seperated by spaces). (See \`assets/data/aldebaranPermissions.json\` for valid flags.)`) @@ -66,8 +66,8 @@ export default class SetpermSubcommand extends Command { .includes(permission)) as PermissionString[]; const embedFailure = (error: Error) => new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription(`Something went wrong: \n\`${error}\``) @@ -78,8 +78,8 @@ export default class SetpermSubcommand extends Command { await user.addPermissions(permissions); const embedAddSuccess = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Success") .setDescription(`Successfully added:\n\`${permissions.join(", ")}\`\n to ${user.username}.`) @@ -95,8 +95,8 @@ export default class SetpermSubcommand extends Command { await user.removePermissions(permissions); const embedRemoveSuccess = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Success") .setDescription(`Successfully removed:\n\`${permissions.join(", ")}\`\n from ${user.username}.`) @@ -113,8 +113,8 @@ export default class SetpermSubcommand extends Command { }).catch(() => { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription("The ID specified does not correspond to a valid user.") diff --git a/src/commands/developer/admin/timeout.ts b/src/commands/developer/admin/timeout.ts old mode 100644 new mode 100755 index 3e6ceb06..dab99d8c --- a/src/commands/developer/admin/timeout.ts +++ b/src/commands/developer/admin/timeout.ts @@ -1,5 +1,5 @@ import { MessageEmbed } from "discord.js"; -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../../structures/contexts/MessageContext.js"; import { Command } from "../../../groups/DeveloperCommand.js"; import AldebaranClient from "../../../structures/djs/Client.js"; @@ -33,7 +33,7 @@ export default class TimeoutSubcommand extends Command { .addField("Reason", args.join(" "), true) .addField("Server Invite", "https://discord.gg/3x6rXAv", true) .setColor("RED") - .setFooter(`Action taken by ${ctx.message.author.tag}`, ctx.message.author.displayAvatarURL()); + .setFooter(`Action taken by ${ctx.author.user.tag}`, ctx.author.avatarURL); user.user.send({ embeds: [embed] }); }).catch((err: Error) => { console.error(err); @@ -46,8 +46,8 @@ export default class TimeoutSubcommand extends Command { .setDescription("This ID does not correspond to any Discord user. Make sure you did not make a mistake typing it.") .setColor("RED") .setFooter( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ); ctx.reply(embed); }); @@ -57,8 +57,8 @@ export default class TimeoutSubcommand extends Command { .setDescription("This command requires three arguments in order to work, the user to timeout, the length and the reason of it.") .setColor("RED") .setFooter( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ); ctx.reply(embed); } diff --git a/src/commands/developer/admin/view.ts b/src/commands/developer/admin/view.ts old mode 100644 new mode 100755 index e44c414c..b9e740aa --- a/src/commands/developer/admin/view.ts +++ b/src/commands/developer/admin/view.ts @@ -2,21 +2,22 @@ import util from "util"; import { MessageEmbed } from "discord.js"; import { Command } from "../../../groups/DeveloperCommand.js"; import AldebaranClient from "../../../structures/djs/Client.js"; -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; +import DiscordMessageContext from "../../../structures/contexts/DiscordMessageContext.js"; export default class ViewSubcommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Shows detailled information about the specified user or guild", - perms: { aldebaran: ["EDIT_USERS"] } + perms: { aldebaran: ["EDIT_USERS"] }, + platforms: ["DISCORD"] }); } // eslint-disable-next-line class-methods-use-this - async run(ctx: MessageContext) { + async run(ctx: DiscordMessageContext) { const args = ctx.args as string[]; - const id = ctx.message.mentions.members!.size === 1 - ? ctx.message.mentions.members!.first()!.id : args[0]; + const id = ctx.mentions.members!.size === 1 + ? ctx.mentions.members!.first()!.id : args[0]; ctx.client.customUsers.fetch(id).then(async user => { const guilds = []; const embed = new MessageEmbed() @@ -39,9 +40,9 @@ export default class ViewSubcommand extends Command { }).catch(async () => { const customGuild = await ctx.client.customGuilds.fetch(id); const settings = customGuild.settings; - if (ctx.message.guild) { + if (ctx.guild) { let adminsStr = ""; - const members = Array.from(ctx.message.guild.members.cache.values()); + const members = Array.from(ctx.guild.guild.members.cache.values()); const bots = members.filter(m => m.user.bot === true); const humans = members.filter(m => m.user.bot === false); const botRate = bots.length * 100 / members.length; @@ -49,18 +50,18 @@ export default class ViewSubcommand extends Command { for (const member of admins) { adminsStr += `\`${member.user.id}\` | **\`[${member.user.tag}]\`** <@${member.user.id}>\n`; } - const owner = await ctx.message.guild.fetchOwner(); + const owner = await ctx.guild.guild.fetchOwner(); const embed = new MessageEmbed() - .setAuthor(`${ctx.message.guild.name} | ${ctx.message.guild.id}`, ctx.message.guild.iconURL()!) - .setDescription(`**Owner** : <@${ctx.message.guild.ownerId}> **\`[${owner.user.tag}]\`**\n**Member Count** : ${humans.length} Members (+${bots.length} Bots / ${Math.floor(botRate)}%)`); + .setAuthor(`${ctx.guild.guild.name} | ${ctx.guild.id}`, ctx.guild.guild.iconURL()!) + .setDescription(`**Owner** : <@${ctx.guild.guild.ownerId}> **\`[${owner.user.tag}]\`**\n**Member Count** : ${humans.length} Members (+${bots.length} Bots / ${Math.floor(botRate)}%)`); if (Object.entries(settings).length !== 0) embed.addField("Settings", `\`\`\`js\n${util.inspect(settings, false, null)}\`\`\``); if (adminsStr !== "") embed.addField("Admins", adminsStr); ctx.reply(embed); } else { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Warning") .setDescription(`The ID specified does not correspond to a valid user or a guild where ${ctx.client.name} is.`) diff --git a/src/commands/drpg/glead.ts b/src/commands/drpg/glead.ts old mode 100644 new mode 100755 index d7dfd552..2ec17381 --- a/src/commands/drpg/glead.ts +++ b/src/commands/drpg/glead.ts @@ -2,12 +2,13 @@ /* eslint-disable no-await-in-loop */ import fs from "fs"; import request from "request"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; import { Command, Embed } from "../../groups/DRPGCommand.js"; import { DRPGAttribute, DRPGGuild, DRPGItem, DRPGSkill, DRPGUser } from "../../interfaces/DiscordRPG.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { drpgItems, drpgLocationdb } from "../../utils/Constants.js"; import { paginate, timeSince } from "../../utils/Methods.js"; +import DiscordMessageContext from "../../structures/contexts/DiscordMessageContext.js"; +import DiscordSlashMessageContext from "../../structures/contexts/DiscordSlashMessageContext.js"; export type Guild = DRPGGuild & { users: User[], lastUpdate: number }; export type User = DRPGUser & { lastUpdate: number }; @@ -82,19 +83,37 @@ export default class GleadCommand extends Command { super(client, { description: "Displays a DiscordRPG user's guild leaderboard", help: "These are the attributes you can use as the \"attribute\" argument: `level`, `item name`, `gold`, `xp`, `lux`, `deaths`, `kills`, `points`, `questPoints`, `mine`, `chop`, `fish`, `forage`, `crits`, `defense`, `goldBoost`, `lumberBoost`, `mineBoost`, `reaping`, `salvaging`, `scavenge`, `strength`, `taming`, `xpBoost`, `lastseen` and `location`.", - usage: "[user] [--showid] [--desc] [attribute]", example: "141610251299454976 showid --desc lastseen", args: { - user: { as: "user", optional: true }, - showid: { as: "boolean", flag: { short: "s", long: "showid" }, optional: true }, - desc: { as: "boolean", flag: { short: "s", long: "desc" }, optional: true }, - attribute: { as: "word", optional: true } - } + user: { + as: "user", + desc: "The user whose guild you want to target", + optional: true + }, + showid: { + as: "boolean", + desc: "Whether user IDs should be displayed", + flag: { short: "s", long: "showid" }, + optional: true + }, + desc: { + as: "boolean", + desc: "Whether the list should be displayed in the reverse order", + flag: { short: "s", long: "desc" }, + optional: true + }, + attribute: { + as: "string", + desc: "The attribute whose leaderboard you want to see", + optional: true + } + }, + platforms: ["DISCORD", "DISCORD_SLASH"] }); } // eslint-disable-next-line class-methods-use-this - async run(ctx: MessageContext) { + async run(ctx: DiscordMessageContext | DiscordSlashMessageContext) { const args = ctx.args as { user?: string, showid?: boolean, @@ -104,10 +123,10 @@ export default class GleadCommand extends Command { // Get guild data, either from the cache or from the API const userData = await getUserData( - args.user || ctx.message.author.id, ctx.client + args.user || ctx.author.id, ctx.client ); if (!userData || !userData.guild) { - return ctx.reply(`That user isn't in a guild, ${ctx.message.author.username}.`); + return ctx.reply(`That user isn't in a guild, ${ctx.author.username}.`); } const guildData = await getGuild(userData, ctx.client) as Guild; diff --git a/src/commands/drpg/gold.ts b/src/commands/drpg/gold.ts old mode 100644 new mode 100755 index 6c541075..c299e370 --- a/src/commands/drpg/gold.ts +++ b/src/commands/drpg/gold.ts @@ -1,6 +1,6 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/DRPGCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { formatNumber } from "../../utils/Methods.js"; @@ -8,62 +8,59 @@ export default class GoldCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays the estimated gold per kill at a certain level", - usage: "Level EquipmentBoost GoldboostPoints", - example: "323 18 max" + example: "323 18 10", + args: { + level: { as: "number", desc: "The character level" }, + boost: { + as: "number", + desc: "Your equipment Gold Boost bonus", + optional: true + }, + points: { + as: "number", + desc: "The number of points assigned to the Gold Boost attribute", + optional: true + } + } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const args = ctx.args as string[]; - const level = parseInt(args[0], 10); - let attributes = 0; - if (args[2] !== undefined) { - if (args[2] === "max") attributes = 6969696969696966696969696969; - else attributes = parseInt(args[2], 10); - } - const equipment = args[1] !== undefined ? parseInt(args[1], 10) : 0; - if ( - !Number.isNaN(level) - && !Number.isNaN(attributes) - && !Number.isNaN(equipment) - ) { - if (attributes > level * 5) attributes = level * 5; - const baseGold = level < 22 - ? level * 4 : (50 + (level - 55) * 8 + 200 + level * 8) / 2; + const args = ctx.args as { level: number, boost: number, points?: number }; + const { level } = args; + const equipment = args.boost || 0; + const attrib = Math.min(args.points || 0, level * 5); - const getGold = (ring = 1) => Math.round((baseGold * ( - 1 + (Math.floor(attributes / 10) + equipment) / 100) - + level) * ring); + const baseGold = level < 22 + ? level * 4 + : (50 + (level - 55) * 8 + 200 + level * 8) / 2; - const embed = new MessageEmbed() - .setTitle("Average Obtained Gold") - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) - .setColor(0x00ae86) - .setDescription( - `**Please note all infomation about Gold are estimations!**\nYou have a +${equipment}% Gold Boost on your equipment, and you have ${attributes} points in the Gold Boost attribute.` - ) - .addField( - "**With a donor ring of Gold (x1.5)**", - `${formatNumber(getGold(1.5))} Gold per kill on average`, - true - ) - .addField( - "**With an enchanted donor ring of Gold (x1.56)**", - `${formatNumber(getGold(1.56))} Gold per kill on average`, - true - ) - .addField( - "**Without a ring of Gold**", - `${formatNumber(getGold())} Gold per kill on average` - ); - ctx.reply(embed); - } else { - ctx.reply("You need to specify a level and the Gold Boost percentage the used equipment has (if you want to take it in account)."); - } - return true; + const getGold = (ring = 1) => Math.round((baseGold * ( + 1 + (Math.floor(attrib / 10) + equipment) / 100) + + level) * ring); + + const embed = new MessageEmbed() + .setTitle("Average Obtained Gold") + .setAuthor(ctx.author.username, ctx.author.avatarURL) + .setColor(0x00ae86) + .setDescription( + `**Please note all infomation about Gold are estimations!**\nYou have a +${equipment}% Gold Boost on your equipment, and you have ${attrib} points in the Gold Boost attribute.` + ) + .addField( + "**With a donor ring of Gold (x1.5)**", + `${formatNumber(getGold(1.5))} Gold per kill on average`, + true + ) + .addField( + "**With an enchanted donor ring of Gold (x1.56)**", + `${formatNumber(getGold(1.56))} Gold per kill on average`, + true + ) + .addField( + "**Without a ring of Gold**", + `${formatNumber(getGold())} Gold per kill on average` + ); + ctx.reply(embed); } }; diff --git a/src/commands/drpg/plant.ts b/src/commands/drpg/plant.ts old mode 100644 new mode 100755 index 0ba53100..20b28aa1 --- a/src/commands/drpg/plant.ts +++ b/src/commands/drpg/plant.ts @@ -1,7 +1,7 @@ import { evaluate } from "mathjs"; import request from "request"; import { Command, Embed } from "../../groups/DRPGCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { drpgItems, drpgLocationdb } from "../../utils/Constants.js"; import { DRPGUser } from "../../interfaces/DiscordRPG.js"; @@ -10,11 +10,18 @@ export default class PlantCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays users plant information and estimated loots", - usage: "UserMention|UserID", example: "320933389513523220", args: { - user: { as: "user", optional: true }, - plant: { as: "number", optional: true } + user: { + as: "user", + desc: "The user whose plant information you want to see", + optional: true + }, + plant: { + as: "number", + desc: "The plant ID", + optional: true + } } }); } @@ -22,7 +29,7 @@ export default class PlantCommand extends Command { // eslint-disable-next-line class-methods-use-this async run(ctx: MessageContext) { const args = ctx.args as { user: string, plant: string }; - const userid = args.user || ctx.message.author.id; + const userid = args.user || ctx.author.id; const plantId = args.plant || null; request({ uri: `http://api.discorddungeons.me/v3/user/${userid}`, @@ -68,8 +75,8 @@ export default class PlantCommand extends Command { const highestRewards = highestMin === highestMax ? `**${highestMin} ${rewardName}**` : `between **${highestMin}** and **${highestMax} ${rewardName}**`; - const pronoun = ctx.message.author.id === userid ? "You" : "They"; - const ownership = ctx.message.author.id === userid ? "your" : "their"; + const pronoun = ctx.author.id === userid ? "You" : "They"; + const ownership = ctx.author.id === userid ? "your" : "their"; const embed = new Embed(this) .setAuthor(`${target.username} | Plant information | ${item.name} @ ${drpgLocationdb[plantId]}`, target.displayAvatarURL()) .setDescription(`With ${ownership} current reaping skills (${luck === 1 ? 0 : luck} points), ${pronoun} will receive ${normalRewards}. With the highest reaping skills possible for ${ownership} level (${luckMax} points) ${pronoun.toLowerCase()} could have, ${pronoun.toLowerCase()} will receive ${highestRewards}.`) @@ -87,12 +94,12 @@ export default class PlantCommand extends Command { if (plantsList !== "") { const embed = new Embed(this) .setAuthor(`${target.username} | Sapling information`, target.displayAvatarURL()) - .setDescription(`${ctx.message.author.id === userid ? "You have" : `**${target.username}** has`} **${plantsList.match(/\n/g)!.length} plants** set. Please tell us which one you want to view the information of. Use \`${ctx.prefix}plant 4\` for example.\n${plantsList}`); + .setDescription(`${ctx.author.id === userid ? "You have" : `**${target.username}** has`} **${plantsList.match(/\n/g)!.length} plants** set. Please tell us which one you want to view the information of. Use \`${ctx.prefix}plant 4\` for example.\n${plantsList}`); return ctx.reply(embed); } const embed = new Embed(this) .setAuthor(`${target.username} | Sapling information`, target.displayAvatarURL()) - .setDescription(`${ctx.message.author.id === userid ? "You have" : `**${target.username}** has`} no plant set.`); + .setDescription(`${ctx.author.id === userid ? "You have" : `**${target.username}** has`} no plant set.`); return ctx.reply(embed); } return ctx.reply("the DiscordRPG API seems down, please retry later."); diff --git a/src/commands/drpg/plantcalc.ts b/src/commands/drpg/plantcalc.ts old mode 100644 new mode 100755 index 255ca62b..a11b17f6 --- a/src/commands/drpg/plantcalc.ts +++ b/src/commands/drpg/plantcalc.ts @@ -2,42 +2,47 @@ import { evaluate } from "mathjs"; import { Command } from "../../groups/DRPGCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { drpgItems } from "../../utils/Constants.js"; -import { DRPGItem } from "../../interfaces/DiscordRPG.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class PlantcalcCommand extends Command { constructor(client: AldebaranClient) { super(client, { - description: "Displays estimated plant harvest based on time an level given", - usage: "ReapingPoints Hours ItemName", - example: "3600 24 Olive Seed" + description: "Displays estimated plant harvest based on time and level given", + example: "3600 24 \"Olive Seed\"", + args: { + seed: { + as: "string", + desc: "The seed of the plant you want to harvest" + }, + hours: { + as: "number", + desc: "How many hours you want your seed to be planted for" + }, + points: { + as: "number", + desc: "The number of points assigned to the Reaping attribute", + optional: true + } + } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const args = ctx.args as string[]; - if (args.length >= 3) { - const points = args.shift(); - const hours = parseInt(args.shift()!, 10); - const itemName = args.join(" "); - let item: DRPGItem | null = null; - - for (const element of Object.values(drpgItems)) { - if (element.sapling && element.name.toLowerCase().includes(itemName)) { - item = element; - } - } + const args = ctx.args as { seed: string, hours: number, points?: number }; + const points = args.points || 0; + const seed = args.seed.toLowerCase(); - if (item && item.sapling) { - const scope = { luck: points, passed: hours * 3600 }; - const min = evaluate(item.sapling.loot.amount.min, scope); - const max = evaluate(item.sapling.loot.amount.max, scope); - ctx.reply(`Estimated ${min} - ${max} when planted for ${hours} hours. `); - } else { - ctx.error("WRONG_USAGE", "You need to provide the name of a valid sapling."); - } + const item = Object.values(drpgItems) + .find(e => e.sapling && e.name.toLowerCase().includes(seed)); - } else ctx.reply(`You must provide reaping points, hours set and item name. Example (${ctx.prefix}plantcalc 1 24 olive)`); + if (item && item.sapling) { + const scope = { luck: points, passed: args.hours * 3600 }; + const min = evaluate(item.sapling.loot.amount.min, scope); + const max = evaluate(item.sapling.loot.amount.max, scope); + ctx.reply(`Estimated ${min} - ${max} when planted for ${args.hours} hours. `); + } else { + ctx.error("WRONG_USAGE", "You need to provide the name of a valid sapling."); + } } }; diff --git a/src/commands/drpg/skills.ts b/src/commands/drpg/skills.ts old mode 100644 new mode 100755 index 98fd958c..4b59282a --- a/src/commands/drpg/skills.ts +++ b/src/commands/drpg/skills.ts @@ -4,22 +4,25 @@ import { Command } from "../../groups/DRPGCommand.js"; import { formatNumber } from "../../utils/Methods.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { drpgItems } from "../../utils/Constants.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class SkillsCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays users' skills information", - usage: "UserMention|UserID", example: "246302641930502145", - args: { user: { as: "user", optional: true } } + args: { user: { + as: "user", + desc: "The user whose skills you want to see", + optional: true + } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { const args = ctx.args as { user: string }; - ctx.client.users.fetch(args.user || ctx.message.author.id).then(user => { + ctx.client.users.fetch(args.user || ctx.author.id).then(user => { request({ uri: `http://api.discorddungeons.me/v3/user/${user.id}`, headers: { Authorization: process.env.API_DISCORDRPG } }, (err, response, body) => { if (err) throw err; if (response.statusCode === 404) { diff --git a/src/commands/drpg/stats.ts b/src/commands/drpg/stats.ts old mode 100644 new mode 100755 index 0be4f53d..50f94f91 --- a/src/commands/drpg/stats.ts +++ b/src/commands/drpg/stats.ts @@ -7,7 +7,7 @@ import { formatNumber, getTimeString, lightOrDark } from "../../utils/Methods.js import AldebaranClient from "../../structures/djs/Client.js"; import { drpgLocationdb } from "../../utils/Constants.js"; import { DRPGUser } from "../../interfaces/DiscordRPG.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { createCanvas, Image, registerFont, loadImage } = canvasModule; @@ -15,16 +15,19 @@ export default class StatsCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays a DiscordRPG user's character and pet infos", - usage: "UserMention|UserID", example: "141610251299454976", - args: { user: { as: "user", optional: true } } + args: { user: { + as: "user", + desc: "The user whose stats you want to see", + optional: true + } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { const args = ctx.args as { user: string }; - ctx.client.users.fetch(args.user || ctx.message.author.id).then(user => { + ctx.client.users.fetch(args.user || ctx.author.id).then(user => { request({ uri: `http://api.discorddungeons.me/v3/user/${user.id}`, headers: { Authorization: process.env.API_DISCORDRPG } @@ -111,7 +114,7 @@ export default class StatsCommand extends Command { // eslint-disable-next-line class-methods-use-this image(ctx: MessageContext, args: { user: string }) { - const userId = args.user || ctx.message.author.id; + const userId = args.user || ctx.author.id; ctx.client.users.fetch(userId).then(user => { request({ uri: `http://api.discorddungeons.me/v3/user/${userId}`, @@ -136,13 +139,13 @@ export default class StatsCommand extends Command { registerFont("./assets/fonts/Exo2-Regular.ttf", { family: "Exo 2" }); - const bannerFG = lightOrDark(ctx.message.member!.displayHexColor) + const bannerFG = lightOrDark(ctx.member!.displayHexColor) ? ["black", "#222222"] : ["white", "#DDDDDD"]; context.fillStyle = "#222222"; context.fillRect(0, 0, 840, 775); - context.fillStyle = ctx.message.member!.displayHexColor; + context.fillStyle = ctx.member!.displayHexColor; context.fillRect(0, 0, 840, 126); context.save(); diff --git a/src/commands/drpg/trap.ts b/src/commands/drpg/trap.ts old mode 100644 new mode 100755 index d0d749c9..c1ddbca6 --- a/src/commands/drpg/trap.ts +++ b/src/commands/drpg/trap.ts @@ -5,19 +5,19 @@ import { Command } from "../../groups/DRPGCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { drpgItems, drpgLocationdb } from "../../utils/Constants.js"; import { DRPGUser } from "../../interfaces/DiscordRPG.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class TrapCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays users' trap information and estimated loots", - usage: "User TrapLocationID Max?", example: "240971835330658305 4 --max", args: { - user: { as: "user", optional: true }, - trap: { as: "number", optional: true }, + user: { as: "user", desc: "The user whose information you want to see", optional: true }, + trap: { as: "number", desc: "The trap ID", optional: true }, max: { as: "boolean", + desc: "Whether the result should assume you spent all your skills points into salvaging", flag: { short: "m", long: "max" }, optional: true } @@ -32,7 +32,7 @@ export default class TrapCommand extends Command { trap: string, max: boolean }; - const userid = args.user || ctx.message.author.id; + const userid = args.user || ctx.author.id; const trapId = args.trap || null; const isMax = args.max || false; @@ -62,7 +62,7 @@ export default class TrapCommand extends Command { const trap = data[trapId]; const elapsedTime = (Date.now() - trap.time) / 1000; const scope = { luck, passed: elapsedTime }; - const pronoun = ctx.message.author.id === userid ? "You" : "They"; + const pronoun = ctx.author.id === userid ? "You" : "They"; let items = ""; drpgItems[trap.id].trap!.loot.forEach(item => { const min = evaluate(item.amount.min, scope); @@ -97,7 +97,7 @@ export default class TrapCommand extends Command { } const embed = new MessageEmbed() .setAuthor(`${target.username} | Trap information`, target.displayAvatarURL()) - .setDescription(`${ctx.message.author.id === userid ? "You have" : `**${target.username}** has`} **${traps.match(/\n/g)!.length} traps** set. Please tell us which one you want to view the information of. Use \`${ctx.prefix}trap 4\` for example.\n${traps}`) + .setDescription(`${ctx.author.id === userid ? "You have" : `**${target.username}** has`} **${traps.match(/\n/g)!.length} traps** set. Please tell us which one you want to view the information of. Use \`${ctx.prefix}trap 4\` for example.\n${traps}`) .setColor("GREEN"); ctx.reply(embed); } diff --git a/src/commands/drpg/upgradecalc.ts b/src/commands/drpg/upgradecalc.ts old mode 100644 new mode 100755 index 110e2a4f..6e7913ab --- a/src/commands/drpg/upgradecalc.ts +++ b/src/commands/drpg/upgradecalc.ts @@ -1,5 +1,5 @@ import { Command, Embed } from "../../groups/DRPGCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class UpgradecalcCommand extends Command { @@ -8,14 +8,22 @@ export default class UpgradecalcCommand extends Command { description: "Displays the number of upgrades you need for your weapon", example: "400 386 7283 7408 1050 1.56 2", args: { - charLevel: { as: "number" }, - petLevel: { as: "number" }, - minPetDamage: { as: "number" }, - maxPetDamage: { as: "number" }, - minWeaponDamage: { as: "number" }, - maxWeaponDamage: { as: "number" }, - strMultiplier: { as: "number", optional: true }, - shots: { as: "number", optional: true } + charLevel: { as: "number", desc: "The character's level" }, + petLevel: { as: "number", desc: "The pet's level" }, + minPetDamage: { as: "number", desc: "The least damage the pet can deal" }, + maxPetDamage: { as: "number", desc: "The most damage the pet can deal" }, + minWeaponDamage: { as: "number", desc: "The least damage the weapon can deal" }, + maxWeaponDamage: { as: "number", desc: "The most damage the weapon can deal" }, + strMultiplier: { + as: "number", + desc: "The character's strength multiplier", + optional: true + }, + shots: { + as: "number", + desc: "The most shots you want to give to one enemy", + optional: true + } } }); } diff --git a/src/commands/drpg/walls.ts b/src/commands/drpg/walls.ts old mode 100644 new mode 100755 index 3f76ac46..9ca2ccaf --- a/src/commands/drpg/walls.ts +++ b/src/commands/drpg/walls.ts @@ -1,163 +1,142 @@ -import { Message, MessageEmbed } from "discord.js"; +import { MessageEmbed } from "discord.js"; import request from "request"; import { Command } from "../../groups/DRPGCommand.js"; import { formatNumber } from "../../utils/Methods.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { drpgXpBases } from "../../utils/Constants.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; + +function calcWall( + lvl: number | string, + base: number | string, + prevWall: number | string +) { + const L = Number(lvl); + const B = Number(base); + const C = prevWall ? Number(prevWall) : 25; + return L * (B + C) + L ** 2 * (B - C); +} + +function findKeyAbove(level: number) { + let loops = 0; // prevent timeout + while (drpgXpBases[level] === undefined) { + level++; + loops++; + if (loops > 50000) { + throw new Error("The level you entered was too high, command timed out."); + } + } + return level; +} + +function findKeyBelow(level: number) { + let loops = 0; + while (drpgXpBases[level] === undefined && level > 0) { + level--; + loops++; + if (loops > 50000) { + throw new Error("The level you entered was too high, command timed out."); + } + } + return level; +} + +function userWall(ctx: MessageContext, lvl: number) { + try { + const baseLvl = findKeyAbove(lvl); + const prevBaseLvl = findKeyBelow(lvl - 1); + + const base = drpgXpBases[baseLvl]; + let prevBase = 0; + if (!drpgXpBases[prevBaseLvl]) { + prevBase = 25; + } else { + prevBase = drpgXpBases[prevBaseLvl]; + } + const wall = calcWall(baseLvl, base, prevBase); + + return [wall, baseLvl]; + } catch (e) { + ctx.reply((e as Error).message); + throw e; + } +} + +function calcXPNeeded(base: number, lvl: number) { + return base * (lvl ** 2 + lvl); +} export default class WallsCommand extends Command { constructor(client: AldebaranClient) { super(client, { - description: "Displays user's wall information", - usage: "UserMention|UserID", - example: "246302641930502145" + description: "Displays user's wall progression", + example: "246302641930502145", + args: { user: { + as: "user", + desc: "The user whose walls progression you want to see", + optional: true + } } }); } // eslint-disable-next-line class-methods-use-this async run(ctx: MessageContext) { - const args = ctx.args as string[]; - function calcWall( - lvl: number | string, - base: number | string, - prevWall: number | string - ) { - const L = Number(lvl); - const B = Number(base); - const C = prevWall ? Number(prevWall) : 25; - return L * (B + C) + L ** 2 * (B - C); - } - - function findKeyAbove(level: number) { - let loops = 0; // prevent timeout - while (drpgXpBases[level] === undefined) { - level++; - loops++; - if (loops > 50000) { - throw new Error("The level you entered was too high, command timed out."); - } - } - return level; - } - - function findKeyBelow(level: number) { - let loops = 0; - while (drpgXpBases[level] === undefined && level > 0) { - level--; - loops++; - if (loops > 50000) { - throw new Error("The level you entered was too high, command timed out."); - } - } - return level; - } + const userId = (ctx.args as { user: string }).user || ctx.author.id; + const user = await ctx.client.users.fetch(userId); - function userWall(msg: Message, lvl: number) { + request({ + uri: `http://api.discorddungeons.me/v3/user/${user.id}`, + headers: { Authorization: process.env.API_DISCORDRPG } + }, (err, _, body) => { + if (err) throw err; + let data; try { - const baseLvl = findKeyAbove(lvl); - const prevBaseLvl = findKeyBelow(lvl - 1); - - const base = drpgXpBases[baseLvl]; - let prevBase = 0; - if (!drpgXpBases[prevBaseLvl]) { - prevBase = 25; - } else { - prevBase = drpgXpBases[prevBaseLvl]; - } - const wall = calcWall(baseLvl, base, prevBase); - - return [wall, baseLvl]; + data = JSON.parse(body); } catch (e) { - msg.reply(e.msg); - throw e; + ctx.reply("the DiscordRPG API seems down, please retry later."); + return; } - } - function calcXPNeeded(base: number, lvl: number) { - return base * (lvl ** 2 + lvl); - } - - try { - const user = await ctx.client.users.fetch(args[0] || ctx.message.author.id); - request({ - uri: `http://api.discorddungeons.me/v3/user/${user.id}`, - headers: { Authorization: process.env.API_DISCORDRPG } - }, (err, _, body) => { - if (err) throw err; - let data; - try { - data = JSON.parse(body); - } catch (e) { - ctx.reply("the DiscordRPG API seems down, please retry later."); - return; - } - if (data.status === 404) { - ctx.reply("It looks like the player you mentioned hasn't started their adventure on DiscordRPG."); - return; - } - data = data.data; - - const [wall, baseLvl] = userWall(ctx.message, data.level); - const userAtWall = data.level === baseLvl; - const xpNeeded = calcXPNeeded(drpgXpBases[baseLvl], baseLvl); - const wallProgress = xpNeeded - data.xp; - - const embed = new MessageEmbed() - .setColor(0x00ae86) - .setAuthor(`${user.username} | DiscordRPG Walls`, - user.displayAvatarURL()) - .addField( - `Base at Level ${baseLvl}`, - `The baseXP (the increment of XP needed to level up - the "XP ramp") for Level ${baseLvl} is ${drpgXpBases[baseLvl]}.` - ); + if (data.status === 404) { + ctx.reply("It looks like the player you mentioned hasn't started their adventure on DiscordRPG."); + return; + } + data = data.data; - if (userAtWall) { - embed.addField( - `Level ${baseLvl} wall`, - `They're at a ${wall.toLocaleString("en-US")} XP wall.` - ); - embed.addField( - `${user.username}'s progress`, - `**${formatNumber(wall - wallProgress)} XP** / ${formatNumber(wall)} XP (**${Math.round( - 100 * ((wall - wallProgress) * 100) / wall - ) / 100}%**)` - ); - } else { - embed.addField( - `${user.username}'s next wall`, - `Level ${baseLvl}: ${wall.toLocaleString( - "en-US" - )} XP wall\nYou will need ${xpNeeded.toLocaleString( - "en-US" - )} XP total at level ${baseLvl}.` - ); - } - ctx.reply(embed); - }); - } catch (err) { - const [wall, baseLvl] = userWall(ctx.message, Number(args[0])); + const [wall, baseLvl] = userWall(ctx, data.level); + const userAtWall = data.level === baseLvl; const xpNeeded = calcXPNeeded(drpgXpBases[baseLvl], baseLvl); + const wallProgress = xpNeeded - data.xp; const embed = new MessageEmbed() .setColor(0x00ae86) - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) - .setTitle(`Wall closest to Level ${args[0]}`) + .setAuthor(`${user.username} | DiscordRPG Walls`, user.displayAvatarURL()) .addField( `Base at Level ${baseLvl}`, `The baseXP (the increment of XP needed to level up - the "XP ramp") for Level ${baseLvl} is ${drpgXpBases[baseLvl]}.` - ) - .addField( + ); + + if (userAtWall) { + embed.addField( `Level ${baseLvl} wall`, - `The wall at Level ${baseLvl} is ${wall.toLocaleString( + `They're at a ${wall.toLocaleString("en-US")} XP wall.` + ); + embed.addField( + `${user.username}'s progress`, + `**${formatNumber(wall - wallProgress)} XP** / ${formatNumber(wall)} XP (**${Math.round( + 100 * ((wall - wallProgress) * 100) / wall + ) / 100}%**)` + ); + } else { + embed.addField( + `${user.username}'s next wall`, + `Level ${baseLvl}: ${wall.toLocaleString( "en-US" - )} XP. You will need ${xpNeeded.toLocaleString( + )} XP wall\nYou will need ${xpNeeded.toLocaleString( "en-US" - )} XP total to progress at that level.` + )} XP total at level ${baseLvl}.` ); + } ctx.reply(embed); - } + }); } }; diff --git a/src/commands/drpg/weapon.ts b/src/commands/drpg/weapon.ts old mode 100644 new mode 100755 index fe904fd3..670c2027 --- a/src/commands/drpg/weapon.ts +++ b/src/commands/drpg/weapon.ts @@ -1,6 +1,6 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/DRPGCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { drpgItems } from "../../utils/Constants.js"; @@ -8,9 +8,8 @@ export default class WeaponCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Recommends you the best weapons for your level", - usage: "Level", example: "150", - args: { level: { as: "number" } } + args: { level: { as: "number", desc: "The level you want your weapon to be at" } } }); } @@ -45,13 +44,17 @@ export default class WeaponCommand extends Command { const embed = new MessageEmbed() .setTitle(`Obtainable Weapons Available At Level ${level}`) - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) + .setAuthor(ctx.author.username, ctx.author.avatarURL) .setColor(0x00AE86) .setDescription("Will display weapon available at level specfied, unless none exist which will return close matches above and below level specfied."); - for (const weapon of results) embed.addField(`__*${weapon.name} - Lvl.${weapon.level}*__`, `*${weapon.desc}*\n**Price:** ${weapon.cost} gold\n**Damage:** ${weapon.weapon!.dmg.min} - ${weapon.weapon!.dmg.max}\n**ItemID:** ${weapon.id}`, false); + + for (const weapon of results) { + embed.addField( + `__*${weapon.name} - Lvl.${weapon.level}*__`, + `*${weapon.desc}*\n**Price:** ${weapon.cost} gold\n**Damage:** ${weapon.weapon!.dmg.min} - ${weapon.weapon!.dmg.max}\n**ItemID:** ${weapon.id}`, + false + ); + } return ctx.reply(embed); } }; diff --git a/src/commands/drpg/xp.ts b/src/commands/drpg/xp.ts old mode 100644 new mode 100755 index 79a09953..76eecd8a --- a/src/commands/drpg/xp.ts +++ b/src/commands/drpg/xp.ts @@ -1,6 +1,6 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/DRPGCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { formatNumber } from "../../utils/Methods.js"; @@ -8,73 +8,70 @@ export default class XpCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays estimated XP per kill at a certain level", - usage: "Level EquipmentBonus XPBoostAttribute", - example: "323 18 max" + example: "323 18 max", + args: { + level: { as: "number", desc: "The character level" }, + boost: { + as: "number", + desc: "Your equipment XP Boost bonus", + optional: true + }, + points: { + as: "number", + desc: "The number of points assigned to the XP Boost attribute", + optional: true + } + } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const args = ctx.args as string[]; - const level = Number(args[0]); - const enchant = args[1] !== undefined ? parseInt(args[1], 10) : 0; - let attributes = 0; - if (args[2] !== undefined) { - if (args[2] === "max") attributes = 6969696969696966696969696969; - else attributes = parseInt(args[2], 10); - } - if ( - !Number.isNaN(level) - && !Number.isNaN(enchant) - && !Number.isNaN(attributes) - ) { - if (attributes > level * 5) attributes = level * 5; - const baseXP = level < 22 - ? level * 5 - : (50 + (level - 55) * 2.719047619 + 200 + level * 2.719047619) / 2; + const args = ctx.args as { level: number, boost: number, points?: number }; + const { level } = args; + const enchant = args.boost || 0; + const attrib = Math.min(args.points || 0, level * 5); - const getXP = (ring = 1) => Math.round( - (baseXP * (1 + (Math.floor(attributes / 10) + enchant) / 100) + level) - * ring - ); + const baseXP = level < 22 + ? level * 5 + : (50 + (level - 55) * 2.719047619 + 200 + level * 2.719047619) / 2; - const embed = new MessageEmbed() - .setTitle(`Average Xp Kill At Lvl. ${level}`) - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) - .setColor(0x00ae86) - .setDescription( - `**Please note all infomation about XP are estimations, and only works with dynamobs!**\nYou have a +${enchant}% XP Boost on your equipment, and you have ${attributes} points in your XP Boost attribute.` - ) - .addField( - "**With a ring of XP (x1.25)**", - `${formatNumber(getXP(1.25))} XP per kill on average`, - true - ) - .addField( - "**With an enchanted ring of XP (x1.31)**", - `${formatNumber(getXP(1.31))} XP per kill on average`, - true - ) - .addField( - "**With a donor ring of XP (x1.5)**", - `${formatNumber(getXP(1.5))} XP per kill on average`, - true - ) - .addField( - "**With an enchanted donor ring of XP (x1.56)**", - `${formatNumber(getXP(1.56))} XP per kill on average`, - true - ) - .addField( - "**Without a ring of XP**", - `${formatNumber(getXP())} XP per kill on average` - ); - ctx.reply(embed); - } else { - ctx.reply("You need to specify a level and the XP Boost percentage the used equipment has (if you want to take it in account)."); + const getXP = (ring = 1) => { + const xp = baseXP * (1 + (Math.floor(attrib / 10) + enchant) / 100) + level; + return Math.round(xp * ring); } + + const embed = new MessageEmbed() + .setTitle(`Average Xp Kill At Lvl. ${level}`) + .setAuthor(ctx.author.username, ctx.author.avatarURL) + .setColor(0x00ae86) + .setDescription( + `**Please note all infomation about XP are estimations, and only works with dynamobs!**\nYou have a +${enchant}% XP Boost on your equipment, and you have ${attrib} points in your XP Boost attribute.` + ) + .addField( + "**With a ring of XP (x1.25)**", + `${formatNumber(getXP(1.25))} XP per kill on average`, + true + ) + .addField( + "**With an enchanted ring of XP (x1.31)**", + `${formatNumber(getXP(1.31))} XP per kill on average`, + true + ) + .addField( + "**With a donor ring of XP (x1.5)**", + `${formatNumber(getXP(1.5))} XP per kill on average`, + true + ) + .addField( + "**With an enchanted donor ring of XP (x1.56)**", + `${formatNumber(getXP(1.56))} XP per kill on average`, + true + ) + .addField( + "**Without a ring of XP**", + `${formatNumber(getXP())} XP per kill on average` + ); + ctx.reply(embed); } }; diff --git a/src/commands/fun/8ball.ts b/src/commands/fun/8ball.ts old mode 100644 new mode 100755 index 072ed7c1..190a9746 --- a/src/commands/fun/8ball.ts +++ b/src/commands/fun/8ball.ts @@ -1,5 +1,5 @@ import { Command, Embed } from "../../groups/FunCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class EightballCommand extends Command { @@ -8,22 +8,21 @@ export default class EightballCommand extends Command { description: "Ask the magic 8ball a question, you will be given the right answer", example: "Should Allen get a hug?", name: "8ball", - usage: "Question" + args: { question: { + as: "string", + desc: "The question you want the 8ball to answer" + } } }); } // eslint-disable-next-line class-methods-use-this async run(ctx: MessageContext) { - const text = (ctx.args as string[]).join(" "); - if (text) { - const data = await ctx.client.nekoslife.sfw["8Ball"]({ text }); - const embed = new Embed(this) - .setDescription(`**${data.response}**`) - .setImage(data.url!) - .setFooter("Powered by nekos.life", ctx.client.user.avatarURL()!); - ctx.reply(embed); - } else { - ctx.reply("Please ask a question"); - } + const { question } = ctx.args as { question: string }; + const data = await ctx.client.nekoslife.sfw["eightBall"]({ text: question }); + const embed = new Embed(this) + .setDescription(`**${data.response}**`) + .setImage(data.url!) + .setFooter("Powered by nekos.life", ctx.client.user.avatarURL()!); + ctx.reply(embed); } }; diff --git a/src/commands/fun/emojilist.ts b/src/commands/fun/emojilist.ts old mode 100644 new mode 100755 index 03413a37..8f7a8976 --- a/src/commands/fun/emojilist.ts +++ b/src/commands/fun/emojilist.ts @@ -1,5 +1,5 @@ import { Command } from "../../groups/FunCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class EmojilistCommand extends Command { @@ -12,7 +12,7 @@ export default class EmojilistCommand extends Command { // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const emojilist = ctx.message.guild!.emojis.cache + const emojilist = ctx.guild!.guild.emojis.cache .map(e => e.toString()).join(""); if (emojilist.length <= 2000) ctx.reply(emojilist); diff --git a/src/commands/fun/fact.ts b/src/commands/fun/fact.ts old mode 100644 new mode 100755 index 8d380f75..adc5ff7c --- a/src/commands/fun/fact.ts +++ b/src/commands/fun/fact.ts @@ -1,5 +1,5 @@ import { Command, Embed } from "../../groups/FunCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class FactCommand extends Command { diff --git a/src/commands/fun/kaomoji.ts b/src/commands/fun/kaomoji.ts old mode 100644 new mode 100755 index 3f90e24d..394fbdfa --- a/src/commands/fun/kaomoji.ts +++ b/src/commands/fun/kaomoji.ts @@ -1,5 +1,5 @@ import { Command } from "../../groups/FunCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class KaomojiCommand extends Command { diff --git a/src/commands/fun/owoify.ts b/src/commands/fun/owoify.ts old mode 100644 new mode 100755 index c892b028..524a0881 --- a/src/commands/fun/owoify.ts +++ b/src/commands/fun/owoify.ts @@ -1,22 +1,22 @@ import { Command, Embed } from "../../groups/FunCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class OwoifyCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Sends an owoified text", - usage: "Text", - example: "why is the grass green?" + example: "why is the grass green?", + args: { text: { as: "string", desc: "The text to owoify" } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const args = ctx.args as string[]; + const { text } = ctx.args as { text: string }; const embed = new Embed(this) .setTitle("owoifier") - .setDescription(args.join(" ").replace(/r|l/g, "w")); + .setDescription(text.replace(/r|l/g, "w")); ctx.reply(embed); } }; diff --git a/src/commands/fun/say.ts b/src/commands/fun/say.ts old mode 100644 new mode 100755 index 9acaf51f..b7d1120f --- a/src/commands/fun/say.ts +++ b/src/commands/fun/say.ts @@ -1,25 +1,22 @@ import { Command, Embed } from "../../groups/FunCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class SayCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Make the bot say something", - usage: "Text", - example: "aldebaran is the best bot" + example: "aldebaran is the best bot", + args: { text: { as: "string", desc: "What you want Aldebaran to say" } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const args = ctx.args as string[]; + const { text } = ctx.args as { text: string }; const embed = new Embed(this) - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) - .setDescription(args.join(" ")); + .setAuthor(ctx.author.username, ctx.author.avatarURL) + .setDescription(text); ctx.reply(embed); } }; diff --git a/src/commands/fun/timecompletion.ts b/src/commands/fun/timecompletion.ts old mode 100644 new mode 100755 index e1ea2392..746fcfd3 --- a/src/commands/fun/timecompletion.ts +++ b/src/commands/fun/timecompletion.ts @@ -1,5 +1,5 @@ import { Command, Embed } from "../../groups/FunCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class TimecompletionCommand extends Command { diff --git a/src/commands/games/rps.ts b/src/commands/games/rps.ts old mode 100644 new mode 100755 index b1d1d7fd..10945e36 --- a/src/commands/games/rps.ts +++ b/src/commands/games/rps.ts @@ -1,98 +1,109 @@ -import { Message, MessageEmbed, MessageReaction, User } from "discord.js"; +import { MessageActionRow, MessageButton, MessageComponentInteraction, MessageEmbed } from "discord.js"; import { Command } from "../../groups/GamesCommand.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import DiscordMessageContext from "../../structures/contexts/DiscordMessageContext.js"; +import DiscordSlashMessageContext from "../../structures/contexts/DiscordSlashMessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; +const win = { + "🪨": "✂️", + "🧻": "🪨", + "✂️": "🧻" +}; + +const words = { + "🪨": "rock", + "🧻": "paper", + "✂️": "scissors" +}; + export default class RpsCommand extends Command { constructor(client: AldebaranClient) { - super(client, { description: "Rock. Paper. Scissors!" }); + super(client, { + description: "Rock. Paper. Scissors!", + args: { + user: { as: "user", desc: "The user you want to play with" } + }, + platforms: ["DISCORD", "DISCORD_SLASH"] + }); } // eslint-disable-next-line class-methods-use-this - run(ctx: MessageContext) { - const args = ctx.args as string[]; - if (args[0] !== undefined) { - if (ctx.message.mentions.users.size > 0) { - const target = ctx.message.mentions.users.first()!; - if (target.id === ctx.client.user.id) { - ctx.reply("Sorry, but I don't want to play right now..."); - } else if (!ctx.message.author.bot) { - const introEmbed = new MessageEmbed() - .setAuthor("Rock. Paper. Scissors.", ctx.client.user.avatarURL()!) - .setDescription(`**The person you want to play with has to accept your invitation by clicking the emoji on this message.**\nHere is how this game is going to work with you: once the other have accepted the invitation, **you will both receive a message** in your private messages from ${ctx.client.name}. You will have to **type either \"rock\", either \"paper\", either \"scissors\"** within 15 seconds (you can also type the first letter of each if you are too lazy to type the full word). **The results will be sent to the channel where the game has begun.**`) - .setColor(this.color); - ctx.reply(introEmbed).then(msg => { - msg.react("✅"); - const reactionsFilter = (reaction: MessageReaction, user: User) => reaction.emoji.name === "✅" && user.id === target.id; - const messagesFilter = (msgTest: Message) => ["r", "p", "s", "rock", "paper", "scissors"] - .includes(msgTest.content); - msg.awaitReactions({ filter: reactionsFilter, time: 60000, max: 1 }) - .then(async collected => { - if (collected.size !== 0) { - ctx.reply("The game will begin shortly."); - ctx.message.author.send( - "Please type your choice here. \"rock\" or \"r\", \"paper\" or \"p\", or \"scissors\" or \"s\"." - ); - target.send( - "Please type your choice here. \"rock\" or \"r\", \"paper\" or \"p\", or \"scissors\" or \"s\"." - ); - const options = { filter: messagesFilter, time: 15000, max: 1 }; - const authorDM = await ctx.message.author.createDM(); - const targetDM = await target.createDM(); - Promise.all([ - authorDM.awaitMessages(options), - targetDM.awaitMessages(options) - ]).then(([authorPlay, targetPlay]) => { - if (authorPlay.size && targetPlay.size) { - const win = { - r: "s", - p: "r", - s: "p" - }; - const words = { - r: "rock", - p: "paper", - s: "scissors" - }; - const authorResponse = authorPlay - .first()!.content[0] as keyof typeof win; - const targetResponse = targetPlay - .first()!.content[0] as keyof typeof win; - if (authorResponse !== targetResponse) { - if (win[authorResponse] === targetResponse) { - const embed = new MessageEmbed() - .setAuthor(`${ctx.message.author.username} won!`, ctx.message.author.displayAvatarURL()) - .setDescription(`They played ${words[authorResponse]}, while **${target.username}** played ${words[targetResponse]}.`) - .setColor(this.color); - ctx.reply(embed); - } else if (win[targetResponse] === authorResponse) { - const embed = new MessageEmbed() - .setAuthor(`${target.username} won!`, target.displayAvatarURL()) - .setDescription(`They played ${words[targetResponse]}, while ${ctx.message.author.username} played ${words[authorResponse]}.`) - .setColor(this.color); - ctx.reply(embed); - } - } else { - ctx.reply(`Both users played ${targetResponse}, retry!`); - } - } - }); - } else { - ctx.reply("the person you want to play with has not accepted your invitation."); - } - }).catch(error => { - ctx.reply("An error occured with this RPS game."); - throw error; - }); - }); - } else { - ctx.reply(`You cannot play against a bot that is not ${ctx.client.name}.`); - } + async run(ctx: DiscordMessageContext | DiscordSlashMessageContext) { + const args = ctx.args as { user: string }; + const target = await ctx.client.customUsers.fetch(args.user); + + if (target.user.bot) { + return ctx.reply("You can't play this game against a bot."); + } + + const introEmbed = new MessageEmbed() + .setAuthor("Rock. Paper. Scissors.", ctx.author.avatarURL) + .setDescription(`The person you want to play with has to accept your invitation by clicking the **Accept** button on this message.\nHere is how this game is going to go: once your opponent accepts your invitation, three buttons will appear; choose the winning one. The results will be sent to the channel where the game has begun.`) + .setColor(this.color); + + const acceptButton = new MessageButton() + .setStyle("SUCCESS") + .setLabel("Accept") + .setCustomId("ok"); + const row = new MessageActionRow().setComponents([acceptButton]); + const opt = { embeds: [introEmbed], components: [row] }; + const msg = ctx instanceof DiscordSlashMessageContext + ? await ctx.reply(opt, false, true) + : await ctx.reply(opt); + + const filter = (i: MessageComponentInteraction) => i.user.id === target.id; + msg.awaitMessageComponent({ filter }).then(async interaction => { + interaction.deferUpdate(); + + const startEmbed = new MessageEmbed() + .setAuthor("Rock. Paper. Scissors.", ctx.author.avatarURL) + .setDescription("And the fun begins now! Use the buttons below, and discover the winner once both of you have made their choice!") + .setColor(this.color); + + const emojiButton = (emoji: string) => new MessageButton() + .setStyle("SECONDARY") + .setEmoji(emoji) + .setCustomId(emoji); + const [rock, paper, scissors] = ["🪨", "🧻", "✂️"].map(emojiButton); + const actionRow = new MessageActionRow() + .setComponents([rock, paper, scissors]); + + const opt = { embeds: [startEmbed], components: [actionRow] }; + const game = ctx instanceof DiscordSlashMessageContext + ? await ctx.followUp(opt, false, true) + : await ctx.reply(opt); + + const [authorPlay, targetPlay] = await Promise.all([ + game.awaitMessageComponent({ filter: i => i.user.id === ctx.author.id }), + game.awaitMessageComponent({ filter: i => i.user.id === target.id }) + ]); + + authorPlay.deferUpdate(); + targetPlay.deferUpdate(); + const authorResponse = authorPlay.customId as keyof typeof win; + const targetResponse = targetPlay.customId as keyof typeof win; + + let content; + if (authorResponse === targetResponse) { + content = `Both users played ${targetResponse}, retry!`; + } else if (win[authorResponse] === targetResponse) { + content = new MessageEmbed() + .setAuthor(`${ctx.author.username} won!`, ctx.author.avatarURL) + .setDescription(`They played ${words[authorResponse]}, while **${target.username}** played ${words[targetResponse]}.`) + .setColor(this.color); } else { - ctx.reply("You have to ping a valid user in order to play this game."); + content = new MessageEmbed() + .setAuthor(`${target.username} won!`, target.avatarURL) + .setDescription(`They played ${words[targetResponse]}, while ${ctx.author.username} played ${words[authorResponse]}.`) + .setColor(this.color); } - } else { - ctx.reply("You can choose to play against a bot or against someone else by pinging him. But you need to choose if you want to play!"); - } + + ctx instanceof DiscordSlashMessageContext + ? ctx.followUp(content, false, true) + : ctx.reply(content); + }).catch(error => { + ctx.reply("An error occured with this RPS game."); + throw error; + }); } }; diff --git a/src/commands/general/avatar.ts b/src/commands/general/avatar.ts old mode 100644 new mode 100755 index b842844a..cb87a051 --- a/src/commands/general/avatar.ts +++ b/src/commands/general/avatar.ts @@ -1,23 +1,26 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/Command.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class AvatarCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays the avatar of the specified user", - usage: "UserMention/UserID", example: "320933389513523220", aliases: ["pfp"], - args: { user: { as: "user", optional: true } } + args: { user: { + as: "user", + desc: "The user whose avatar you want to see", + optional: true + } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { const args = ctx.args as { user?: string }; - ctx.client.users.fetch(args.user || ctx.message.author.id).then(user => { + ctx.client.users.fetch(args.user || ctx.author.id).then(user => { const embed = new MessageEmbed() .setAuthor(user.username, user.displayAvatarURL()) .setTitle(`${user.username}'s Avatar`) diff --git a/src/commands/general/bstats.ts b/src/commands/general/bstats.ts old mode 100644 new mode 100755 index 37c8885d..81d1c7c4 --- a/src/commands/general/bstats.ts +++ b/src/commands/general/bstats.ts @@ -1,7 +1,7 @@ import { MessageEmbed } from "discord.js"; import os from "os"; import { Command } from "../../groups/Command.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { getTimeString } from "../../utils/Methods.js"; diff --git a/src/commands/general/bugreport.ts b/src/commands/general/bugreport.ts old mode 100644 new mode 100755 index 7dccb273..c5b21a00 --- a/src/commands/general/bugreport.ts +++ b/src/commands/general/bugreport.ts @@ -1,31 +1,33 @@ // Command Developed with the help of Akashic Bearer#2305 import { MessageEmbed, WebhookClient } from "discord.js"; import { Command } from "../../groups/Command.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import AldebaranClient from "../../structures/djs/Client.js"; export default class BugreportCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Sends a bug report", - usage: "BugReport", - example: "ur bot doesnt work" + example: "ur bot doesnt work", + args: { report: { + as: "string", + desc: "Details about the bug you have encountered" + } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const args = ctx.args as string[]; - if (args.length === 0) return ctx.reply("You can't send an empty bug report."); + const { report } = ctx.args as { report: string }; const embed = new MessageEmbed() - .setDescription(args.join(" ")) - .setFooter(`User: ${ctx.message.author.tag} [ID: ${ctx.message.author.id}]`); + .setDescription(report) + .setFooter(`User: ${ctx.author.user.tag} [ID: ${ctx.author.id}]`); new WebhookClient({ id: process.env.WEBHOOK_BUGREPORTS_ID!, token: process.env.WEBHOOK_BUGREPORTS_TOKEN! }).send({ - username: ctx.message.author.username, - avatarURL: ctx.message.author.displayAvatarURL(), + username: ctx.author.username, + avatarURL: ctx.author.avatarURL, embeds: [embed] }).then(() => { ctx.reply("Your bug report has been sent to the main server!"); diff --git a/src/commands/general/commands.ts b/src/commands/general/commands.ts old mode 100644 new mode 100755 index 327246c7..3d9b2acc --- a/src/commands/general/commands.ts +++ b/src/commands/general/commands.ts @@ -1,6 +1,7 @@ import { Command, Embed } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; +import { Platform } from "../../utils/Constants.js"; export default class CommandsCommand extends Command { constructor(client: AldebaranClient) { @@ -24,29 +25,35 @@ export default class CommandsCommand extends Command { } // eslint-disable-next-line class-methods-use-this - async run(ctx: MessageContext) { + async run(ctx: MessageContext, platform: Platform) { const args = ctx.args as { showHidden: boolean, hideAliases: boolean }; - const guild = ctx.message.guild ? await ctx.guild() : null; - const commands: { [key: string]: string[] } = {}; - for (const [name, data] of ctx.client.commands.commands) { - if (args.showHidden || (await data.check(ctx) && !data.hidden)) { - if (commands[data.category] === undefined) - commands[data.category] = []; - if (name === data.name) { - commands[data.category].push(name); - } else if (!args.hideAliases) { - commands[data.category].push(`*${name}*`); + const categories: { [key: string]: string[] } = {}; + const commands = ctx.client.commands.commands + .filter(c => c.supports(platform)); + let count = 0; + for (const command of commands) { + if (args.showHidden || (await command.check(ctx) && !command.hidden)) { + if (!categories[command.category]) { + categories[command.category] = []; + } + categories[command.category].push(`${command.name}`); + count++; + if (!args.hideAliases) { + command.aliases.forEach(a => { + categories[command.category].push(`*${a}*`); + }); } } } - const embed = new Embed(this) - .setAuthor( - `${ctx.client.name} | List of ${ctx.client.commands.size} commands`, - ctx.client.user.avatarURL()! - ); - embed.setFooter(`${!args.showHidden && !args.hideAliases ? "Use --showhidden to view all commands and --hidealiases to hide aliases." : ""} To learn how to use the customized commands, check ${ctx.prefix}commands guide.`); - for (const [category, list] of Object.entries(commands)) { + const embed = new Embed(this).setAuthor( + `${ctx.client.name} | List of ${count} commands`, + ctx.client.user.avatarURL()! + ); + if (!args.showHidden && !args.hideAliases) { + embed.setFooter("Use --showhidden to view all commands and --hidealiases to hide aliases."); + } + for (const [category, list] of Object.entries(categories)) { embed.addField(category, list.join(", "), true); } ctx.reply(embed); diff --git a/src/commands/general/credits.ts b/src/commands/general/credits.ts old mode 100644 new mode 100755 index 02fdd679..b7979d4f --- a/src/commands/general/credits.ts +++ b/src/commands/general/credits.ts @@ -1,7 +1,7 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class CreditsCommand extends Command { constructor(client: AldebaranClient) { diff --git a/src/commands/general/help.ts b/src/commands/general/help.ts old mode 100644 new mode 100755 index 9638b50c..c6bc4ef0 --- a/src/commands/general/help.ts +++ b/src/commands/general/help.ts @@ -1,42 +1,42 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import { categories } from "../../utils/Constants.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import { categories, Platform } from "../../utils/Constants.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; + +const emoji = `:small_blue_diamond:`; export default class HelpCommand extends Command { constructor(client: AldebaranClient) { super(client, { - description: "Displays detailled help about the bot's commands" + description: "Displays detailled help about the bot's commands", + args: { query: { + as: "string", + desc: "The command or command category whose details you want to see", + optional: true + } } }); } - async run(ctx: MessageContext) { - const args = ctx.args as string[]; - if (args[0] !== undefined) { - const match = categories[args[0].toLowerCase()]; + async run(ctx: MessageContext, platform: Platform) { + const { query } = ctx.args as { query?: string }; + if (query) { + const command = query.toLowerCase(); + const match = categories[command]; const category = typeof match === "string" ? categories[match] : match; if (category !== undefined) { - let list = ""; - const categoryCommands = new Map(); - for (const cmd of ctx.client.commands.commands) { - categoryCommands.set(...cmd); - } - for (const [cmd, data] of categoryCommands) { - if (data.category === category.name && !data.aliases.includes(cmd)) { - list += `:small_blue_diamond: **${cmd}** : ${data.shortDesc}\n`; - } - } + const list = ctx.client.commands.commands + .filter(c => (c.category === category.name || c.matches(command)) + && c.supports(platform)) + .reduce((acc, c) => `${acc}${emoji} **${c.name}** : ${c.shortDesc}\n`, ""); const categoryEmbed = new MessageEmbed() .setAuthor("Category Help", ctx.client.user.avatarURL()!) .setTitle(`${category.title} - ${category.description}`) .setDescription(list) .setColor(this.color); ctx.reply({ embeds: [categoryEmbed] }); - } else if (ctx.client.commands.exists(args[0].toLowerCase())) { - ctx.reply( - ctx.client.commands.getHelp(args[0].toLowerCase(), ctx.prefix) - ); + } else if (ctx.client.commands.exists(command, platform)) { + ctx.reply(ctx.client.commands.get(command, platform)!.toHelpEmbed()); } else { ctx.error("NOT_FOUND", "You are trying to find help for a command or a category that does not exist. Make sure you did not make a typo in your request."); } diff --git a/src/commands/general/info.ts b/src/commands/general/info.ts old mode 100644 new mode 100755 index edbf74f6..968cdb58 --- a/src/commands/general/info.ts +++ b/src/commands/general/info.ts @@ -2,7 +2,7 @@ import { MessageEmbed, version } from "discord.js"; import { Command } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { formatNumber } from "../../utils/Methods.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class InfoCommand extends Command { constructor(client: AldebaranClient) { @@ -53,10 +53,9 @@ export default class InfoCommand extends Command { ) .addField("Privacy Policy", "As of now, if Aldebaran has read permissions in a channel, it can read all messages inside it. Because Discord now requires Discord bot developers to be transparent about how they use messages' content, you should know about [Aldebaran's Privacy Policy](https://aldebaran.ciborn.dev/privacy-policy).") .setThumbnail(ctx.client.user.avatarURL()!) - .setColor(ctx.message.guild ? ctx.message.guild.me!.displayColor : "BLUE"); - if (ctx.message.guild) { - const prefix = (await ctx.guild())!.prefix; - embed.setFooter(`The prefix in this guild is "${prefix}".`); + .setColor(ctx.guild ? ctx.guild.guild.me!.displayColor : "BLUE"); + if (ctx.guild) { + embed.setFooter(`The prefix in this guild is "${ctx.prefix}".`); } ctx.reply(embed); } diff --git a/src/commands/general/invite.ts b/src/commands/general/invite.ts old mode 100644 new mode 100755 index 51fef259..44178ae7 --- a/src/commands/general/invite.ts +++ b/src/commands/general/invite.ts @@ -1,23 +1,37 @@ -import { MessageEmbed } from "discord.js"; +import { MessageActionRow, MessageButton, MessageEmbed } from "discord.js"; import { Command } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import DiscordMessageContext from "../../structures/contexts/DiscordMessageContext.js"; +import DiscordSlashMessageContext from "../../structures/contexts/DiscordSlashMessageContext.js"; -const botInvite = process.env.BOT_INVITE || "https://discordapp.com/api/oauth2/authorize?client_id=437802197539880970&permissions=60480&scope=bot"; +const botInvite = process.env.BOT_INVITE || "https://discordapp.com/api/oauth2/authorize?client_id=437802197539880970&permissions=60480&scope=bot%20applications.commands"; const serverInvite = process.env.SERVER_INVITE || "https://discord.gg/8J8ZH9AjsC"; export default class InviteCommand extends Command { constructor(client: AldebaranClient) { super(client, { - description: "Displays the bot and server invites" + description: "Displays the bot and server invites", + platforms: ["DISCORD", "DISCORD_SLASH"] }); } - run(ctx: MessageContext) { + run(ctx: DiscordMessageContext | DiscordSlashMessageContext) { const embed = new MessageEmbed() .setTitle("Invite Links") - .setDescription(`[__**Add Bot To Your Server**__](${botInvite})\n*Let the fun commands start*\n[__**Join Support Server**__](${serverInvite})\n*Stay updated with the newest features and commands*`) + .addField("Bot invite link", `[**Add ${this.client.name} to your server**](${botInvite})\n*Let the fun commands start!*`) + .addField("Support server link", `[**Join Support Server**](${serverInvite})\n*Stay updated with the newest features and commands!*`) .setColor(this.color); - ctx.reply(embed); + + const botButton = new MessageButton() + .setStyle("LINK") + .setLabel("Bot invite link") + .setURL(botInvite); + const serverButton = new MessageButton() + .setStyle("LINK") + .setLabel("Support server link") + .setURL(serverInvite); + const actionRow = new MessageActionRow() + .setComponents([botButton, serverButton]); + ctx.reply({ embeds: [embed], components: [actionRow] }); } }; diff --git a/src/commands/general/ping.ts b/src/commands/general/ping.ts old mode 100644 new mode 100755 index b6d667a4..4718d486 --- a/src/commands/general/ping.ts +++ b/src/commands/general/ping.ts @@ -1,7 +1,10 @@ -import { ColorResolvable, MessageEmbed } from "discord.js"; +import { ColorResolvable, Message, MessageEmbed } from "discord.js"; import { Command } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; +import { Platform } from "../../utils/Constants.js"; +import DiscordMessageContext from "../../structures/contexts/DiscordMessageContext.js"; +import DiscordSlashMessageContext from "../../structures/contexts/DiscordSlashMessageContext.js"; const messages = { good: [ @@ -25,18 +28,24 @@ export default class PingCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays the bot's current ping to Discord", - aliases: ["pong"] + aliases: ["pong"], + platforms: ["DISCORD", "DISCORD_SLASH"] }); } // eslint-disable-next-line class-methods-use-this - async run(ctx: MessageContext) { + async run(ctx: MessageContext, platform: Platform) { const embed = new MessageEmbed() .addField("WebSocket Heartbeat", `${Math.floor(ctx.client.ws.ping)} ms`, true) .addField(`${ctx.client.name} Ping`, "Computing...", true) .setColor("BLUE"); - const newMessage = await ctx.reply(embed); - const ping = newMessage.createdTimestamp - ctx.message.createdTimestamp; + let msg = null; + if (platform === "DISCORD") { + msg = await (ctx as DiscordMessageContext).reply(embed); + } else if (platform === "DISCORD_SLASH") { + msg = await (ctx as DiscordSlashMessageContext).reply(embed, false, true); + } + const ping = msg!.createdTimestamp - ctx.createdTimestamp; let color: ColorResolvable = "BLUE"; let desc = "Hi."; @@ -62,6 +71,6 @@ export default class PingCommand extends Command { .addField("WebSocket Heartbeat", `${Math.floor(ctx.client.ws.ping)} ms`, true) .addField(`${ctx.client.name} Ping`, `${ping} ms`, true) .setColor(color); - newMessage.edit({ content: desc, embeds: [embedResult] }); + msg!.edit({ content: desc, embeds: [embedResult] }); } }; diff --git a/src/commands/general/profile.ts b/src/commands/general/profile.ts old mode 100644 new mode 100755 index acc0b10f..aa6a0817 --- a/src/commands/general/profile.ts +++ b/src/commands/general/profile.ts @@ -1,22 +1,25 @@ import { ColorResolvable, MessageEmbed } from "discord.js"; import { Command } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class ProfileCommand extends Command { constructor(client: AldebaranClient) { super(client, { - description: "Shows your social profile", - usage: "UserMention|UserID", + description: "Shows your Aldebaran social profile", example: "320933389513523220", - args: { user: { as: "user", optional: true } } + args: { user: { + as: "user", + desc: "The user whose social profile you want to see", + optional: true + } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { const args = ctx.args as { user: string }; - ctx.client.customUsers.fetch(args.user || ctx.message.author.id) + ctx.client.customUsers.fetch(args.user || ctx.author.id) .then(async user => { const profile = (await user.profile()).profile; if (profile.name) { @@ -44,8 +47,8 @@ export default class ProfileCommand extends Command { } else { const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("No Profile Found") .setDescription(`Please use \`${ctx.prefix}setprofile name \` to create your profile`) diff --git a/src/commands/general/suggest.ts b/src/commands/general/suggest.ts old mode 100644 new mode 100755 index 7506eb57..4826bc3b --- a/src/commands/general/suggest.ts +++ b/src/commands/general/suggest.ts @@ -2,30 +2,32 @@ import { MessageEmbed, WebhookClient } from "discord.js"; import { Command } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class SuggestCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Sends a suggestion", - usage: "Suggestion", - example: "more nsfw commands" + example: "more nsfw commands", + args: { suggestion: { + as: "string", + desc: "Details about the suggestion you want to make" + } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const args = ctx.args as string[]; - if (args.length === 0) return ctx.reply("You can't send an empty suggestion."); + const { suggestion } = ctx.args as { suggestion: string }; const embed = new MessageEmbed() - .setDescription(args.join(" ")) - .setFooter(`User: ${ctx.message.author.tag} [ID: ${ctx.message.author.id}]`); + .setDescription(suggestion) + .setFooter(`User: ${ctx.author.user.tag} [ID: ${ctx.author.id}]`); new WebhookClient({ - id: process.env.WEBHOOK_SUGGESTION_ID!, - token: process.env.WEBHOOK_SUGGESTION_TOKEN! + id: process.env.WEBHOOK_SUGGESTIONS_ID!, + token: process.env.WEBHOOK_SUGGESTIONS_TOKEN! }).send({ - username: ctx.message.author.username, - avatarURL: ctx.message.author.displayAvatarURL(), + username: ctx.author.username, + avatarURL: ctx.author.avatarURL, embeds: [embed] }).then(() => { ctx.reply("Your suggestion has been sent to the main server!"); diff --git a/src/commands/general/time.ts b/src/commands/general/time.ts old mode 100644 new mode 100755 index aef784ff..68db99f7 --- a/src/commands/general/time.ts +++ b/src/commands/general/time.ts @@ -1,7 +1,7 @@ import moment from "moment-timezone"; import { Command, Embed } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class TimeCommand extends Command { constructor(client: AldebaranClient) { @@ -9,7 +9,11 @@ export default class TimeCommand extends Command { description: "Prints a user's time based on their configured timezone", example: "<@143026985763864576>", args: { - user: { as: "user", optional: true }, + user: { + as: "user", + desc: "The user whose time you want to know", + optional: true + }, clean: { as: "boolean", flag: { short: "c", long: "clean" }, @@ -23,7 +27,7 @@ export default class TimeCommand extends Command { async run(ctx: MessageContext) { const args = ctx.args as { user?: string, clean?: boolean }; const user = await ctx.client.customUsers - .fetch(args.user || ctx.message.author.id); + .fetch(args.user || ctx.author.id); let { timezone } = user.settings; if (timezone !== undefined) { if (!timezone.includes("/")) { @@ -61,7 +65,7 @@ export default class TimeCommand extends Command { embed.setFooter("If this is inaccurate, try setting a tz timezone instead of a GMT-based timezone!"); ctx.reply(embed); } - } else if (user.user.equals(ctx.message.author)) { + } else if (user.user.equals(ctx.author.user)) { ctx.reply( `it seems that you do not have configured your timezone. Please check \`${ ctx.prefix diff --git a/src/commands/general/user.ts b/src/commands/general/user.ts old mode 100644 new mode 100755 index 5da0825b..f671982c --- a/src/commands/general/user.ts +++ b/src/commands/general/user.ts @@ -2,41 +2,40 @@ import { MessageEmbed } from "discord.js"; import { getDateWithTimezone } from "../../utils/Methods.js"; import { Command } from "../../groups/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class UserCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Shows detailled user information", - usage: "UserMention/UserID", example: "437802197539880970", - args: { user: { as: "user", optional: true } } + args: { user: { + as: "user", + desc: "The user whose information you want to see", + optional: true + } } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { const args = ctx.args as { user: string }; - ctx.client.customUsers.fetch(args.user || ctx.message.author.id) + ctx.client.customUsers.fetch(args.user || ctx.author.id) .then(async user => { const allRoles = new Map(); const rolesList = []; const allPermissions = []; let mjd = null; let memberNick = null; - const member = ctx.message.guild - ? await ctx.message.guild.members.fetch(user.id) - : null; - if (member) { - mjd = new Date(member.joinedTimestamp!); - memberNick = member.nickname === undefined - ? null : member.nickname; - if (member.permissions.has("ADMINISTRATOR")) + if (ctx.member) { + mjd = new Date(ctx.member.joinedTimestamp!); + memberNick = ctx.member.nickname === undefined + ? null : ctx.member.nickname; + if (ctx.member.permissions.has("ADMINISTRATOR")) allPermissions.push("Administrator"); else { - // eslint-disable-next-line prefer-const for (let [name, value] of Object.entries( - member.permissions.serialize() + ctx.member.permissions.serialize() )) { if (value) { const splitName = name.toLowerCase().split("_"); @@ -47,7 +46,7 @@ export default class UserCommand extends Command { } } } - for (const [id, data] of member.roles.cache) + for (const [id, data] of ctx.member.roles.cache) if (data.name !== "@everyone") allRoles.set(id, data.rawPosition); // eslint-disable-next-line func-names allRoles[Symbol.iterator] = function* () { @@ -74,25 +73,25 @@ export default class UserCommand extends Command { const embed = new MessageEmbed() .setAuthor( - `${user.user.tag} | ${member ? `${ctx.message.guild!.name} | Member Details` : "User Details"}`, + `${user.user.tag} | ${ctx.guild ? `${ctx.guild.guild.name} | Member Details` : "User Details"}`, user.user.displayAvatarURL() ) .setDescription(`**User ID** ${user.id}\n${memberNick !== null ? `**Nickname** ${memberNick}\n` : ""}`) .setThumbnail(user.user.displayAvatarURL()) - .setColor(member ? member.displayColor : this.color) + .setColor(ctx.member ? ctx.member.displayColor : this.color) .setFooter("User account created on") .setTimestamp(new Date(user.user.createdTimestamp)); if (mjd !== null) embed.addField( "Server Join Date", `${getDate(mjd)} - ${ - ctx.message.author.id === user.id ? "You have" : "This user has" + ctx.author.id === user.id ? "You have" : "This user has" } been on this server for **${Math.floor( (Date.now() - mjd.getTime()) / 86400000 )} days**.` ); if (rolesList.length > 0) - embed.addField(`Roles (${member!.roles.cache.size - 1})`, `${rolesList.join(", ")}`); + embed.addField(`Roles (${ctx.member!.roles.cache.size - 1})`, `${rolesList.join(", ")}`); if (allPermissions.length > 0) embed.addField("Permissions", allPermissions.join(", ")); ctx.reply(embed); diff --git a/src/commands/image/birb.ts b/src/commands/image/birb.ts old mode 100644 new mode 100755 index 090828c2..713659ca --- a/src/commands/image/birb.ts +++ b/src/commands/image/birb.ts @@ -1,7 +1,7 @@ import request from "request"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class BirbCommand extends Command { constructor(client: AldebaranClient) { @@ -9,12 +9,12 @@ export default class BirbCommand extends Command { } run(ctx: MessageContext) { - request({ uri: "http://random.birb.pw/tweet.json/" }, (err, response, body) => { + request({ uri: "https://some-random-api.ml/img/birb" }, (err, response, body) => { if (err || response.statusCode !== 200) return ctx.reply("This seems to be a birb problem"); const embed = new Embed(this) .setTitle("You want some __Birb__?") - .setImage(`http://random.birb.pw/img/${JSON.parse(body).file}`) - .setFooter("Birb powered by http://random.brib.pw"); + .setImage(JSON.parse(body).link) + .setFooter("Birb powered by https://some-random-api.ml/img/birb"); return ctx.reply(embed); }); } diff --git a/src/commands/image/bunny.ts b/src/commands/image/bunny.ts old mode 100644 new mode 100755 index 80687c7b..ddb27138 --- a/src/commands/image/bunny.ts +++ b/src/commands/image/bunny.ts @@ -1,7 +1,7 @@ import request from "request"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class BunnyCommand extends Command { constructor(client: AldebaranClient) { diff --git a/src/commands/image/cat.ts b/src/commands/image/cat.ts old mode 100644 new mode 100755 index 3bb9bd6b..285c84d2 --- a/src/commands/image/cat.ts +++ b/src/commands/image/cat.ts @@ -2,7 +2,7 @@ import request from "request"; import parser from "xml2js"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; type ExpectedResponse = { response: { diff --git a/src/commands/image/cuteag.ts b/src/commands/image/cuteag.ts deleted file mode 100644 index 60747f11..00000000 --- a/src/commands/image/cuteag.ts +++ /dev/null @@ -1,24 +0,0 @@ -import request from "request"; -import { Command, Embed } from "../../groups/ImageCommand.js"; -import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; - -export default class CuteagCommand extends Command { - constructor(client: AldebaranClient) { - super(client, { - description: "Displays a random cute anime girl picture" - }); - } - - run(ctx: MessageContext) { - request({ uri: "http://api.cutegirls.moe/json" }, (err, response, body) => { - if (err) return; - const { data } = JSON.parse(body); - const embed = new Embed(this) - .setTitle(data.title) - .setImage(data.image) - .setFooter(`Source: ${data.link}`); - ctx.reply(embed); - }); - } -}; diff --git a/src/commands/image/dog.ts b/src/commands/image/dog.ts old mode 100644 new mode 100755 index 5b07141e..545351fb --- a/src/commands/image/dog.ts +++ b/src/commands/image/dog.ts @@ -1,7 +1,7 @@ import request from "request"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class DogCommand extends Command { constructor(client: AldebaranClient) { diff --git a/src/commands/image/duck.ts b/src/commands/image/duck.ts old mode 100644 new mode 100755 index 3d573650..4cc9f159 --- a/src/commands/image/duck.ts +++ b/src/commands/image/duck.ts @@ -1,7 +1,7 @@ import request from "request"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class DuckCommand extends Command { constructor(client: AldebaranClient) { diff --git a/src/commands/image/hedgehog.ts b/src/commands/image/hedgehog.ts old mode 100644 new mode 100755 index a75b3005..69c36e3b --- a/src/commands/image/hedgehog.ts +++ b/src/commands/image/hedgehog.ts @@ -1,7 +1,7 @@ import request from "request"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class HedgehogCommand extends Command { constructor(client: AldebaranClient) { diff --git a/src/commands/image/lizard.ts b/src/commands/image/lizard.ts old mode 100644 new mode 100755 index e3a9fb7a..d9522236 --- a/src/commands/image/lizard.ts +++ b/src/commands/image/lizard.ts @@ -1,11 +1,11 @@ import { Command as C, Embed as E } from "../../groups/ImageCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); -export default class NekoCommand extends Command { +export default class LizardCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Displays a random lizard picture or a GIF" diff --git a/src/commands/image/neko.ts b/src/commands/image/neko.ts old mode 100644 new mode 100755 index e7df0322..584999de --- a/src/commands/image/neko.ts +++ b/src/commands/image/neko.ts @@ -1,7 +1,7 @@ import { Command as C, Embed as E } from "../../groups/ImageCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); @@ -14,7 +14,7 @@ export default class NekoCommand extends Command { async run(ctx: MessageContext) { const embed = new Embed(this, - `${ctx.message.author}, here is your innocent neko.`); + `<@${ctx.author.id}>, here is your innocent neko.`); embed.send(ctx, ctx.client.nekoslife.sfw.neko); } }; diff --git a/src/commands/image/panda.ts b/src/commands/image/panda.ts old mode 100644 new mode 100755 index 61fbc981..d8f2f782 --- a/src/commands/image/panda.ts +++ b/src/commands/image/panda.ts @@ -1,7 +1,7 @@ import request from "request"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class PandaCommand extends Command { constructor(client: AldebaranClient) { diff --git a/src/commands/image/pepe.ts b/src/commands/image/pepe.ts old mode 100644 new mode 100755 index 504f6e18..6fc89f5e --- a/src/commands/image/pepe.ts +++ b/src/commands/image/pepe.ts @@ -2,7 +2,7 @@ import tenor from "tenorjs"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; type Post = { media: { diff --git a/src/commands/image/randimal.ts b/src/commands/image/randimal.ts old mode 100644 new mode 100755 index cb4e2eb1..1ab8dc36 --- a/src/commands/image/randimal.ts +++ b/src/commands/image/randimal.ts @@ -1,7 +1,7 @@ import request from "request"; import { Command, Embed } from "../../groups/ImageCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class RandimalCommand extends Command { constructor(client: AldebaranClient) { diff --git a/src/commands/image/rcgp.ts b/src/commands/image/rcgp.ts new file mode 100755 index 00000000..fb387cf2 --- /dev/null +++ b/src/commands/image/rcgp.ts @@ -0,0 +1,24 @@ +import request from "request"; +import { Command, Embed } from "../../groups/ImageCommand.js"; +import AldebaranClient from "../../structures/djs/Client.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; + +export default class RCGPCommand extends Command { + constructor(client: AldebaranClient) { + super(client, { + description: "Displays a random cute anime girl holding a programming book" + }); + } + + run(ctx: MessageContext) { + request({ uri: "https://rcgp.anjara.eu/api/image" }, (err, response, body) => { + if (err) return; + const { src, path } = JSON.parse(body); + const embed = new Embed(this) + .setTitle(src) + .setImage(`https://rcgp.anjara.eu/storage/${path}`) + .setFooter(`Powered by https://rcgp.anjara.eu`); + ctx.reply(embed); + }); + } +}; diff --git a/src/commands/nsfw/lewd.ts b/src/commands/nsfw/lewd.ts old mode 100644 new mode 100755 index 99879b55..5fc517af --- a/src/commands/nsfw/lewd.ts +++ b/src/commands/nsfw/lewd.ts @@ -1,15 +1,14 @@ import { Command, Embed } from "../../groups/NSFWCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { imageUrls } from "../../utils/Constants.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class LewdCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Performs a lewd action on the specified user", - usage: "User", example: "<@437802197539880970>", - args: { user: { as: "user" } } + args: { user: { as: "user", desc: "The user you want to be lewd to" } } }); } @@ -19,7 +18,7 @@ export default class LewdCommand extends Command { .lewd[Math.floor(Math.random() * imageUrls.lewd.length)]; ctx.client.users.fetch(args.user).then(target => { const embed = new Embed(this) - .setDescription(`${ctx.message.author} is being lewd towards ${target}`) + .setDescription(`${ctx.author} is being lewd towards ${target}`) .setImage(sendlewds); ctx.reply(embed); }).catch(() => { diff --git a/src/commands/nsfw/xboobs.ts b/src/commands/nsfw/xboobs.ts old mode 100644 new mode 100755 index 02a84e9f..72821155 --- a/src/commands/nsfw/xboobs.ts +++ b/src/commands/nsfw/xboobs.ts @@ -1,7 +1,7 @@ import { Command as C, Embed as E } from "../../groups/NSFWCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); @@ -14,7 +14,7 @@ export default class XBoobsCommand extends Command { async run(ctx: MessageContext) { const embed = new Embed(this, - `${ctx.message.author} You want boobs? I give you... BOOBS!`); + `${ctx.author} You want boobs? I give you... BOOBS!`); embed.send(ctx, ctx.client.nekoslife.nsfw.boobs); } }; diff --git a/src/commands/nsfw/xkitty.ts b/src/commands/nsfw/xkitty.ts old mode 100644 new mode 100755 index 927ac921..9a3a228f --- a/src/commands/nsfw/xkitty.ts +++ b/src/commands/nsfw/xkitty.ts @@ -1,7 +1,7 @@ import { Command as C, Embed as E } from "../../groups/NSFWCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); @@ -14,7 +14,7 @@ export default class XKittyCommand extends Command { async run(ctx: MessageContext) { const embed = new Embed(this, - `${ctx.message.author}, here is your kitty!`); + `${ctx.author}, here is your kitty!`); embed.send(ctx, ctx.client.nekoslife.nsfw.pussy); } }; diff --git a/src/commands/nsfw/xlesbian.ts b/src/commands/nsfw/xlesbian.ts old mode 100644 new mode 100755 index a0e31afa..a00332c9 --- a/src/commands/nsfw/xlesbian.ts +++ b/src/commands/nsfw/xlesbian.ts @@ -1,7 +1,7 @@ import { Command as C, Embed as E } from "../../groups/NSFWCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); @@ -14,7 +14,7 @@ export default class XLesbianCommand extends Command { async run(ctx: MessageContext) { const embed = new Embed(this, - `${ctx.message.author} LEZ be Honest!`); + `${ctx.author} LEZ be Honest!`); embed.send(ctx, ctx.client.nekoslife.nsfw.lesbian); } }; diff --git a/src/commands/nsfw/xneko.ts b/src/commands/nsfw/xneko.ts old mode 100644 new mode 100755 index b04f89fc..206b986d --- a/src/commands/nsfw/xneko.ts +++ b/src/commands/nsfw/xneko.ts @@ -1,7 +1,7 @@ import { Command as C, Embed as E } from "../../groups/NSFWCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); @@ -14,7 +14,7 @@ export default class XNekoCommand extends Command { async run(ctx: MessageContext) { const embed = new Embed(this, - `${ctx.message.author}, here is your naughty neko.`); + `${ctx.author}, here is your naughty neko.`); embed.send(ctx, ctx.client.nekoslife.nsfw.nekoGif); } }; diff --git a/src/commands/nsfw/xrandom.ts b/src/commands/nsfw/xrandom.ts old mode 100644 new mode 100755 index 57416183..43a35a07 --- a/src/commands/nsfw/xrandom.ts +++ b/src/commands/nsfw/xrandom.ts @@ -1,7 +1,7 @@ import { Command as C, Embed as E } from "../../groups/NSFWCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); @@ -14,7 +14,7 @@ export default class XRandomCommand extends Command { async run(ctx: MessageContext) { const embed = new Embed(this, - `${ctx.message.author}, you wanted something random? Here you go!`); + `${ctx.author}, you wanted something random? Here you go!`); embed.send(ctx, ctx.client.nekoslife.nsfw.randomHentaiGif); } }; diff --git a/src/commands/osu!/osu.ts b/src/commands/osu!/osu.ts old mode 100644 new mode 100755 index a683c39e..5bd4f0e3 --- a/src/commands/osu!/osu.ts +++ b/src/commands/osu!/osu.ts @@ -1,7 +1,7 @@ import { Mode, User } from "nodesu"; import { Command, Embed } from "../../groups/OsuCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import { OsuMode } from "../../utils/Constants.js"; const f = (x: number | string) => x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); @@ -25,8 +25,13 @@ export default class OsuCommand extends Command { example: "Ciborn --mania", aliases: ["osuprofile"], args: { - user: { as: "word", desc: "Username/UserID", optional: true }, - mode: { as: "mode", optional: true } + user: { as: "string", desc: "Username/UserID", optional: true }, + mode: { + as: "mode", + choices: [["osu!", "osu"], ["osu!mania", "mania"], ["osu!ctb", "ctb"], ["osu!taiko", "taiko"]], + desc: "osu! Mode", + optional: true + } } }); } @@ -34,13 +39,12 @@ export default class OsuCommand extends Command { async run(ctx: MessageContext) { const args = ctx.args as { user?: string, mode?: string }; const client = ctx.client.nodesu!; - const author = await ctx.author(); - const mode = (args.mode || author.settings.osumode || "osu") as OsuMode; + const mode = (args.mode || ctx.author.settings.osumode || "osu") as OsuMode; if (Mode[mode] !== undefined) { client.user.get( args.user - || author.settings.osuusername - || author.username, + || ctx.author.settings.osuusername + || ctx.author.username, Mode[mode] ).then(data => { const user = new User(data); diff --git a/src/commands/osu!/osubest.ts b/src/commands/osu!/osubest.ts old mode 100644 new mode 100755 index e3b859ee..c222bc60 --- a/src/commands/osu!/osubest.ts +++ b/src/commands/osu!/osubest.ts @@ -3,7 +3,7 @@ import ojsama from "ojsama"; import ppv2Results, { Result } from "../../utils/osu!/ppv2Results.js"; import { Command, Embed } from "../../groups/OsuCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import { OsuMode } from "../../utils/Constants.js"; type Score = { @@ -44,8 +44,13 @@ export default class OsubestCommand extends Command { example: "Ciborn", aliases: ["osutop"], args: { - user: { as: "word", desc: "Username/ID", optional: true }, - mode: { as: "mode", optional: true } + user: { as: "string", desc: "Username/UserID", optional: true }, + mode: { + as: "mode", + choices: [["osu!", "osu"], ["osu!mania", "mania"], ["osu!ctb", "ctb"], ["osu!taiko", "taiko"]], + desc: "osu! Mode", + optional: true + } } }); } @@ -53,13 +58,12 @@ export default class OsubestCommand extends Command { async run(ctx: MessageContext) { const args = ctx.args as { user?: string, mode?: string }; const client = ctx.client.nodesu!; - const author = await ctx.author(); - const mode = (args.mode || author.settings.osumode || "osu") as OsuMode; + const mode = (args.mode || ctx.author.settings.osumode || "osu") as OsuMode; if (Mode[mode] !== undefined) { client.user.getBest( args.user - || author.settings.osuusername - || author.username, + || ctx.author.settings.osuusername + || ctx.author.username, Mode[mode], 5 ).then(async (data: any) => { const best = data.reduce( diff --git a/src/commands/osu!/osumap.ts b/src/commands/osu!/osumap.ts old mode 100644 new mode 100755 index f71ec69c..fe8019c1 --- a/src/commands/osu!/osumap.ts +++ b/src/commands/osu!/osumap.ts @@ -4,7 +4,7 @@ import retrieveBeatmapFile from "../../utils/osu!/retrieveBeatmapFile.js"; import ppv2Results from "../../utils/osu!/ppv2Results.js"; import { Command, Embed } from "../../groups/OsuCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const supportedMods = ["NF", "EZ", "HT", "SO", "HR", "DT", "NC", "HD", "FL"]; const d = (x: number | string) => (x.toString().length === 1 ? `0${x}` : x); @@ -27,6 +27,7 @@ export default class OsumapCommand extends Command { map: { as: "expression", regex: /\d+$/, desc: "Beatmap URL / ID" }, mode: { as: "mode", + choices: [["osu!", "osu"], ["osu!mania", "mania"], ["osu!ctb", "ctb"], ["osu!taiko", "taiko"]], desc: "Game Mode (--osu, --mania, --ctb, --taiko)", optional: true }, diff --git a/src/commands/osu!/osurecent.ts b/src/commands/osu!/osurecent.ts old mode 100644 new mode 100755 index 6a844f0e..349427f1 --- a/src/commands/osu!/osurecent.ts +++ b/src/commands/osu!/osurecent.ts @@ -3,7 +3,7 @@ import ojsama from "ojsama"; import ppv2Results, { Result } from "../../utils/osu!/ppv2Results.js"; import { Command, Embed } from "../../groups/OsuCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import { OsuMode } from "../../utils/Constants.js"; const ranks = { @@ -25,8 +25,13 @@ export default class OsurecentCommand extends Command { example: "Ciborn", aliases: ["osurs"], args: { - user: { as: "word", desc: "Username/UserID", optional: true }, - mode: { as: "mode", optional: true } + user: { as: "string", desc: "Username/UserID", optional: true }, + mode: { + as: "mode", + choices: [["osu!", "osu"], ["osu!mania", "mania"], ["osu!ctb", "ctb"], ["osu!taiko", "taiko"]], + desc: "osu! Mode", + optional: true + } } }); } @@ -34,14 +39,13 @@ export default class OsurecentCommand extends Command { // eslint-disable-next-line class-methods-use-this async run(ctx: MessageContext) { const args = ctx.args as { user?: string, mode?: string }; - const author = await ctx.author(); const client = ctx.client.nodesu!; - const mode = (args.mode || author.settings.osumode || "osu") as OsuMode; + const mode = (args.mode || ctx.author.settings.osumode || "osu") as OsuMode; if (Mode[mode] !== undefined) { client.user.getRecent( args.user - || author.settings.osuusername - || author.username, + || ctx.author.settings.osuusername + || ctx.author.username, Mode[mode], 1 ).then(async data => { diff --git a/src/commands/settings/enabledrpg.ts b/src/commands/settings/enabledrpg.ts old mode 100644 new mode 100755 index 68349184..dc1c5436 --- a/src/commands/settings/enabledrpg.ts +++ b/src/commands/settings/enabledrpg.ts @@ -1,8 +1,10 @@ -import { MessageEmbed, MessageReaction, User } from "discord.js"; +import { Message, MessageActionRow, MessageButton, MessageEmbed, TextChannel } from "discord.js"; import { Command } from "../../groups/SettingsCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; -import { GuildSetting, UserSetting } from "../../utils/Constants.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; +import { GuildSetting, Platform, UserSetting } from "../../utils/Constants.js"; +import DiscordSlashMessageContext from "../../structures/contexts/DiscordSlashMessageContext.js"; +import DiscordMessageContext from "../../structures/contexts/DiscordMessageContext.js"; const guildParameters = [ { @@ -33,7 +35,8 @@ export default class EnableDRPGCommand extends Command { aliases: ["edrpg"], description: "Utility command to enable configuration values for DiscordRPG usage", - requiresGuild: true + requiresGuild: true, + platforms: ["DISCORD", "DISCORD_SLASH"] }); } @@ -45,62 +48,61 @@ export default class EnableDRPGCommand extends Command { .setDescription(`**This will enable the following ${ type} settings:**\n${ parameters.reduce((p, c) => `${p}${`${c.description} - \`${c.name}\``}\n`, "") - }**Do you want to proceed?** Click :white_check_mark: to continue. You can always configure the settings in \`${ctx.prefix}${type[0]}config\`.`) + }**Do you want to proceed?** Click the **Proceed** button to continue. You can always configure the settings using \`${ctx.prefix}${type[0]}config\`.`) .setColor("BLUE"); } - setUserSettings(ctx: MessageContext) { + setSettings( + ctx: DiscordMessageContext | DiscordSlashMessageContext, + type: "user" | "guild", + ) { return new Promise(async resolve => { - const author = await ctx.author(); - const embed = this.configuringEmbed(ctx, "user"); - const checkMark = "✅"; - const filter = (r: MessageReaction, u: User) => r.emoji.name === checkMark - && u.id === ctx.message.author.id; - const msg = await ctx.reply(embed); - await msg.react(checkMark); - msg.awaitReactions({ filter, time: 30000, max: 1, errors: ["time"] }) - .then(() => { + const embed = this.configuringEmbed(ctx, type); + const button = new MessageButton() + .setStyle("PRIMARY") + .setLabel("Proceed") + .setCustomId("ok"); + const actionRow = new MessageActionRow().setComponents([button]); + const opt = { embeds: [embed], components: [actionRow] }; + const msg = ctx instanceof DiscordSlashMessageContext + ? await ctx.reply(opt, true, true) + : await ctx.reply(opt); + + msg.awaitMessageComponent({ componentType: "BUTTON" }).then(interaction => { + if (type === "user") { userParameters.forEach(parameter => { - author.changeSetting(parameter.name as UserSetting, "on"); + ctx.author.changeSetting(parameter.name as UserSetting, "on"); }); - resolve(true); - }).catch(() => { - msg.reactions.removeAll(); - msg.edit("The operation has been cancelled."); - }); - }); - } - - setGuildSettings(ctx: MessageContext) { - return new Promise(async resolve => { - const guild = (await ctx.guild())!; - const embed = this.configuringEmbed(ctx, "guild"); - const checkMark = "✅"; - const filter = (r: MessageReaction, u: User) => r.emoji.name === checkMark - && u.id === ctx.message.author.id; - const msg = await ctx.reply(embed); - await msg.react(checkMark); - msg.awaitReactions({ filter, time: 30000, max: 1, errors: ["time"] }).then(() => { - guildParameters.forEach(parameter => { - guild.changeSetting(parameter.name as GuildSetting, "on"); - }); + } else { + guildParameters.forEach(parameter => { + ctx.guild!.changeSetting(parameter.name as GuildSetting, "on"); + }); + } + interaction.deferUpdate(); resolve(true); }).catch(() => { - msg.reactions.removeAll(); msg.edit("The operation has been cancelled."); }); }); } // eslint-disable-next-line class-methods-use-this - done(ctx: MessageContext) { + done( + ctx: DiscordMessageContext | DiscordSlashMessageContext, + followUp: boolean = false + ) { const embed = new MessageEmbed() .setTitle("Done!") .setDescription( `${ctx.client.name}'s DRPG features are now enabled. Feel free to use DRPG normally. ${ctx.client.name} will respond appropriately when your adventure and sides are ready, and when you have low health.\nYou can always turn off features in \`${ctx.prefix}uconfig\` and \`${ctx.prefix}gconfig\`.\n*If this guild has changed its DRPG prefix, it must also be set using \`${ctx.prefix}gconfig discordrpgPrefix \`.*` ) .setColor("GREEN"); - ctx.reply(embed); + + if (ctx instanceof DiscordSlashMessageContext) { + followUp ? ctx.followUp(embed, true) : ctx.reply(embed, true); + } else { + ctx.reply(embed); + } } // eslint-disable-next-line class-methods-use-this @@ -115,36 +117,31 @@ export default class EnableDRPGCommand extends Command { } // eslint-disable-next-line class-methods-use-this - async run(ctx: MessageContext) { - const author = await ctx.author(); - const guild = (await ctx.guild())!; - - const isAdmin = ctx.message.member! - .permissionsIn(ctx.channel) + async run(ctx: DiscordMessageContext | DiscordSlashMessageContext) { + const isAdmin = ctx.member! + .permissionsIn(ctx.channel as TextChannel) .has("MANAGE_GUILD"); const guildEnabled = guildParameters - .every(parameter => guild.settings[parameter.name as GuildSetting] === "on"); + .every(parameter => ctx.guild!.settings[parameter.name as GuildSetting] === "on"); const userEnabled = userParameters - .every(parameter => author.settings[parameter.name as UserSetting] === "on"); + .every(parameter => ctx.author.settings[parameter.name as UserSetting] === "on"); if (isAdmin && !guildEnabled && !userEnabled) { - await this.setGuildSettings(ctx); - await this.setUserSettings(ctx); - this.done(ctx); + await this.setSettings(ctx, "guild"); + await this.setSettings(ctx, "user"); + this.done(ctx, true); } else if (isAdmin && !guildEnabled) { - await this.setGuildSettings(ctx); - this.done(ctx); + await this.setSettings(ctx, "guild"); + this.done(ctx, true); } else if (isAdmin && !userEnabled) { - await this.setUserSettings(ctx); - this.done(ctx); - } else if (isAdmin) { - this.done(ctx); + await this.setSettings(ctx, "user"); + this.done(ctx, true); } else if (!isAdmin && !guildEnabled) { this.noPermissions(ctx); } else if (!isAdmin && !userEnabled) { - await this.setUserSettings(ctx); - this.done(ctx); + await this.setSettings(ctx, "user"); + this.done(ctx, true); } else { this.done(ctx); } diff --git a/src/commands/settings/gconfig.ts b/src/commands/settings/gconfig.ts old mode 100644 new mode 100755 index 26be6456..f8932d39 --- a/src/commands/settings/gconfig.ts +++ b/src/commands/settings/gconfig.ts @@ -2,26 +2,34 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/SettingsCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { GuildSetting, Settings, SettingsModel, TargetedSettings } from "../../utils/Constants.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class GconfigCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Manages the settings of your server", - usage: "Parameter Value", example: "adventureTimer on", perms: { discord: ["MANAGE_GUILD"] }, - requiresGuild: true + requiresGuild: true, + args: { + setting: { + as: "string", + desc: "The setting you want to edit (or \"help\", \"list\" and \"view\" for more information)" + }, + value: { + as: "string", + desc: "The value to which you want to edit the setting you just selected, if any", + optional: true + } + } }); } // eslint-disable-next-line class-methods-use-this async run(ctx: MessageContext) { - const args = ctx.args as string[]; - const setting = args[0] as GuildSetting; - const guild = (await ctx.guild())!; + const args = ctx.args as { setting: string, value?: string }; const parametersAvailable = SettingsModel.guild as Settings["guild"]; - if (args.length === 0) { + if (args.setting === "help") { const embed = new MessageEmbed() .setAuthor("User Settings", ctx.client.user.avatarURL()!) .setDescription( @@ -29,14 +37,14 @@ export default class GconfigCommand extends Command { ) .setColor("BLUE"); ctx.reply(embed); - } else if (args.includes("list")) { + } else if (args.setting === "list") { const list: { [key: string]: { [key: string]: TargetedSettings } } = {}; for (const [key, data] of Object.entries(parametersAvailable)) { if (!list[data.category]) list[data.category] = {}; if (data.showOnlyIfBotIsInGuild) { try { // eslint-disable-next-line no-await-in-loop - await ctx.message.guild!.members.fetch(data.showOnlyIfBotIsInGuild); + await ctx.guild!.guild.members.fetch(data.showOnlyIfBotIsInGuild); list[data.category][key] = data; } catch {} // eslint-disable-line no-empty } else { @@ -45,8 +53,8 @@ export default class GconfigCommand extends Command { } const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Config Command Help Page") .setColor("BLUE"); @@ -60,9 +68,9 @@ export default class GconfigCommand extends Command { } } ctx.reply(embed); - } else if (args.includes("view")) { + } else if (args.setting === "view") { let list = ""; - for (const [key, value] of Object.entries(guild.settings)) { + for (const [key, value] of Object.entries(ctx.guild!.settings)) { list += `**${key}** - \`${value}\`\n`; } const embed = new MessageEmbed() @@ -70,44 +78,37 @@ export default class GconfigCommand extends Command { .setDescription(list === "" ? "None" : list) .setColor("BLUE"); ctx.reply(embed); - } else if (Object.keys(parametersAvailable).indexOf(args[0]) !== -1) { - if (parametersAvailable[setting]!.support(args[1])) { + } else if (Object.keys(parametersAvailable).includes(args.setting) && args.value) { + const setting = args.setting.toLowerCase() as GuildSetting; + if (parametersAvailable[setting]!.support(args.value)) { if (parametersAvailable[setting]!.postUpdate) { - /* eslint-disable no-param-reassign */ parametersAvailable[setting]!.postUpdate!( - args[1], - ctx.message.author, - ctx.message.guild! + args.value, + ctx.author.user, + ctx.guild!.guild ); } if (parametersAvailable[setting]!.postUpdate) { parametersAvailable[ setting - ]!.postUpdate!(args[1], ctx.message.author, ctx.message.guild!); - /* eslint-enable no-param-reassign */ + ]!.postUpdate!(args.value, ctx.author.user, ctx.guild!.guild); } - guild.changeSetting(setting, args[1]).then(() => { + ctx.guild!.changeSetting(setting, args.value).then(() => { const embed = new MessageEmbed() - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) + .setAuthor(ctx.author.username, ctx.author.avatarURL) .setTitle("Settings successfully changed") .setDescription( `The property **\`${ - args[0] + setting }\`** has successfully been changed to the value **\`${ - args[1] + args.value }\`**.` ) .setColor("GREEN"); ctx.reply(embed); }).catch(err => { const embed = new MessageEmbed() - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) + .setAuthor(ctx.author.username, ctx.author.avatarURL) .setTitle("An Error Occured") .setDescription( "An error occured and we could not change your settings. Please retry later." diff --git a/src/commands/settings/setprofile.ts b/src/commands/settings/setprofile.ts old mode 100644 new mode 100755 index 0f9d0023..147d6a18 --- a/src/commands/settings/setprofile.ts +++ b/src/commands/settings/setprofile.ts @@ -1,23 +1,31 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/SettingsCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import { SocialProfileProperty } from "../../utils/Constants.js"; export default class SetprofileCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Changes your profile information", - usage: "Section Input", - example: "aboutme My name is Xxx_FortnitePro_xxX!" + example: "aboutme My name is Xxx_FortnitePro_xxX!", + args: { + section: { + as: "string", + desc: "The name of the profile's section you want to edit" + }, + input: { + as: "string", + desc: "What you want to write in the section you just selected" + } + } }); } // eslint-disable-next-line class-methods-use-this async run(ctx: MessageContext) { - const args = ctx.args as string[]; - const profile = await (await ctx.author()).profile(); - const availableSections = ["aboutMe", "dmFriendly", "age", "gender", "name", "country", "timezone", "birthday", "profilePictureLink", "favoriteGames", "profileColor", "favoriteMusic", "socialLinks", "zodiacName", "flavorText"]; + const args = ctx.args as { section: string, input: string }; + const profile = await ctx.author.profile(); const sectionMatches = { profilepicturelink: "profilePictureLink", favoritegames: "favoriteGames", @@ -27,28 +35,18 @@ export default class SetprofileCommand extends Command { zodiacname: "zodiacName", flavortext: "flavorText" }; - const embed = new MessageEmbed() - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) - .setDescription("Please specify a section and value") - .setColor("RED") - .addField("**__Available Sections__**", `${availableSections.join(" | ")}`, false); - if (args.length <= 0) return ctx.reply(embed); - const section = args.shift()!.toLowerCase(); + const section = args.section.toLowerCase(); const profiletarget = (sectionMatches[section as keyof typeof sectionMatches] || section) as SocialProfileProperty; - const inputdata = args.join(" "); - profile.changeProperty(profiletarget, inputdata).then(() => { - ctx.reply(`Your ${profiletarget} has been updated to \`${inputdata}\`.`); + profile.changeProperty(profiletarget, args.input).then(() => { + ctx.reply(`Your ${profiletarget} has been updated to \`${args.input}\`.`); }).catch(() => { const error = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Unknown Profile Section") .setDescription("Please check to ensure this is a correct profile section. If you think the specified profile section was valid, please make sure the value is too.") diff --git a/src/commands/settings/uconfig.ts b/src/commands/settings/uconfig.ts old mode 100644 new mode 100755 index d3a8fa41..a968e5ea --- a/src/commands/settings/uconfig.ts +++ b/src/commands/settings/uconfig.ts @@ -2,24 +2,32 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../../groups/SettingsCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { GuildSetting, Settings, SettingsModel, TargetedSettings, UserSetting } from "../../utils/Constants.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class UconfigCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Manages your personal settings", - usage: "Parameter Value", - example: "adventureTimer on" + example: "adventureTimer on", + args: { + setting: { + as: "string", + desc: "The setting you want to edit (or \"help\", \"list\" and \"view\" for more information)" + }, + value: { + as: "string", + desc: "The value to which you want to edit the setting you just selected, if any", + optional: true + } + } }); } // eslint-disable-next-line class-methods-use-this async run(ctx: MessageContext) { - const args = ctx.args as string[]; - const author = await ctx.author(); - const setting = args[0] as UserSetting; + const args = ctx.args as { setting: string, value?: string }; const parametersAvailable = SettingsModel.user as Settings["user"]; - if (args.length === 0) { + if (args.setting === "help") { const embed = new MessageEmbed() .setAuthor("User Settings", ctx.client.user.avatarURL()!) .setDescription( @@ -30,14 +38,14 @@ export default class UconfigCommand extends Command { `Make sure to also use \`${ctx.prefix}gconfig\` for server settings.` ); ctx.reply(embed); - } else if (args.includes("list")) { + } else if (args.setting === "list") { const list: { [key: string]: { [key: string]: TargetedSettings } } = {}; for (const [key, data] of Object.entries(parametersAvailable)) { if (list[data.category] === undefined) list[data.category] = {}; - if (data.showOnlyIfBotIsInGuild && ctx.message.guild) { + if (data.showOnlyIfBotIsInGuild && ctx.guild) { try { // eslint-disable-next-line no-await-in-loop - await ctx.message.guild.members.fetch(data.showOnlyIfBotIsInGuild); + await ctx.guild.guild.members.fetch(data.showOnlyIfBotIsInGuild); list[data.category][key] = data; } catch {} // eslint-disable-line no-empty } else { @@ -46,21 +54,20 @@ export default class UconfigCommand extends Command { } const embed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setTitle("Config Command Help Page") .setDescription( `**__IMPORTANT: If the setting is disabled in ${ctx.prefix}gconfig by server owner, it will be ignored.__** If a server setting is undefined, a :warning: icon will appear in front of the concerned properties.` ) .setColor("BLUE"); - - const guild = (await ctx.guild())!; + for (const [category, parameters] of Object.entries(list)) { let entries = ""; for (const [key, data] of Object.entries(parameters)) { - if (ctx.message.guild) { - if (!guild.settings[key as GuildSetting] + if (ctx.guild) { + if (!ctx.guild.settings[key as GuildSetting] && ctx.client.models.settings.guild[key as GuildSetting] ) { entries += ":warning: "; @@ -73,9 +80,9 @@ export default class UconfigCommand extends Command { } } ctx.reply(embed); - } else if (args.includes("view")) { + } else if (args.setting === "view") { let list = ""; - for (const [key, value] of Object.entries(author.settings)) { + for (const [key, value] of Object.entries(ctx.author.settings)) { list += `**${key}** - \`${value}\`\n`; } const embed = new MessageEmbed() @@ -83,50 +90,43 @@ export default class UconfigCommand extends Command { .setDescription(list === "" ? "None" : list) .setColor("BLUE"); ctx.reply(embed); - } else if (Object.keys(parametersAvailable).indexOf(args[0]) !== -1) { - if (parametersAvailable[setting]!.support(args[1])) { - author.changeSetting(setting, args[1]) - .then(() => { - if (parametersAvailable[setting]!.postUpdate) { - /* eslint-disable no-param-reassign */ - parametersAvailable[setting]!.postUpdate!( - args[1], - ctx.message.author - ); - } - if (parametersAvailable[setting]!.postUpdate) { - parametersAvailable[setting]! - .postUpdate!(args[1], ctx.message.author); - } - const embed = new MessageEmbed() - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) - .setTitle("Settings successfully changed") - .setDescription( - `The property **\`${ - setting - }\`** has successfully been changed to the value **\`${ - args[1] - }\`**.` - ) - .setColor("GREEN"); - ctx.reply(embed); - }).catch(err => { - const embed = new MessageEmbed() - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) - .setTitle("An Error Occured") - .setDescription( - "An error occured and we could not change your settings. Please retry later." - ) - .setColor("RED"); - ctx.reply(embed); - throw err; - }); + } else if (Object.keys(parametersAvailable).includes(args.setting) && args.value) { + const setting = args.setting.toLowerCase() as UserSetting; + if (parametersAvailable[setting]!.support(args.value)) { + ctx.author.changeSetting(setting, args.value).then(() => { + if (parametersAvailable[setting]!.postUpdate) { + parametersAvailable[setting]!.postUpdate!( + args.value!, + ctx.author.user + ); + } + if (parametersAvailable[setting]!.postUpdate) { + parametersAvailable[setting]! + .postUpdate!(args.value!, ctx.author.user); + } + const embed = new MessageEmbed() + .setAuthor(ctx.author.username, ctx.author.avatarURL) + .setTitle("Settings successfully changed") + .setDescription( + `The property **\`${ + setting + }\`** has successfully been changed to the value **\`${ + args.value + }\`**.` + ) + .setColor("GREEN"); + ctx.reply(embed); + }).catch(err => { + const embed = new MessageEmbed() + .setAuthor(ctx.author.username, ctx.author.avatarURL) + .setTitle("An Error Occured") + .setDescription( + "An error occured and we could not change your settings. Please retry later." + ) + .setColor("RED"); + ctx.reply(embed); + throw err; + }); } else { const embed = new MessageEmbed() .setTitle("Not supported") diff --git a/src/commands/social/poke.ts b/src/commands/social/poke.ts old mode 100644 new mode 100755 index 93f5c196..6779f509 --- a/src/commands/social/poke.ts +++ b/src/commands/social/poke.ts @@ -1,7 +1,7 @@ import { Command as C, Embed as E } from "../../groups/SocialCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); @@ -17,7 +17,7 @@ export default class PokeCommand extends Command { async run(ctx: MessageContext) { const args = ctx.args as { target: string }; ctx.client.users.fetch(args.target).then(target => { - const embed = new Embed(this, `${ctx.message.author} is poking ${target}`); + const embed = new Embed(this, `<@${ctx.author.id}> is poking ${target}`); embed.send(ctx, ctx.client.nekoslife.sfw.poke); }).catch(() => { ctx.reply("Please mention someone :thinking:"); }); } diff --git a/src/commands/social/tickle.ts b/src/commands/social/tickle.ts old mode 100644 new mode 100755 index f301bdf7..4ff8c86b --- a/src/commands/social/tickle.ts +++ b/src/commands/social/tickle.ts @@ -1,7 +1,7 @@ import { Command as C, Embed as E } from "../../groups/SocialCommand.js"; import subCategory from "../../groups/multi/NekoslifeSubcategory.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const { Command, Embed } = subCategory(C, E); @@ -9,18 +9,17 @@ export default class TickleCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Tickle someone!", - example: "<@437802197539880970>" + example: "<@437802197539880970>", + args: { target: { as: "user", desc: "The person to tickle" } } }); } async run(ctx: MessageContext) { - if (ctx.message.mentions.users.first()) { - const target = ctx.message.mentions.users.first(); + const args = ctx.args as { target: string }; + ctx.client.users.fetch(args.target).then(target => { const embed = new Embed(this, - `${ctx.message.author} won't stop tickling ${target}!`); + `<@${ctx.author.id}> won't stop tickling ${target}!`); embed.send(ctx, ctx.client.nekoslife.sfw.tickle); - } else { - ctx.reply("Please mention someone :thinking:"); - } + }).catch(() => { ctx.reply("Please mention someone :thinking:"); }); } }; diff --git a/src/commands/utilities/curconv.ts b/src/commands/utilities/curconv.ts old mode 100644 new mode 100755 index f8d7e355..05077227 --- a/src/commands/utilities/curconv.ts +++ b/src/commands/utilities/curconv.ts @@ -2,7 +2,7 @@ import request, { Response } from "request"; import { Command, Embed } from "../../groups/UtilitiesCommand.js"; import { ICommand } from "../../interfaces/Command.js"; import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; const fixerURL = "http://data.fixer.io/api"; @@ -19,26 +19,22 @@ export default class CurConvCommand extends Command implements ICommand { super(client, { description: "Converts from one currency unit to another, or lists currency equalivents", - example: "USD GBP 10" + example: "USD GBP 10", + args: { + from: { as: "string", desc: "The currency you want to convert from" }, + to: { as: "string", desc: "The currency you want to convert to" }, + amount: { + as: "number", + desc: "The amount you want to convert", + optional: true + } + } }); } run(ctx: MessageContext) { - const args = ctx.args as string[]; - if (args.length < 2) { - ctx.error("MISSING_ARGS", "Please use `&?curconv` to see how to use this command!"); - } else if (args.length >= 2) { - const fromCurrency = args[0] as Currency; - const toCurrency = args[1] as Currency; - const value = Number(args[2]); - if (fromCurrency && toCurrency && value) { - this.convCurToAnotherCur(ctx, fromCurrency, toCurrency, value); - } else if (fromCurrency && toCurrency) { - this.convCurToAnotherCur(ctx, fromCurrency, toCurrency, 1); - } else { - ctx.error("WRONG_USAGE", "At least one argument is missing or incorrect. Please use `&?curconv` to see how to use this command!"); - } - } + const args = ctx.args as { from: Currency, to: Currency, amount: number }; + this.convCurToAnotherCur(ctx, args.from, args.to, args.amount || 1); } convCurToAnotherCur( diff --git a/src/commands/utilities/math.ts b/src/commands/utilities/math.ts old mode 100644 new mode 100755 index ee5ce177..d44082ff --- a/src/commands/utilities/math.ts +++ b/src/commands/utilities/math.ts @@ -3,44 +3,33 @@ import { evaluate } from "mathjs"; import { Command, Embed } from "../../groups/UtilitiesCommand.js"; import AldebaranClient from "../../structures/djs/Client.js"; import { formatNumber } from "../../utils/Methods.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default class MathCommand extends Command { constructor(client: AldebaranClient) { super(client, { description: "Evaluates a math expression", - usage: "Expression", example: "sqrt(4) * 2", - aliases: ["calc"] + aliases: ["calc"], + args: { + expression: { as: "string", desc: "The expression you want to evaluate" } + } }); } // eslint-disable-next-line class-methods-use-this run(ctx: MessageContext) { - const args = ctx.args as string[]; - if (args.length !== 0) { - let result: number | string; - try { - result = args.join(" ") === "10 + 9" || args.join(" ") === "10+9" - ? 21 - : evaluate(args.join(" ").replace(/,/g, "")); - } catch (err) { - result = "The specified math expression is invalid."; - } - const embed = new Embed(this) - .setTitle("Math Expression Evaluation") - .addField("Result", `\`\`\`${formatNumber(result)}\`\`\``); - ctx.reply(embed); - } else { - const embed = new MessageEmbed() - .setAuthor("You are using this command incorrectly.") - .setDescription("You need to specify something to calculate in order to make this command work.") - .setFooter( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) - .setColor("RED"); - ctx.reply(embed); + const { expression } = ctx.args as { expression: string }; + + let result: number | string; + try { + result = evaluate(expression.replace(/,/g, "")); + } catch (err) { + result = "The specified math expression is invalid."; } + const embed = new Embed(this) + .setTitle("Math Expression Evaluation") + .addField("Result", `\`\`\`${formatNumber(result)}\`\`\``); + ctx.reply(embed); } }; diff --git a/src/commands/utilities/translate.ts b/src/commands/utilities/translate.ts deleted file mode 100644 index 9aea7359..00000000 --- a/src/commands/utilities/translate.ts +++ /dev/null @@ -1,76 +0,0 @@ -import request from "request"; -import { Command, Embed } from "../../groups/UtilitiesCommand.js"; -import AldebaranClient from "../../structures/djs/Client.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; - -export default class TranslateCommand extends Command { - constructor(client: AldebaranClient) { - super(client, { - description: "Translates the specified word or the sentence into the specified language", - usage: "To (From) ToTranslate", - example: "fr en hello" - }); - } - - // eslint-disable-next-line class-methods-use-this - run(ctx: MessageContext) { - const args = ctx.args as string[]; - let initialLang: string | null = null; - let resultLang: string; - let content: string; - if (args.length >= 2) { - if (args[0].length === 2) { - resultLang = args.shift()!; - if (args[0].length === 2 && args.length >= 2) - initialLang = args.shift()!; - content = args.join(" "); - } else { - return ctx.reply( - "You seem to have specified an invalid language code. Please refer to to see the list of the supported languages." - ); - } - } else { - return ctx.reply( - "You have to specify at least the text to translate and what language you want it to be translated to." - ); - } - return request( - `https://translate.yandex.net/api/v1.5/tr.json/translate?key=${ - process.env.API_YANDEX - }&lang=${ - !initialLang ? resultLang : `${initialLang}-${resultLang}` - }&text=${encodeURI(content)}`, - (err, response, body) => { - if (err) { - ctx.reply("A serious error occured."); - console.error(err); - } else if (response.statusCode === 200) { - const result = JSON.parse(body); - const embed = new Embed(this) - .setTitle( - `Text Translation (${ - !initialLang - ? `to ${resultLang}` - : `from ${initialLang} to ${resultLang}` - })` - ) - .setDescription( - `**Translation Result**\n${ - content === "baguette" && resultLang === "fr" - ? ":french_bread:" - : result.text[0] - }` - ) - .setFooter("Powered by Yandex.Translate"); - ctx.reply(embed); - } else { - ctx.reply( - `An error occured when contacting the Yandex Translate API.\n**Response Status Code**: ${ - response.statusCode - }` - ); - } - } - ); - } -}; diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts new file mode 100755 index 00000000..0ea4de76 --- /dev/null +++ b/src/events/interactionCreate.ts @@ -0,0 +1,14 @@ +import { Interaction } from "discord.js"; +import DiscordSlashMessageContext from "../structures/contexts/DiscordSlashMessageContext.js"; +import AldebaranClient from "../structures/djs/Client"; + +export default async (client: AldebaranClient, interaction: Interaction) => { + if (interaction.isCommand()) { + const author = await client.customUsers.fetch(interaction.user.id); + const guild = interaction.guild + ? await client.customGuilds.fetch(interaction.guild.id) + : undefined; + const ctx = new DiscordSlashMessageContext(client, interaction, author, guild); + ctx.command.execute(ctx, "DISCORD_SLASH"); + } +} \ No newline at end of file diff --git a/src/events/message.ts b/src/events/message.ts old mode 100644 new mode 100755 index c61ff453..6b506baf --- a/src/events/message.ts +++ b/src/events/message.ts @@ -1,7 +1,7 @@ import { Message, MessageEmbed } from "discord.js"; import { IImageCommand } from "../interfaces/Command.js"; import AldebaranClient from "../structures/djs/Client.js"; -import MessageContext from "../structures/aldebaran/MessageContext.js"; +import DiscordMessageContext from "../structures/contexts/DiscordMessageContext.js"; import DiscordRPG from "../utils/bots/DiscordRPG.js"; import DRPGAdventure from "../utils/timer/DiscordRPG/adv.js"; @@ -13,7 +13,7 @@ export default async (client: AldebaranClient, message: Message) => { const guild = message.guild ? await client.customGuilds.fetch(message.guild.id) - : null; + : undefined; let prefix = guild ? process.argv[2] === "dev" @@ -21,20 +21,21 @@ export default async (client: AldebaranClient, message: Message) => { : guild.prefix : ""; - const ctx = new MessageContext(client, message, prefix); + const author = await client.customUsers.fetch(message.author.id); - const user = await ctx.author(); - if (user.banned) return; + const ctx = new DiscordMessageContext(client, message, author, guild); + + if (author.banned) return; const drpgIDs = ["170915625722576896", "891614347015626762"]; - if (guild && drpgIDs.includes(ctx.message.author.id)) { + if (guild && drpgIDs.includes(ctx.author.id)) { DiscordRPG(ctx); - } else if (!user.user.bot) { - const drpgMatch = ctx.message.content.toLowerCase() + } else if (!author.user.bot) { + const drpgMatch = ctx.content.toLowerCase() .match(/.+(?=stats|adv|padv|mine|forage|fish|chop)/); if (drpgMatch) { const filter = (msg: Message) => drpgIDs.includes(msg.author.id); - ctx.message.channel.awaitMessages({ filter, max: 1, time: 2000 }) + ctx.channel.awaitMessages({ filter, max: 1, time: 2000 }) .then(async () => { if (!guild!.settings.discordrpgprefix) { guild!.settings.discordrpgprefix = drpgMatch[0]; @@ -46,38 +47,31 @@ export default async (client: AldebaranClient, message: Message) => { } } - if (user.user.bot) return; + if (author.user.bot) return; if (!message.mentions.users.get(client.user.id)) { - if (ctx.message.content.indexOf(prefix) !== 0) return; - if (ctx.message.content.slice(prefix.length)[0] === " ") return; + if (ctx.content.indexOf(prefix) !== 0) return; + if (ctx.content.slice(prefix.length)[0] === " ") return; } else { - prefix = ctx.message.content.trim().substring(0, ctx.message.content.indexOf(">") + 1); + prefix = ctx.content.trim().substring(0, ctx.content.indexOf(">") + 1); } - const args = ctx.message.content.slice(prefix.length).trim().split(/ +/g); - const command = args.shift()!.toLowerCase(); - - const sliced = command.slice(1); - if (command.indexOf("?") === 0) { - ctx.reply(ctx.client.commands.getHelp(sliced, prefix)); + if (ctx.command && ctx.mode === "HELP") { + ctx.reply(ctx.command.toHelpEmbed(prefix)); /* } else if (command.indexOf("#") === 0) { - ctx.client.commands.bypassRun(sliced, message, prefix).catch(err => { + ctx.client.commands.bypassRun(ctx).catch(err => { if (err.message === "INVALID_COMMAND") return; if (err.message === "UNALLOWED_ADMIN_BYPASS") { const embed = new MessageEmbed() .setTitle("You are not allowed to use this.") .setDescription(`By using \`#\`, you are trying to bypass Discord permissions requirements and other checks, which is only allowed for ${ctx.client.name} Administrators.`) - .setFooter( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) + .setFooter(ctx.author.username, ctx.author.avatarURL) .setColor("RED"); ctx.reply(embed); } else { console.error(err); } }); - } else if (command.indexOf("-") === 0) { + } *//* else if (command.indexOf("-") === 0) { try { const cmd = ctx.client.commands.get(sliced) as IImageCommand; if (cmd && cmd.image) { @@ -91,13 +85,16 @@ export default async (client: AldebaranClient, message: Message) => { .setFooter(message.author.username, message.author.displayAvatarURL()) .setColor("RED"); ctx.reply(embed); - } - } else { - client.commands.execute(command, message, prefix).catch(err => { + } */ + } else if (ctx.command) { + ctx.command.execute(ctx, "DISCORD").then(() => { + const user = `USER: ${message.author.tag} (${message.author.id})`; + console.log(`\x1b[34m- COMMAND: ${ctx.command!.name} | ${user}\x1b[0m`); + }).catch(err => { if (err.message === "INVALID_PERMISSIONS") { const embed = new MessageEmbed() .setTitle("You are not allowed to use this.") - .setDescription(`This command requires permissions that you do not currently have. Please check \`${prefix}?${command}\` for more information about the requirements to use this command.`) + .setDescription(`This command requires permissions that you do not currently have. Please check \`${prefix}?${ctx.command!.name}\` for more information about the requirements to use this command.`) .setFooter(message.author.username, message.author.displayAvatarURL()) .setColor("RED"); ctx.reply(embed); @@ -110,18 +107,11 @@ export default async (client: AldebaranClient, message: Message) => { .setFooter(message.author.username, message.author.displayAvatarURL()) .setColor("RED"); ctx.reply(embed); - } else if (err.message === "INVALID_COMMAND") { - console.log(`Someone unsuccessfully tried ${command}.`); } else if (err.message === "INVALID_ARGS") { - ctx.error("INVALID_ARGS", `Please check \`${prefix}?${command}\` for more information on how to use this command.`) - } else { + ctx.error("INVALID_ARGS", `Please check \`${prefix}?${ctx.command!.name}\` for more information on how to use this command.`) + } else if (err.message !== "INVALID_COMMAND") { console.error(err); } }); } - console.log( - `\x1b[34m- COMMAND: ${command} | USER: ${message.author.tag} (${ - message.author.id - }) | ARGS: ${args.join(" ") || "None"}\x1b[0m` - ); }; diff --git a/src/events/ready.ts b/src/events/ready.ts old mode 100644 new mode 100755 index 8c91e1e7..2686793a --- a/src/events/ready.ts +++ b/src/events/ready.ts @@ -10,7 +10,7 @@ export default (client: AldebaranClient) => { console.log( `\x1b[36m# ${client.users.cache.size} users, ${client.channels.cache.size} channels, ${ client.guilds.cache.size - } servers, ${client.commands.size} commands\x1b[0m` + } servers\x1b[0m` ); const parseText = (value: string) => { diff --git a/src/global.d.ts b/src/global.d.ts old mode 100644 new mode 100755 diff --git a/src/groups/Command.ts b/src/groups/Command.ts old mode 100644 new mode 100755 index 9706dd8e..c268f785 --- a/src/groups/Command.ts +++ b/src/groups/Command.ts @@ -1,8 +1,8 @@ -import { Client, ColorResolvable, MessageEmbed, PermissionString as DJSPermission } from "discord.js"; +import { Client, ColorResolvable, MessageEmbed, PermissionString as DJSPermission, TextChannel } from "discord.js"; import AldebaranClient from "../structures/djs/Client.js"; -import { PermissionString as AldebaranPermission } from "../utils/Constants"; +import { PermissionString as AldebaranPermission, Platform } from "../utils/Constants"; import { CommandMetadata, ICommand } from "../interfaces/Command.js"; -import MessageContext from "../structures/aldebaran/MessageContext.js"; +import MessageContext from "../structures/contexts/MessageContext.js"; export abstract class Command implements ICommand { aliases: string[]; @@ -14,8 +14,7 @@ export abstract class Command implements ICommand { metadata: CommandMetadata; name: string = "dummy"; perms: { discord: DJSPermission[], aldebaran: AldebaranPermission[] }; - subcommands: Map = new Map(); - usage: string; + subcommands: Map = new Map(); /** * Command abstract class, extend it to build a command @@ -39,11 +38,10 @@ export abstract class Command implements ICommand { this.client = client; this.example = !metadata.example ? "" : `\`${metadata.example}\``; this.metadata = metadata; - this.usage = !metadata.usage ? "" : `\`${metadata.usage}\``; } guildCheck(ctx: MessageContext) { - return this.metadata.requiresGuild ? !!ctx.message.guild : true; + return this.metadata.requiresGuild ? !!ctx.guild : true; } /** @@ -53,12 +51,11 @@ export abstract class Command implements ICommand { let check = true; if (this.perms.discord && this.guildCheck(ctx)) { check = this.perms.discord - .every(p => ctx.message.member!.permissionsIn(ctx.channel).has(p)); + .every(p => ctx.member!.permissionsIn(ctx.channel as TextChannel).has(p)); } if (this.perms.aldebaran && check) { - const user = await ctx.author(); check = this.perms.aldebaran - .every(perm => user.hasPermission(perm)); + .every(perm => ctx.author.hasPermission(perm)); } return check; } @@ -70,18 +67,32 @@ export abstract class Command implements ICommand { /** * Executes the specified command */ - async execute(ctx: MessageContext): Promise { + async execute(ctx: MessageContext, platform: Platform): Promise { const guild = this.guildCheck(ctx); if (!guild) throw new Error("NOT_IN_GUILD"); const perms = await this.permsCheck(ctx); if (!perms) throw new Error("MISSING_PERMS"); if (!ctx.argsCheck()) throw new Error("INVALID_ARGS"); - return this.run(ctx); + return this.run(ctx, platform); } - abstract run(ctx: MessageContext): void; + /** + * Whether the string in parameter matches the identity (name, aliases) of this command + */ + matches(name: string) { + return this.name === name || this.aliases.includes(name); + } + + abstract run(ctx: MessageContext, platform: Platform): void; + + /** + * Whether this command supports the platform in parameter + */ + supports(platform: Platform) { + return !this.metadata.platforms || this.metadata.platforms.includes(platform); + } - toHelpEmbed(command: string, prefix = "&") { + toHelpEmbed(prefix = "&") { const embed = new MessageEmbed() .setAuthor( `${this.client.name} | Command Help | ${this.name}`, @@ -89,10 +100,8 @@ export abstract class Command implements ICommand { ) .setTitle(this.metadata.description) .addField("Category", this.category, true) - .addField("Example", `${prefix}${command} ${this.example}`, true) + .addField("Example", `${prefix}${this.name} ${this.example}`, true) .setColor("BLUE"); - if (this.metadata.usage !== undefined) - embed.addField("Usage", `${prefix}${command} ${this.usage}`, true); if (this.metadata.help !== undefined) embed.setDescription(this.metadata.help); if (this.aliases.length > 0) @@ -109,11 +118,15 @@ export abstract class Command implements ICommand { for (const [id, data] of Object.entries(this.metadata.args)) { const begin = `\`${id}\` (${data.as}${data.optional ? ", optional" : ""})`; const t = data.as.includes("?") ? ["[", "]"] : ["<", ">"]; - if (data.flag === undefined) args += `${begin}${data.desc ? ` - *${data.desc}*` : ""}\n`; - else args += `${begin} - \`-${data.flag.short}\`/\`--${data.flag.long}\`${data.desc ? ` - *${data.desc}*` : ""}\n`; - usage += data.flag === undefined ? `${t[0]}${id}${t[1]} ` : `${t[0]}-${data.flag.short}|--${data.flag.long}${data.as !== "boolean" ? ` ${id}` : ""}${t[1]} `; + if ((data.as === "mode" || data.as === "boolean") && data.flag) { + args += `${begin} - \`-${data.flag.short}\`/\`--${data.flag.long}\`${data.desc ? ` - *${data.desc}*` : ""}\n`; + usage += `${t[0]}-${data.flag.short}|--${data.flag.long}${data.as !== "boolean" ? ` ${id}` : ""}${t[1]} `; + } else { + args += `${begin}${data.desc ? ` - *${data.desc}*` : ""}\n`; + usage += `${t[0]}${id}${t[1]} `; + } } - embed.addField("Usage", `${prefix}${command} \`${usage.trim()}\``, true); + embed.addField("Usage", `${prefix}${this.name} \`${usage.trim()}\``, true); embed.addField("Arguments", args); } return embed; diff --git a/src/groups/DRPGCommand.ts b/src/groups/DRPGCommand.ts old mode 100644 new mode 100755 diff --git a/src/groups/DeveloperCommand.ts b/src/groups/DeveloperCommand.ts old mode 100644 new mode 100755 diff --git a/src/groups/FunCommand.ts b/src/groups/FunCommand.ts old mode 100644 new mode 100755 diff --git a/src/groups/GamesCommand.ts b/src/groups/GamesCommand.ts old mode 100644 new mode 100755 diff --git a/src/groups/ImageCommand.ts b/src/groups/ImageCommand.ts old mode 100644 new mode 100755 diff --git a/src/groups/NSFWCommand.ts b/src/groups/NSFWCommand.ts old mode 100644 new mode 100755 index f757ee9f..ea1ef373 --- a/src/groups/NSFWCommand.ts +++ b/src/groups/NSFWCommand.ts @@ -1,6 +1,6 @@ import { TextChannel, ThreadChannel } from "discord.js"; import { CommandMetadata } from "../interfaces/Command.js"; -import MessageContext from "../structures/aldebaran/MessageContext.js"; +import MessageContext from "../structures/contexts/MessageContext.js"; import AldebaranClient from "../structures/djs/Client.js"; import { Command as C, Embed as E } from "./Command.js"; diff --git a/src/groups/OsuCommand.ts b/src/groups/OsuCommand.ts old mode 100644 new mode 100755 diff --git a/src/groups/SettingsCommand.ts b/src/groups/SettingsCommand.ts old mode 100644 new mode 100755 diff --git a/src/groups/SocialCommand.ts b/src/groups/SocialCommand.ts old mode 100644 new mode 100755 index 69656efa..9712a1f6 --- a/src/groups/SocialCommand.ts +++ b/src/groups/SocialCommand.ts @@ -5,7 +5,10 @@ import { Command as C, Embed as E } from "./Command.js"; export abstract class Command extends C { constructor(client: AldebaranClient, metadata: CommandMetadata) { super(client, { - args: { user: { as: "user" } }, + args: { user: { + as: "user", + desc: "The user you want to annoy with random memes" + } }, ...metadata }); this.category = "Action"; diff --git a/src/groups/UtilitiesCommand.ts b/src/groups/UtilitiesCommand.ts old mode 100644 new mode 100755 diff --git a/src/groups/multi/NekoslifeSubcategory.ts b/src/groups/multi/NekoslifeSubcategory.ts old mode 100644 new mode 100755 index 06bbe292..ff0723a3 --- a/src/groups/multi/NekoslifeSubcategory.ts +++ b/src/groups/multi/NekoslifeSubcategory.ts @@ -1,6 +1,6 @@ import { MessageEmbed } from "discord.js"; import { Command } from "../Command.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; export default (cmd: typeof Command, embed: typeof MessageEmbed) => { class Embed extends embed { diff --git a/src/handlers/CommandHandler.ts b/src/handlers/CommandHandler.ts old mode 100644 new mode 100755 index 81a6dd65..411e72af --- a/src/handlers/CommandHandler.ts +++ b/src/handlers/CommandHandler.ts @@ -1,13 +1,14 @@ -import { Message } from "discord.js"; import AldebaranClient from "../structures/djs/Client.js"; import { Command } from "../groups/Command.js"; -import MessageContext from "../structures/aldebaran/MessageContext.js"; -import { ICommand } from "../interfaces/Command.js"; +import { SlashCommandBuilder } from "@discordjs/builders"; +import { Arg } from "../utils/Args.js"; +import { Platform, SlashCommandOption as Option } from "../utils/Constants.js"; export default class CommandHandler { private static instance: CommandHandler; client: AldebaranClient; - commands: Map = new Map(); + commands: Command[] = []; + slashCommands: SlashCommandBuilder[] = []; private constructor(client: AldebaranClient) { this.client = client; @@ -22,70 +23,30 @@ export default class CommandHandler { return CommandHandler.instance; } - async execute(name: string, message: Message, prefix: string) { - if (message.guild) { - const guild = await this.client.customGuilds.fetch(message.guild.id); - } - if (!this.exists(name)) throw new TypeError("INVALID_COMMAND"); - const command = this.get(name)!; - const cArgs = command.metadata.args; - const ctx = new MessageContext(this.client, message, prefix, cArgs); - const args = ctx.getSplitArgs(); - if (args.length === 0) { - if (command.subcommands.size > 0) { - if (command.metadata.allowIndexCommand) { - return command.execute(ctx); - } else { - throw new TypeError("INVALID_COMMAND"); - } - } else { - return command.execute(ctx); - } - } else if (command.subcommands.size > 0) { - const subcommand = args.shift()!; - if (command.subcommands.get(subcommand)) { - ctx.setLevel(2); - return command.subcommands.get(subcommand)!.execute(ctx); - } else if (command.metadata.allowUnknownSubcommands) { - return command.execute(ctx); - } else { - throw new TypeError("INVALID_COMMAND"); - } - } else { - return command.execute(ctx); - } - } - - get size() { - let size = 0; - for (const [name, data] of this.commands) - if (name === data.name) size++; - return size; - } - - get(command: string) { - return this.commands.get(command); + get(command: string, platform: Platform) { + return this.commands.find(c => c.matches(command) && c.supports(platform)); } - async bypassRun(name: string, message: Message, prefix: string) { - if (!this.exists(name)) throw new TypeError("INVALID_COMMAND"); - const command = this.commands.get(name)!; - const { args } = command.metadata; - const ctx = new MessageContext(this.client, message, prefix, args); - const user = await this.client.customUsers.fetch(ctx.message.author.id); + /* async bypassRun(ctx: MessageContext) { + const user = await this.client.customUsers.fetch(ctx.author.id); if (!user.hasPermission("ADMINISTRATOR")) { throw new Error("UNALLOWED_ADMIN_BYPASS"); } - return command.execute(ctx); - } + return ctx.command.execute(ctx); + } */ - exists(command: string) { - return !!this.commands.get(command); + exists(command: string, platform: Platform) { + return !!this.get(command, platform); } - getHelp(command: string, prefix = "&") { - if (!this.exists(command)) throw new TypeError("INVALID_COMMAND"); - return this.commands.get(command)!.toHelpEmbed(command, prefix); + static patchOption(option: T, name: string, metadata: Arg) { + try { + return option.setName(name.toLowerCase()) + .setDescription(metadata.desc) + .setRequired(!metadata.optional || false) as T; + } catch (err) { + throw new TypeError(`There is an issue with the '${name}' command.\n${err}`); + } } register(...structures: (typeof Command)[]) { @@ -93,10 +54,41 @@ export default class CommandHandler { const command: Command = new (Structure as any)(this.client); command.name = command.metadata.name || command.constructor.name.slice(0, -7).toLowerCase(); - this.commands.set(command.name, command); - command.aliases.forEach(alias => { - this.commands.set(alias, command); - }); + this.commands.push(command); + + if (process.env.DEPLOY_SLASH && command.supports("DISCORD_SLASH")) { + const slash = new SlashCommandBuilder() + .setName(command.name) + .setDescription(command.metadata.description); + + if (command.metadata.args) { + for (const [name, meta] of Object.entries(command.metadata.args)) { + if (meta.as === "boolean") { + slash.addBooleanOption(o => CommandHandler.patchOption(o, name, meta)); + } else if (meta.as === "user") { + slash.addUserOption(o => CommandHandler.patchOption(o, name, meta)); + } else if (meta.as === "mode") { + slash.addStringOption(o => CommandHandler.patchOption(o, name, meta) + .setChoices(meta.choices)); + } else if (meta.as === "string" || meta.as === "expression") { + slash.addStringOption(o => CommandHandler.patchOption(o, name, meta)); + } else if (meta.as === "number") { + slash.addIntegerOption(o => CommandHandler.patchOption(o, name, meta)); + } + } + } + + for (const [name, subcommand] of command.subcommands) { + if (subcommand.supports("DISCORD_SLASH")) { + slash.addSubcommand(sub => sub + .setName(name) + .setDescription(subcommand.metadata.description) + ); + } + } + + this.slashCommands.push(slash); + } }, this); } }; diff --git a/src/handlers/DatabaseProvider.ts b/src/handlers/DatabaseProvider.ts old mode 100644 new mode 100755 diff --git a/src/handlers/GenericDatabaseProvider.ts b/src/handlers/GenericDatabaseProvider.ts old mode 100644 new mode 100755 diff --git a/src/interfaces/Arg.ts b/src/interfaces/Arg.ts deleted file mode 100644 index d192ddd4..00000000 --- a/src/interfaces/Arg.ts +++ /dev/null @@ -1,14 +0,0 @@ -export interface Arg { - as: "boolean" | "expression" | "mode" | "number" | "user" | "word", - desc?: string, - flag?: { - short?: string, - long?: string - }, - optional?: boolean, - regex?: RegExp -} - -export interface Args { - [key: string]: Arg; -} diff --git a/src/interfaces/Command.ts b/src/interfaces/Command.ts old mode 100644 new mode 100755 index 9763c798..e3ee5b66 --- a/src/interfaces/Command.ts +++ b/src/interfaces/Command.ts @@ -1,13 +1,14 @@ import { ColorResolvable, MessageEmbed, PermissionString as DJSPermission } from "discord.js"; import { Command } from "../groups/Command"; -import MessageContext from "../structures/aldebaran/MessageContext"; +import DiscordMessageContext from "../structures/contexts/DiscordMessageContext.js"; +import DiscordSlashMessageContext from "../structures/contexts/DiscordSlashMessageContext.js"; +import MessageContext from "../structures/contexts/MessageContext.js"; import Client from "../structures/djs/Client"; -import { PermissionString as AldebaranPermission } from "../utils/Constants"; -import { Args } from "./Arg.js"; +import { Args } from "../utils/Args"; +import { PermissionString as AldebaranPermission, Platform } from "../utils/Constants"; export interface CommandMetadata { aliases?: string[], - allowIndexCommand?: boolean, allowUnknownSubcommands?: boolean, args?: Args, cooldown?: { @@ -23,8 +24,8 @@ export interface CommandMetadata { discord?: DJSPermission[], aldebaran?: AldebaranPermission[] }, - requiresGuild?: boolean, - usage?: string, + platforms?: Platform[], + requiresGuild?: boolean }; export interface ICommand { @@ -38,14 +39,16 @@ export interface ICommand { name: string; perms: { discord: DJSPermission[], aldebaran: AldebaranPermission[] }; subcommands: Map; - usage: string; check(ctx: MessageContext): Promise; - execute(ctx: MessageContext): object | void; + execute(ctx: MessageContext, platform: Platform): object | void; guildCheck(ctx: MessageContext): boolean; permsCheck(ctx: MessageContext): Promise; registerSubcommands(...subcommands: T[]): void; - run(ctx: MessageContext): void; + run( + ctx: MessageContext | DiscordMessageContext | DiscordSlashMessageContext, + platform: Platform + ): void; toHelpEmbed(command: string, prefix: string): MessageEmbed; }; diff --git a/src/interfaces/DiscordRPG.ts b/src/interfaces/DiscordRPG.ts old mode 100644 new mode 100755 diff --git a/src/structures/aldebaran/AldebaranPermissions.ts b/src/structures/aldebaran/AldebaranPermissions.ts old mode 100644 new mode 100755 diff --git a/src/structures/aldebaran/CustomGuildManager.ts b/src/structures/aldebaran/CustomGuildManager.ts old mode 100644 new mode 100755 diff --git a/src/structures/aldebaran/CustomProfileManager.ts b/src/structures/aldebaran/CustomProfileManager.ts old mode 100644 new mode 100755 diff --git a/src/structures/aldebaran/CustomUserManager.ts b/src/structures/aldebaran/CustomUserManager.ts old mode 100644 new mode 100755 diff --git a/src/structures/aldebaran/MessageContext.ts b/src/structures/aldebaran/MessageContext.ts deleted file mode 100644 index 1480a90e..00000000 --- a/src/structures/aldebaran/MessageContext.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { Message as DMessage, MessageEmbed as MEmbed, MessageOptions as MOptions, MessagePayload as MPayload, TextChannel, ThreadChannel } from "discord.js"; -import { ErrorString, Errors } from "../../utils/Constants.js"; -import { Args } from "../../interfaces/Arg.js"; -import Client from "../djs/Client.js"; -import Guild from "../djs/Guild.js"; -import User from "../djs/User.js"; - -const checkType = (element: string) => { - if (element.match(/\d{17,19}/g)) return "user"; - if (element.match(/([-]{1,2}[\w]+)/g)) return "flag"; - if (!Number.isNaN(Number(element))) return "number"; - return "word"; -}; - -export default class MessageContext { - private _argsMetadata?: Args; - private _author?: User; - private _guild?: Guild; - private _args?: string[] | { [key: string]: string | boolean; }; - client: Client; - level: number = 0; // 0 if command, 1 if subcommand, 2 if subsubcommand, etc. - message: DMessage; - prefix: string; - - constructor(client: Client, message: DMessage, prefix: string, args?: Args) { - this._argsMetadata = args; - this.client = client; - this.message = message; - this.prefix = prefix; - } - - get args() { - if (!this._args) { - this._args = this.getArgs(); - } - return this._args; - } - - argsCheck() { - if (this._argsMetadata) { - const mandatory = Object.keys(this._argsMetadata) - .filter(k => !this._argsMetadata![k].optional); - const mandatoryFound = Object.keys(this.args).filter(k => mandatory.includes(k)); - return mandatory.length === mandatoryFound.length; - } - return true; - } - - async author() { - if (!this._author) { - this._author = await this.client.customUsers - .fetch(this.message.author.id); - } - return this._author; - } - - get command() { - return this.message.content - .slice(this.prefix.length + +(this.mode !== "NORMAL")) - .split(" ")[0]; - } - - async guild() { - if (this.message.guild) { - if (!this._guild) { - this._guild = await this.client.customGuilds - .fetch(this.message.guild.id); - } - return this._guild; - } - return null; - } - - // the shift parameter should be 1 when a subcommand is used, 2 when a subsubcommand is used (which is sadly not supported), etc. - getSplitArgs() { - const split = this.message.content - .slice(this.prefix.length + this.command.length) - .split(" "); - for (let i = 0; i < this.level + 1; i++) { - split.shift(); - } - return split; - } - - getArgs() { - const split = this.getSplitArgs(); - if (this._argsMetadata) { - const deconstructed = []; // All arguments and their type - for (let i = 0; i < split.length; i++) { - const type = checkType(split[i]); - if (type === "user") { - deconstructed.push({ user: split[i].match(/\d{17,19}/g)![0] }); - } else if (type === "number") { - deconstructed.push({ number: Number(split[i]) }); - } else if (type === "flag") { - deconstructed.push({ - flag: { - id: split[i].replace(/-/g, ""), - pv: split[i + 1] - } - }); - } else if (type === "word") { - deconstructed.push({ word: split[i] }); - } - } - const args: { [key: string]: string | boolean } = { }; - for (const element of deconstructed) { - const [[type, value]] = Object.entries(element); - let result = null; - for (const [arg, data] of Object.entries(this._argsMetadata)) { - if (result) break; - if (args[arg] === undefined) { - if (data.as === type && data.flag === undefined) { - result = { arg, value }; - } else if (type === "flag" && data.flag) { - if ([data.flag.short, data.flag.long].includes(value.id)) { - if (data.as === "boolean") { - result = { arg, value: true }; - } else if (value.pv !== undefined) { - if (checkType(value.pv) === data.as) { - result = { arg, value: value.pv }; - } - } - } - } else if (type === "flag" && data.as === "mode") { - result = { arg, value: value.id }; - } else if (type !== "flag" && data.as === "expression") { - const match = String(value).match(data.regex!); - if (match) { - result = { arg, value: match[0] }; - } - } - } - } - if (result) { - args[result.arg] = result.value; - } - } - return args; - } - return split; - } - - get mode() { - if (this.message.content.indexOf(`${this.prefix}#`) === 0) return "ADMIN"; - if (this.message.content.indexOf(`${this.prefix}?`) === 0) return "HELP"; - if (this.message.content.indexOf(`${this.prefix}-`) === 0) return "IMAGE"; - return "NORMAL"; - } - - setLevel(level: number) { - this.level = level; - this._args = undefined; - } - - async error(type: ErrorString, desc?: string, value?: string) { - const title = Errors[type] !== undefined ? Errors[type](value!) : "An error has occured."; - const embed = new MEmbed() - .setTitle(title) - .setColor("RED"); - if (type === "UNEXPECTED_BEHAVIOR") { - embed.setDescription(`${desc}\nPlease contact the developers or fill a bug report with \`${this.prefix}bugreport\`.`); - } else if (type === "INVALID_USER") { - embed.setDescription("The user ID you have supplied is invalid, or the user you have mentionned does not exist. Make sure your user ID or your mention is correct."); - } else if (desc) { - embed.setDescription(desc); - } - return this.reply(embed); - } - - async reply(content: string | MPayload | MOptions | MEmbed) { - if (content instanceof MEmbed) { - return this.message.channel.send({ embeds: [content] }); - } - return this.message.channel.send(content); - } - - get channel() { - return this.message.channel as TextChannel | ThreadChannel; - } -}; diff --git a/src/structures/aldebaran/SocialProfile.ts b/src/structures/aldebaran/SocialProfile.ts old mode 100644 new mode 100755 diff --git a/src/structures/contexts/DiscordMessageContext.ts b/src/structures/contexts/DiscordMessageContext.ts new file mode 100755 index 00000000..7fcfd33b --- /dev/null +++ b/src/structures/contexts/DiscordMessageContext.ts @@ -0,0 +1,94 @@ +import { Message, MessageEmbed, MessageOptions, TextChannel } from "discord.js"; +import MessageContext from "./MessageContext.js" +import Guild from "../djs/Guild.js"; +import User from "../djs/User.js"; +import { parseArgs, parseInput } from "../../utils/Args.js"; +import Client from "../djs/Client.js"; +import { Command } from "../../groups/Command.js"; + +export default class DiscordMessageContext extends MessageContext { + private _splitArgs: string[]; + private message: Message; + public command?: Command; + public author: User; + public guild?: Guild; + + constructor(client: Client, message: Message, author: User, guild?: Guild) { + super(client); + this.author = author; + this.guild = guild; + this.message = message; + + const parsedInput = parseInput( + client, + this.content, + this.mode, + this.prefix, + "DISCORD" + ); + this.command = parsedInput.command; + this._splitArgs = parsedInput.args; + } + + get args() { + if (!this._args) { + const meta = this.command?.metadata.args; + this._args = meta ? parseArgs(this._splitArgs, meta) : this._splitArgs; + } + return this._args; + } + + get channel() { + return this.message.channel; + } + + get content() { + return this.message.content; + } + + get createdTimestamp() { + return this.message.createdTimestamp; + } + + get member() { + return this.message.member; + } + + get mentions() { + return this.message.mentions; + } + + get mode() { + if (this.message.content.indexOf(`${this.prefix}#`) === 0) return "ADMIN"; + if (this.message.content.indexOf(`${this.prefix}?`) === 0) return "HELP"; + if (this.message.content.indexOf(`${this.prefix}-`) === 0) return "IMAGE"; + return "NORMAL"; + } + + get prefix() { + return this.guild?.prefix ?? ""; + } + + async delete(delay?: number): Promise | false> { + const hasPermission = this.guild && (this.channel as TextChannel) + .permissionsFor(this.client.user.id)?.has("MANAGE_MESSAGES"); + + if (hasPermission) { + if (delay) { + return new Promise(resolve => { + setTimeout(() => { + resolve(this.message.delete()); + }, delay); + }); + } + return this.message.delete(); + } + return false; + } + + async reply(content: string | MessageOptions | MessageEmbed) { + return content instanceof MessageEmbed + ? this.message.channel.send({ embeds: [content] }) + : this.message.channel.send(content); + } +} diff --git a/src/structures/contexts/DiscordSlashMessageContext.ts b/src/structures/contexts/DiscordSlashMessageContext.ts new file mode 100755 index 00000000..4e41a336 --- /dev/null +++ b/src/structures/contexts/DiscordSlashMessageContext.ts @@ -0,0 +1,103 @@ +import { MessageOptions, MessageEmbed, CommandInteraction, GuildMember, Message } from "discord.js"; +import { Command } from "../../groups/Command"; +import { CommandMode } from "../../utils/Constants"; +import Client from "../djs/Client"; +import Guild from "../djs/Guild"; +import User from "../djs/User"; +import MessageContext from "./MessageContext.js"; + +type M = Promise>; + +export default class DiscordSlashMessageContext extends MessageContext { + private interaction: CommandInteraction; + public author: User; + public command: Command; + public guild?: Guild; + + constructor(client: Client, interaction: CommandInteraction, author: User, guild?: Guild) { + super(client); + this.author = author; + this.guild = guild; + this.interaction = interaction; + + const subcommand = interaction.options.getSubcommand(false); + if (subcommand) { + this.command = client.commands.get(interaction.commandName, "DISCORD_SLASH")! + .subcommands.get(subcommand)!; + } else { + this.command = client.commands.get(interaction.commandName, "DISCORD_SLASH")!; + } + } + + get args() { + const args: { [key: string]: string | number | boolean | undefined } = {}; + if (this.command.metadata.args) { + Object.keys(this.command.metadata.args).forEach(k => { + args[k] = this.interaction.options.get(k)?.value; + }); + } + return args; + } + + get channel() { + return this.interaction.channel!; + } + + get createdTimestamp() { + return this.interaction.createdTimestamp; + } + + get member() { + return this.interaction.inGuild() + ? this.interaction.member as GuildMember + : null; + } + + get mode(): CommandMode { + return "NORMAL"; + } + + get prefix() { + return "/"; + } + + async delete(): Promise { + return false; + } + + async followUp( + content: string | MessageOptions | MessageEmbed, + ephemeral: boolean = false, + fetchReply: boolean = false + ) { + if (content instanceof MessageEmbed) { + return this.interaction + .followUp({ embeds: [content], ephemeral, fetchReply }) as M; + } else if (typeof content === "string") { + return this.interaction.followUp({ content, fetchReply }) as M; + } else { + return this.interaction.followUp({ ...content, fetchReply }) as M; + } + } + + async reply(content: string | MessageOptions | MessageEmbed): Promise; + async reply( + content: string | MessageOptions | MessageEmbed, + ephemeral?: boolean, + fetchReply?: B + ): Promise : void>; + + async reply( + content: string | MessageOptions | MessageEmbed, + ephemeral: boolean = false, + fetchReply: boolean = false + ) { + if (content instanceof MessageEmbed) { + return this.interaction.reply({ embeds: [content], ephemeral, fetchReply }); + } else if (typeof content === "string") { + return this.interaction.reply({ content, ephemeral, fetchReply }); + } else { + return this.interaction.reply({ ...content, ephemeral, fetchReply }); + } + } +} diff --git a/src/structures/contexts/MessageContext.ts b/src/structures/contexts/MessageContext.ts new file mode 100755 index 00000000..f588e533 --- /dev/null +++ b/src/structures/contexts/MessageContext.ts @@ -0,0 +1,54 @@ +import { GuildMember, Message, MessageEmbed, MessageOptions, TextBasedChannel } from "discord.js"; +import { ErrorString, Errors, CommandMode } from "../../utils/Constants.js"; +import Client from "../djs/Client.js"; +import { Command } from "../../groups/Command.js"; +import User from "../djs/User.js"; +import Guild from "../djs/Guild.js"; + +export default abstract class MessageContext { + protected _args?: string[] | { [key: string]: string | boolean; }; + public abstract author: User; + public client: Client; + public abstract command?: Command; + public abstract guild?: Guild; + + constructor(client: Client) { + this.client = client; + } + + abstract get args(): string[] | { [key: string]: string | number | boolean | undefined; }; + abstract get channel(): TextBasedChannel; + abstract get createdTimestamp(): number; + abstract get member(): GuildMember | null; + abstract get mode(): CommandMode; + abstract get prefix(): string; + + abstract delete(delay?: number): Promise | false>; + + argsCheck() { + if (this.command && this.command.metadata.args) { + const mandatory = Object.keys(this.command.metadata.args) + .filter(k => !this.command!.metadata.args![k].optional); + const mandatoryFound = Object.keys(this.args).filter(k => mandatory.includes(k)); + return mandatory.length === mandatoryFound.length; + } + return true; + } + + async error(type: ErrorString, desc?: string, value?: string) { + const title = Errors[type] ? Errors[type](value!) : "An error has occured."; + const embed = new MessageEmbed() + .setTitle(title) + .setColor("RED"); + if (type === "UNEXPECTED_BEHAVIOR") { + embed.setDescription(`${desc}\nPlease contact the developers or fill a bug report using the \`bugreport\` command.`); + } else if (type === "INVALID_USER") { + embed.setDescription("The user ID you have supplied is invalid, or the user you have mentionned does not exist. Make sure your user ID or your mention is correct."); + } else if (desc) { + embed.setDescription(desc); + } + return this.reply(embed); + } + + abstract reply(content: string | MessageOptions | MessageEmbed): any; +}; diff --git a/src/structures/djs/Client.ts b/src/structures/djs/Client.ts old mode 100644 new mode 100755 index 09b3200b..67fa7bd2 --- a/src/structures/djs/Client.ts +++ b/src/structures/djs/Client.ts @@ -1,10 +1,13 @@ import { Client } from "discord.js"; +import { REST } from "@discordjs/rest"; +import { Routes, Snowflake } from "discord-api-types/v9"; import fs from "fs"; import NekosClient from "nekos.life"; import { Client as NodesuClient } from "nodesu"; import CommandHandler from "../../handlers/CommandHandler.js"; import importCommands from "../../commands/commands.js"; import DatabaseProvider from "../../handlers/DatabaseProvider.js"; +import interactionCreate from "../../events/interactionCreate.js"; import message from "../../events/message.js"; import ready from "../../events/ready.js"; import { aldebaranTeam, packageFile, presences, SettingsModel } from "../../utils/Constants.js"; @@ -23,6 +26,7 @@ export default class AldebaranClient extends Client { drpgCache: { [key: string]: User | Guild } = {}; database = new DatabaseProvider(this); databaseData = { profiles: new Map() }; + id: Snowflake = process.env.DISCORD_CLIENT_ID!; models = { settings: SettingsModel }; name = process.env.NAME || "Aldebaran"; nekoslife = new NekosClient(); @@ -58,9 +62,18 @@ export default class AldebaranClient extends Client { this.drpgCache = JSON.parse(fs.readFileSync("./cache/drpgCache.json").toString()); } + this.on("interactionCreate", int => interactionCreate(this, int)); this.on("messageCreate", msg => message(this, msg)); this.on("ready", () => ready(this)); + if (process.env.DEPLOY_SLASH) { + const rest = new REST({ version: '9' }).setToken(process.env.TOKEN!); + const body = this.commands.slashCommands.map(c => c.toJSON()); + rest.put(Routes.applicationCommands(this.id), { body }) + .then(() => console.log("Slash commands registered")) + .catch(console.error); + } + this.login(process.env.TOKEN).then(() => { console.log(`\x1b[36m# Everything was started, took ${Date.now() - this.started}ms.\x1b[0m`); }); diff --git a/src/structures/djs/Guild.ts b/src/structures/djs/Guild.ts old mode 100644 new mode 100755 diff --git a/src/structures/djs/User.ts b/src/structures/djs/User.ts old mode 100644 new mode 100755 index 9e6f73c9..b2bfc2da --- a/src/structures/djs/User.ts +++ b/src/structures/djs/User.ts @@ -31,6 +31,10 @@ export default class User { this.username = user.username; } + get avatarURL() { + return this.user.displayAvatarURL(); + } + get banned() { return this.timeout > Date.now(); } diff --git a/src/utils/Args.ts b/src/utils/Args.ts new file mode 100755 index 00000000..283e42a9 --- /dev/null +++ b/src/utils/Args.ts @@ -0,0 +1,155 @@ +import AldebaranClient from "../structures/djs/Client"; +import { CommandMode, Platform } from "./Constants"; + +type DefaultArg = { + desc: string, + optional?: boolean +} + +type Flag = { + long: string, + short: string +}; + +export type BooleanArg = DefaultArg & { + as: "boolean", + flag: Flag +} + +export type ExpressionArg = DefaultArg & { + as: "expression", + regex: RegExp +} + +export type ModeArg = DefaultArg & { + as: "mode", + choices: [string, string][], + flag?: Flag +} + +export type NumberArg = DefaultArg & { as: "number" }; +export type StringArg = DefaultArg & { as: "string" }; +export type UserArg = DefaultArg & { as: "user" }; + +export type Arg = BooleanArg | ExpressionArg | ModeArg | NumberArg | StringArg | UserArg; +export type Args = { [key: string]: Arg } + +export function checkArgType(element: string) { + if (element.match(/\d{17,19}/g)) return "user"; + if (element.match(/([-]{1,2}[\w]+)/g)) return "flag"; + if (!Number.isNaN(Number(element))) return "number"; + return "string"; +}; + +/** + * Parses the message content to filter the args from the command/subcommand name. + * @param input The message content + * @param prefix The prefix used in the input + * @param command The name of the requsted command + * @param level 1 when a subcommand is used, 2 when a subsubcommand is used (which is sadly not supported), etc. + * @returns The args, in an array + */ +export function getSplitArgs(input: string, prefix: string, command: string, level: number) { + const split = input.slice(prefix.length + command.length).split(" "); + for (let i = 0; i < level + 1; i++) { + split.shift(); + } + return split; +} + +export function parseArgs(split: string[], argsMetadata: Args) { + if (Object.keys(argsMetadata).length === 1 + && Object.values(argsMetadata)[0].as === "string") { + return { [Object.keys(argsMetadata)[0]]: split.join(" ") }; + } + const deconstructed = []; // All arguments and their type + for (let i = 0; i < split.length; i++) { + // if the argument is between double quotes, then concatenate what needs to be concatenated + if (split[i].startsWith("\"")) { + let chain = `${split[i].slice(1)} `; + i++; + while (chain) { + if (split[i].includes("\"")) { + chain += split[i].substr(0, split[i].indexOf("\"")); + deconstructed.push({ string: chain }); + chain = ""; + + // if the user forgot a space like in `&plantcalc "Olive Seed"2 25`, don't forget 2 + const rest = split[i].substr(split[i].indexOf("\"")); + if (rest) { + split[i] = rest; + } + } else { + i++; + chain += `${split[i]} `; + } + } + } + const type = checkArgType(split[i]); + if (type === "user") { + deconstructed.push({ user: split[i].match(/\d{17,19}/g)![0] }); + } else if (type === "number") { + deconstructed.push({ number: Number(split[i]) }); + } else if (type === "flag") { + deconstructed.push({ + flag: { + id: split[i].replace(/-/g, ""), + pv: split[i + 1] + } + }); + } else if (type === "string") { + deconstructed.push({ string: split[i] }); + } + } + const args: { [key: string]: string | boolean } = { }; + for (const element of deconstructed) { + const [[type, value]]: [string, any][] = Object.entries(element); + let result = null; + for (const [arg, data] of Object.entries(argsMetadata)) { + if (result) break; + if (args[arg] === undefined) { + if (data.as === type && !(data.as === "mode" || data.as === "boolean")) { + result = { arg, value }; + } else if (type === "flag" && (data.as === "mode" || data.as === "boolean") && data.flag) { + if ([data.flag.short, data.flag.long].includes(value.id)) { + if (data.as === "boolean") { + result = { arg, value: true }; + } + } + } else if (type === "flag" && data.as === "mode") { + result = { arg, value: value.id }; + } else if (type !== "flag" && data.as === "expression") { + const match = String(value).match(data.regex!); + if (match) { + result = { arg, value: match[0] }; + } + } + } + } + if (result) { + args[result.arg] = result.value; + } + } + return args; +} + +/** + * Parses the message content into the requested command and its arguments. + */ +export function parseInput( + client: AldebaranClient, + content: string, + mode: CommandMode, + prefix: string, + platform: Platform +) { + const split = content.slice(prefix.length + +(mode !== "NORMAL")).split(" "); + let command = client.commands.get(split.shift() || "", platform); + + if (command) { + while (command!.subcommands.get(split[0])) { + command = command!.subcommands.get(split.shift() || ""); + } + } + return { command, args: split }; +} diff --git a/src/utils/Constants.ts b/src/utils/Constants.ts old mode 100644 new mode 100755 index 61c06b13..f047d677 --- a/src/utils/Constants.ts +++ b/src/utils/Constants.ts @@ -2,6 +2,7 @@ import { Guild, Snowflake, User } from "discord.js"; import { importAssets, timezoneSupport } from "./Methods.js"; import { DRPGXPBases, DRPGItemList, DRPGLocationDB } from "../interfaces/DiscordRPG.js"; import { Mode } from "nodesu"; +import { SlashCommandBooleanOption, SlashCommandIntegerOption, SlashCommandStringOption, SlashCommandUserOption } from "@discordjs/builders"; type AldebaranTeam = { [key: string]: { titles: string[], @@ -210,6 +211,9 @@ export const Permissions = { DEVELOPER: 2048 }; +export type CommandMode = "ADMIN" | "HELP" | "IMAGE" | "NORMAL"; +export type Platform = "DISCORD" | "DISCORD_SLASH"; +export type SlashCommandOption = SlashCommandBooleanOption | SlashCommandIntegerOption | SlashCommandStringOption | SlashCommandUserOption; export type SocialProfileProperty = "aboutMe" | "dmFriendly" | "age" | "gender" | "name" | "country" | "timezone" | "birthday" | "profilePictureLink" | "favoriteGames" | "profileColor" | "favoriteMusic" | "socialLinks" | "zodiacName" | "flavorText"; export type DBUser = { diff --git a/src/utils/Methods.ts b/src/utils/Methods.ts old mode 100644 new mode 100755 index ac577c3d..08932366 --- a/src/utils/Methods.ts +++ b/src/utils/Methods.ts @@ -1,7 +1,8 @@ -import { MessageActionRow, MessageButton, MessageEmbed } from "discord.js"; +import { Message, MessageActionRow, MessageButton, MessageEmbed } from "discord.js"; import { readFileSync } from "fs"; import moment from "moment-timezone"; -import MessageContext from "../structures/aldebaran/MessageContext"; +import DiscordMessageContext from "../structures/contexts/DiscordMessageContext.js"; +import DiscordSlashMessageContext from "../structures/contexts/DiscordSlashMessageContext.js"; const timeNames = moment.tz.names(); @@ -90,7 +91,7 @@ export async function paginate( list: string[], pageSize: number, headerText: string, - ctx: MessageContext, + ctx: DiscordMessageContext | DiscordSlashMessageContext, codeblock?: string, embed: MessageEmbed = new MessageEmbed() ) { @@ -118,18 +119,20 @@ export async function paginate( } updateEmbed(); - const msg = await ctx.message.channel - .send({ embeds: [embed], components: maxPage > 1 ? [buttonRow] : [] }); + const opt = { embeds: [embed], components: maxPage > 1 ? [buttonRow] : [] }; + const reply = ctx instanceof DiscordSlashMessageContext + ? await ctx.reply(opt, false, true) + : await ctx.reply(opt); // Keep collecting interactions as long as there's pages to paginate. while (maxPage > 1) { - const interaction = await msg.awaitMessageComponent({ - filter: i => i.user.id === ctx.message.author.id ? true : !i.deferUpdate(), + const interaction = await reply.awaitMessageComponent({ + filter: i => i.user.id === ctx.author.id ? true : !i.deferUpdate(), time: 60000 }).catch(() => {}); if (!interaction || interaction.customId === "❌") { - msg.edit({ components: [] }); + reply.edit({ components: [] }); break; } diff --git a/src/utils/bots/DiscordRPG.ts b/src/utils/bots/DiscordRPG.ts old mode 100644 new mode 100755 index 99d186cf..cb6cb4e6 --- a/src/utils/bots/DiscordRPG.ts +++ b/src/utils/bots/DiscordRPG.ts @@ -1,5 +1,5 @@ import { MessageEmbed } from "discord.js"; -import MessageContext from "../../structures/aldebaran/MessageContext.js"; +import MessageContext from "../../structures/contexts/MessageContext.js"; import { imageUrls } from "../../utils/Constants.js"; import User from "../../structures/djs/User.js"; @@ -108,7 +108,7 @@ async function percentageCheck( export default async (ctx: MessageContext) => { if (!ctx.message.guild) return false; - const guild = (await ctx.guild())!; + const guild = (await ctx.fetchGuild())!; if (guild.settings.healthmonitor === "off") return false; const player = { currentHP: 0, diff --git a/src/utils/executeSocial.ts b/src/utils/executeSocial.ts old mode 100644 new mode 100755 index 61eb4334..0634c144 --- a/src/utils/executeSocial.ts +++ b/src/utils/executeSocial.ts @@ -1,18 +1,18 @@ import { Embed } from "../groups/SocialCommand.js"; -import MessageContext from "../structures/aldebaran/MessageContext.js"; -import { actionText, imageUrls } from "./Constants.js"; +import DiscordMessageContext from "../structures/contexts/DiscordMessageContext.js"; +import { actionText, imageUrls, Platform } from "./Constants.js"; -export default async (ctx: MessageContext) => { +export default async (ctx: DiscordMessageContext, platform: Platform) => { const args = ctx.args as { user: string }; - const user = args.user || ctx.message.author.id; + const user = args.user || ctx.author.id; ctx.client.users.fetch(user).then(() => { - const [command] = ctx.message.content.slice(ctx.prefix.length).split(" "); + const [command] = ctx.content.slice(ctx.prefix.length).split(" "); const target = `<@${user}>`; - const sender = ctx.message.author.username; + const sender = ctx.author.username; let comment = ""; let randNumber = null; - if (ctx.message.author.id === user) { + if (ctx.author.id === user) { randNumber = Math.floor(Math.random() * actionText[`${command}`].self.length); comment = actionText[`${command}`].self[randNumber].replace("{target}", target); } else { @@ -23,11 +23,8 @@ export default async (ctx: MessageContext) => { const number = Math.floor(Math.random() * imageUrls[command].length); const image = imageUrls[command][number]; - const embed = new Embed(ctx.client.commands.get(command)!) - .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() - ) + const embed = new Embed(ctx.client.commands.get(command, platform)!) + .setAuthor(ctx.author.username, ctx.author.avatarURL) .setDescription(comment) .setImage(image); ctx.reply(embed); diff --git a/src/utils/osu!/ppv2Results.ts b/src/utils/osu!/ppv2Results.ts old mode 100644 new mode 100755 diff --git a/src/utils/osu!/retrieveBeatmapFile.ts b/src/utils/osu!/retrieveBeatmapFile.ts old mode 100644 new mode 100755 diff --git a/src/utils/timer/DiscordRPG/adv.ts b/src/utils/timer/DiscordRPG/adv.ts old mode 100644 new mode 100755 index 1dab81f3..f546e440 --- a/src/utils/timer/DiscordRPG/adv.ts +++ b/src/utils/timer/DiscordRPG/adv.ts @@ -1,46 +1,44 @@ -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; +import DiscordMessageContext from "../../../structures/contexts/DiscordMessageContext.js"; -export default async (ctx: MessageContext) => { - if (!ctx.message.guild) return; - const guild = (await ctx.guild())!; - const user = await ctx.author(); +export default async (ctx: DiscordMessageContext) => { + if (!ctx.guild) return; if ( - user.timers.adventure !== null - || guild.settings.adventuretimer === "off" - || guild.settings.adventuretimer === undefined - || user.settings.adventuretimer === "off" - || user.settings.adventuretimer === undefined + ctx.author.timers.adventure !== null + || ctx.guild!.settings.adventuretimer === "off" + || ctx.guild!.settings.adventuretimer === undefined + || ctx.author.settings.adventuretimer === "off" + || ctx.author.settings.adventuretimer === undefined ) return; - const content = ctx.message.content.toLowerCase(); + const content = ctx.content.toLowerCase(); let prefix = null; for (const element of [ "discordrpg ", "#!", "<@170915625722576896> ", - guild.settings.discordrpgprefix + ctx.guild!.settings.discordrpgprefix ]) { if (element && content.indexOf(`${element}adv`) === 0) { prefix = element; } } if (prefix) { - if (guild.settings.autodelete === "on") { - setTimeout(() => ctx.message.delete().catch(() => {}), 1000); + if (ctx.guild!.settings.autodelete === "on") { + ctx.delete(1000).catch(() => {}); } - const delay = user.settings.adventuretimer === "random" + const delay = ctx.author.settings.adventuretimer === "random" ? Math.random() * 3000 : 0; - user.timers.adventure = setTimeout(() => { - const ping = user.settings.timerping === "adventure" - || user.settings.timerping === "on" - ? `<@${ctx.message.author.id}>` - : `${ctx.message.author.username},`; + ctx.author.timers.adventure = setTimeout(() => { + const ping = ctx.author.settings.timerping === "adventure" + || ctx.author.settings.timerping === "on" + ? `<@${ctx.author.id}>` + : `${ctx.author.username},`; ctx.reply(`${ping} adventure time! :crossed_swords:`).then(msg => { - if (guild.settings.autodelete === "on") { + if (ctx.guild!.settings.autodelete === "on") { setTimeout(() => msg.delete(), 10000); } }); - user.timers.adventure = null; + ctx.author.timers.adventure = null; }, 13900 + delay); } }; diff --git a/src/utils/timer/DiscordRPG/padv.ts b/src/utils/timer/DiscordRPG/padv.ts old mode 100644 new mode 100755 index 21e722fd..785136dc --- a/src/utils/timer/DiscordRPG/padv.ts +++ b/src/utils/timer/DiscordRPG/padv.ts @@ -1,43 +1,41 @@ -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; +import DiscordMessageContext from "../../../structures/contexts/DiscordMessageContext.js"; -export default async (ctx: MessageContext) => { - if (!ctx.message.guild) return; - const guild = (await ctx.guild())!; - const user = await ctx.author(); +export default async (ctx: DiscordMessageContext) => { + if (!ctx.guild) return; if ( - user.timers.padventure !== null - || guild.settings.adventuretimer === "off" - || guild.settings.adventuretimer === undefined - || user.settings.adventuretimer === "off" - || user.settings.adventuretimer === undefined + ctx.author.timers.padventure !== null + || ctx.guild!.settings.adventuretimer === "off" + || ctx.guild!.settings.adventuretimer === undefined + || ctx.author.settings.adventuretimer === "off" + || ctx.author.settings.adventuretimer === undefined ) return; - const content = ctx.message.content.toLowerCase(); + const content = ctx.content.toLowerCase(); let prefix = null; for (const element of [ "discordrpg ", "#!", "<@170915625722576896> ", - guild.settings.discordrpgprefix + ctx.guild!.settings.discordrpgprefix ]) { if (element && content.indexOf(`${element}padv`) === 0) { prefix = element; } } if (prefix) { - if (guild.settings.autodelete === "on") { - setTimeout(() => ctx.message.delete().catch(() => {}), 1000); + if (ctx.guild!.settings.autodelete === "on") { + ctx.delete(1000).catch(() => {}); } - user.timers.padventure = setTimeout(() => { - const ping = user.settings.timerping === "adventure" - || user.settings.timerping === "on" - ? `<@${ctx.message.author.id}>` - : `${ctx.message.author.username},`; + ctx.author.timers.padventure = setTimeout(() => { + const ping = ctx.author.settings.timerping === "adventure" + || ctx.author.settings.timerping === "on" + ? `<@${ctx.author.id}>` + : `${ctx.author.username},`; ctx.reply(`${ping} party adventure time! :crossed_swords:`).then(msg => { - if (guild.settings.autodelete === "on") { + if (ctx.guild!.settings.autodelete === "on") { setTimeout(() => msg.delete(), 10000); } }); - user.timers.padventure = null; + ctx.author.timers.padventure = null; }, 19900); } }; diff --git a/src/utils/timer/DiscordRPG/sides.ts b/src/utils/timer/DiscordRPG/sides.ts old mode 100644 new mode 100755 index 3de25370..e0544a13 --- a/src/utils/timer/DiscordRPG/sides.ts +++ b/src/utils/timer/DiscordRPG/sides.ts @@ -1,25 +1,23 @@ import { MessageEmbed } from "discord.js"; -import MessageContext from "../../../structures/aldebaran/MessageContext.js"; +import DiscordMessageContext from "../../../structures/contexts/DiscordMessageContext.js"; const emoji = ["🥕", "🍋", "🥔", "🐟"]; -export default async (ctx: MessageContext) => { - if (!ctx.message.guild) return; - const guild = (await ctx.guild())!; - const user = await ctx.author(); +export default async (ctx: DiscordMessageContext) => { + if (!ctx.guild) return; - if (!user.settings.sidestimer || user.settings.sidestimer === "off" - || !guild.settings.sidestimer || guild.settings.sidestimer === "off") { + if (!ctx.author.settings.sidestimer || ctx.author.settings.sidestimer === "off" + || !ctx.guild!.settings.sidestimer || ctx.guild!.settings.sidestimer === "off") { return; } let prefix = null; - const content = `${ctx.message.content.toLowerCase()} `; + const content = `${ctx.content.toLowerCase()} `; for (const element of [ "discordrpg ", "#!", - guild.settings.discordrpgprefix + ctx.guild!.settings.discordrpgprefix ]) { for (const action of ["mine", "forage", "chop", "fish"]) { if (content.indexOf(`${element}${action} `) === 0) { @@ -29,48 +27,48 @@ export default async (ctx: MessageContext) => { } if (prefix) { - if (guild.settings.autodelete === "on") { - setTimeout(() => ctx.message.delete().catch(() => {}), 2000); + if (ctx.guild!.settings.autodelete === "on") { + ctx.delete(2000).catch(() => {}); } - if (user.timers.sides !== null) return; + if (ctx.author.timers.sides !== null) return; - const setting = user.settings.sidestimer; + const setting = ctx.author.settings.sidestimer; const primaryAction = setting === "on" ? "mine" : setting; if (content.indexOf(`${prefix}${primaryAction}`) === 0) { // Setting the timer on - user.timers.sides = setTimeout(() => { - const ping = user.settings.timerping === "on" - || user.settings.timerping === "sides" - ? `<@${user.id}>` - : `${user.username},`; + ctx.author.timers.sides = setTimeout(() => { + const ping = ctx.author.settings.timerping === "on" + || ctx.author.settings.timerping === "sides" + ? `<@${ctx.author.id}>` + : `${ctx.author.username},`; const randomemoji = emoji[Math.floor(Math.random() * emoji.length)]; ctx.reply(`${ping} sides time! ${randomemoji}`).then(msg => { - if (guild.settings.autodelete === "on") { + if (ctx.guild!.settings.autodelete === "on") { setTimeout(() => msg.delete(), 180000); } }); - user.timers.sides = null; + ctx.author.timers.sides = null; }, 299250); const timerEmbed = new MessageEmbed() .setAuthor( - ctx.message.author.username, - ctx.message.author.displayAvatarURL() + ctx.author.username, + ctx.author.avatarURL ) .setColor(0x00ae86) .setDescription("React with 🚫 to cancel timer."); ctx.reply(timerEmbed).then(mesg => { - mesg.react("🚫"); + mesg.react("🚫").catch(() => {}); mesg.awaitReactions({ - filter: (r, u) => r.emoji.name === "🚫" && u.id === ctx.message.author.id, + filter: (r, u) => r.emoji.name === "🚫" && u.id === ctx.author.id, time: 5000, max: 1 }).then(reactions => { setTimeout(() => mesg.delete(), 5000); if (reactions.get("🚫") === undefined) { const embed = new MessageEmbed() - .setAuthor("Your sides timer has been set!", ctx.message.author.displayAvatarURL()) + .setAuthor("Your sides timer has been set!", ctx.author.avatarURL) .setColor(0x00ae86); ctx.reply(embed).then(timerset => { setTimeout(() => timerset.delete(), 5000); @@ -78,11 +76,11 @@ export default async (ctx: MessageContext) => { } else { const embed1 = new MessageEmbed() .setDescription("Timer Cancelled") - .setAuthor(`${user.username}`) + .setAuthor(`${ctx.author.username}`) .setColor("RED"); - clearTimeout(user.timers.sides!); - user.timers.sides = null; + clearTimeout(ctx.author.timers.sides!); + ctx.author.timers.sides = null; ctx.reply(embed1).then(timernotset => { setTimeout(() => timernotset.delete(), 5000); diff --git a/tsconfig.json b/tsconfig.json old mode 100644 new mode 100755