Advertisement
lord_shadow

Untitled

Jan 11th, 2024
1,123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import {
  2.     Message,
  3.     InteractionReplyOptions,
  4.     CommandInteraction,
  5.     User,
  6.     Guild,
  7.     GuildMember,
  8.     BaseInteraction,
  9.     MessageCreateOptions,
  10.     InteractionResponseType,
  11.     TextChannel,
  12.     Routes,
  13.     isJSONEncodable,
  14. } from 'discord.js';
  15. import { Command } from '../Command';
  16. import { Args } from 'lexure';
  17. import { getMissingArgumentsEmbed } from '../../handlers/locale';
  18. import { config } from '../../config';
  19. import { discordClient } from '../../main';
  20.  
  21. export class CommandContext  {
  22.     type: 'interaction' | 'message';
  23.     subject?: CommandInteraction | Message;
  24.     user?: User;
  25.     member?: GuildMember;
  26.     guild?: Guild;
  27.     token?: string;
  28.     id?: string;
  29.     args?: { [key: string]: any };
  30.     replied: boolean;
  31.     deferred: boolean;
  32.     command: Command;
  33.     channel: TextChannel | null;
  34.  
  35.     /**
  36.      * Command context for getting usage information and replying.
  37.      *
  38.      * @param payload
  39.      */
  40.     constructor(payload: BaseInteraction | CommandInteraction | Message, command: any, args?: Args) {
  41.         this.type = payload instanceof Message ? 'message' : 'interaction';
  42.         this.subject = payload instanceof BaseInteraction ? payload as CommandInteraction : payload;
  43.         this.user = payload instanceof Message ? payload.author : payload.user;
  44.         this.member = payload.member as GuildMember;
  45.         this.guild = payload.guild;
  46.         this.command = new command();
  47.         this.id = discordClient.user.id;
  48.         console.log(this.id)
  49.         this.token = process.env.DISCORD_TOKEN;
  50.         this.channel = payload.channel as TextChannel;
  51.         this.replied = false;
  52.         this.deferred = false;
  53.  
  54.         this.args = {};
  55.         if(payload instanceof BaseInteraction) {
  56.             const interaction = payload as CommandInteraction;
  57.             interaction.options.data.forEach(async (arg) => {
  58.                 this.args[arg.name] = interaction.options.get(arg.name).value;
  59.             });
  60.         } else {
  61.             this.subject.channel.sendTyping();
  62.             this.command.args.forEach((arg, index) => { if(!arg.isLegacyFlag) this.args[arg.trigger] = args.single() });
  63.             const filledOutArgs = Object.keys(Object.fromEntries(Object.entries(this.args).filter(([_, v]) => v !== null)));
  64.             const requiredArgs = this.command.args.filter((arg) => (arg.required === undefined || arg.required === null ? true : arg.required) && !arg.isLegacyFlag);
  65.             if(filledOutArgs.length < requiredArgs.length) {
  66.                 this.reply({ embeds: [ getMissingArgumentsEmbed(this.command.trigger, this.command.args) ] });
  67.                 throw new Error('INVALID_USAGE');
  68.             } else {
  69.                 if(args.length > requiredArgs.length) {
  70.                     const extraArgs = args.many(1000, requiredArgs.length);
  71.                     this.args[Object.keys(this.args).filter((key) => !this.command.args.find((arg) => arg.trigger === key).isLegacyFlag).at(-1)] = [ this.args[Object.keys(this.args).filter((key) => !this.command.args.find((arg) => arg.trigger === key).isLegacyFlag).at(-1)], ...extraArgs.map((arg) => arg.value)].join(' ');
  72.                 }
  73.                 let areAllRequiredFlagsEntered = true;
  74.                 this.command.args.filter((arg) => arg.isLegacyFlag).forEach((arg) => {
  75.                     const flagValue = args.option(arg.trigger);
  76.                     if(!flagValue && arg.required) areAllRequiredFlagsEntered = false;
  77.                     this.args[arg.trigger] = flagValue;
  78.                 });
  79.                 if(!areAllRequiredFlagsEntered) {
  80.                     this.reply({ embeds: [ getMissingArgumentsEmbed(this.command.trigger, this.command.args) ] });
  81.                     throw new Error('INVALID_USAGE');
  82.                 }
  83.             }
  84.         }
  85.     }
  86.  
  87.     checkPermissions() {
  88.         if(!this.command.permissions || this.command.permissions.length === 0) {
  89.             return true;
  90.         } else {
  91.             let hasPermission = null;
  92.             let permissions = [];
  93.             this.command.permissions.map((permission) => {
  94.                 permission.ids.forEach((id) => {
  95.                     return permissions.push({
  96.                         type: permission.type,
  97.                         id,
  98.                         value: permission.value,
  99.                     });
  100.                 });
  101.             });
  102.             const permission = permissions.forEach((permission) => {
  103.                 let fitsCriteria: boolean;
  104.                 if(!hasPermission) {
  105.                     if(config.permissions.all && this.member.roles.cache.some((role) => config.permissions.all.includes(role.id))) {
  106.                         fitsCriteria = true;
  107.                     } else {
  108.                         if(permission.type === 'role') fitsCriteria = this.member.roles.cache.has(permission.id);
  109.                         if(permission.type === 'user') fitsCriteria = this.member.id === permission.id;
  110.                     }
  111.                     if(fitsCriteria) hasPermission = true;
  112.                 }
  113.             });
  114.             return hasPermission || false;
  115.         }
  116.     }
  117.  
  118.     /**
  119.      * Send a mesasge in the channel of the command message, or directly reply to a command interaction.
  120.      *
  121.      * @param payload
  122.      */
  123.     async reply(payload: string | InteractionReplyOptions | MessageCreateOptions | InteractionReplyOptions) {
  124.         this.replied = true;
  125.         if(this.subject instanceof CommandInteraction) {
  126.             try {
  127.                 const subject = this.subject as CommandInteraction;
  128.                 if(this.deferred) {
  129.                     return await subject.editReply(payload);
  130.                 } else {
  131.                     return await subject.reply(payload as InteractionReplyOptions);
  132.                 }
  133.             } catch (err) {
  134.                 const subject = this.subject as CommandInteraction;
  135.                 try {
  136.                     if(this.deferred) {
  137.                         return await subject.editReply(payload as InteractionReplyOptions);
  138.                     } else {
  139.                         return await subject.reply(payload as InteractionReplyOptions);
  140.                     }
  141.                 } catch (err) {};
  142.             }
  143.         } else {
  144.             return await this.subject.channel.send(payload as MessageCreateOptions);
  145.         }
  146.     }
  147.  
  148. /**
  149.  * Shows a modal component
  150.  * @param {ModalBuilder | ModalComponentData | APIModalInteractionResponseCallbackData} modal The modal to show
  151.  * @returns {Promise<void>}
  152.  */
  153. async showModal(modal) {
  154.     this.replied = false;
  155.     if (this.deferred || this.replied) throw console.error('Cannot show a modal after replying or deferring');
  156.     await discordClient.rest.post(Routes.interactionCallback(this.id, this.token), {
  157.       body: {
  158.         type: InteractionResponseType.Modal,
  159.         data: isJSONEncodable(modal) ? modal.toJSON() : discordClient.options.jsonTransformer(modal),
  160.       },
  161.       auth: false,
  162.     });
  163.     this.replied = true;
  164. }
  165.  
  166.     async editReply(payload: string | InteractionReplyOptions | MessageCreateOptions | InteractionReplyOptions) {
  167.         if(this.subject instanceof CommandInteraction) {
  168.             try {
  169.                 const subject = this.subject as CommandInteraction;
  170.                 return await subject.editReply(payload);
  171.             } catch (err) {
  172.                 const subject = this.subject as CommandInteraction;
  173.                 try {
  174.                     return await subject.editReply(payload);
  175.                 } catch (err) {};
  176.             }
  177.         } else {
  178.             return await this.subject.channel.send(payload as MessageCreateOptions);
  179.         }
  180.     }
  181.  
  182.     /**
  183.      * Defers a reply.
  184.      */
  185.     async defer() {
  186.         try {
  187.             if(this.subject instanceof CommandInteraction) {
  188.                 const interaction = this.subject as CommandInteraction;
  189.                 if(!interaction.deferred && !interaction.replied) await this.subject.deferReply();
  190.             } else {
  191.                 await this.subject.channel.sendTyping();
  192.             }
  193.             this.deferred = true;
  194.         } catch (err) {};
  195.     }
  196. }
  197.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement