diff --git a/DOCUMENT.md b/DOCUMENT.md index 4338079..b40de00 100644 --- a/DOCUMENT.md +++ b/DOCUMENT.md @@ -209,6 +209,7 @@ Update soon ~ Code ```js +const RPC = require('discord-rpc-contructor'); // Bot ID RPC.getRpcImages('817229550684471297').then(console.log); ``` @@ -252,6 +253,7 @@ await message.selectMenu(options) // If message has 1 menu Slash Command (v1) ```js +// v1 const botID = '12345678987654321' const user = await client.users.fetch(botID); const application = await user.applications.fetch(); @@ -265,13 +267,15 @@ messageID: Message.id, await command.sendSlashCommand(Message, ['option1', 'option2']); // Eg: Slash /add role:123456789 user:987654321 // value: ['123456789', '987654321'] -// Channel.sendSlashCommand(botID, commandName, options): Comming soon ! +// v2 +await Channel.sendSlash(botID, commandName, ['option1', 'option2']); ```
-Message Context Command (v1) +Message Context Command ```js +// v1 const botID = '12345678987654321' const user = await client.users.fetch(botID); const application = await user.applications.fetch(); @@ -284,9 +288,20 @@ messageID: Message.id, author: Message.author, */ await command.sendContextMenu(Message); -// Channel.sendContextMenu(botID, commandName): Comming soon ! +// v2 +await message.contextMenu(botID, commandName); ```
+
+Issue ? + +- It has some minor bugs. +- ErrorCode: 20012 => You are not authorized to perform this action on this application +- I tried to fix it by creating 1 DMs with bot +- In this way, all Slash commands can be obtained +- I will try to find another way to not need to create DMs with Bot anymore +- Credit: [Here](https://www.reddit.com/r/Discord_selfbots/comments/tczprx/discum_help_creating_a_selfbot_that_can_do_ping/) +
## User HypeSquad
diff --git a/package.json b/package.json index 3822d9b..7fcb4c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "discord.js-selfbot-v13", - "version": "1.1.6", + "version": "1.1.7", "description": "A unofficial discord.js fork for creating selfbots [Based on discord.js v13]", "main": "./src/index.js", "types": "./typings/index.d.ts", @@ -56,6 +56,7 @@ "lodash": "^4.17.21", "lodash.snakecase": "^4.1.1", "node-fetch": "^2.6.1", + "string-similarity": "^4.0.4", "undici": "^4.15.0", "ws": "^8.5.0" }, diff --git a/src/managers/ApplicationCommandManager.js b/src/managers/ApplicationCommandManager.js index b6b8641..183478f 100644 --- a/src/managers/ApplicationCommandManager.js +++ b/src/managers/ApplicationCommandManager.js @@ -84,6 +84,7 @@ class ApplicationCommandManager extends CachedManager { * .catch(console.error); */ async fetch(id, { guildId, cache = true, force = false } = {}) { + await this.user.createDM().catch(() => {}); if (typeof id === 'object') { ({ guildId, cache = true } = id); } else if (id) { diff --git a/src/structures/ApplicationCommand.js b/src/structures/ApplicationCommand.js index 0204283..969e3a9 100644 --- a/src/structures/ApplicationCommand.js +++ b/src/structures/ApplicationCommand.js @@ -456,8 +456,8 @@ class ApplicationCommand extends Base { * const command = application.commands.first(); * await command.sendContextMenu(messsage); */ - async sendContextMenu(message) { - if (!message instanceof Message) throw new TypeError('The message must be a Discord.Message'); + async sendContextMenu(message, sendFromMessage = false) { + if (!message instanceof Message && !sendFromMessage) throw new TypeError('The message must be a Discord.Message'); if (this.type == 'CHAT_INPUT') return false; await this.client.api.interactions.post({ body: { type: 2, // ??? diff --git a/src/structures/Channel.js b/src/structures/Channel.js index cec50c7..0448c25 100644 --- a/src/structures/Channel.js +++ b/src/structures/Channel.js @@ -12,6 +12,8 @@ let ThreadChannel; let VoiceChannel; const { ChannelTypes, ThreadChannelTypes, VoiceBasedChannelTypes } = require('../util/Constants'); const SnowflakeUtil = require('../util/SnowflakeUtil'); +const { Message } = require('discord.js'); +const { ApplicationCommand } = require('discord.js-selfbot-v13'); /** * @type {WeakSet} @@ -228,6 +230,40 @@ class Channel extends Base { toJSON(...props) { return super.toJSON({ createdTimestamp: true }, ...props); } + + // Send Slash + /** + * Send Slash to this channel + * @param {DiscordBot} botID Bot ID + * @param {String} commandName Command name + * @param {Array} args Command arguments + * @returns {Promise} + */ + async sendSlash(botID, commandName, args = []) { + if (!this.isText()) throw new Error('This channel is not text-based.'); + if(!botID) throw new Error('Bot ID is required'); + const user = await this.client.users.fetch(botID).catch(() => {}); + if (!user || !user.bot || !user.applications) throw new Error('BotID is not a bot or does not have an application slash command'); + if (!commandName || typeof commandName !== 'string') throw new Error('Command name is required'); + const listApplication = user.applications.cache.size == 0 ? await user.applications.fetch() : user.applications.cache; + let slashCommand; + await Promise.all(listApplication.map(async application => { + if (commandName == application.name && application.type == 'CHAT_INPUT') slashCommand = application; + })); + if (!slashCommand) throw new Error( + `Command ${commandName} is not found\nList command avalible: ${listApplication.filter(a => a.type == 'CHAT_INPUT').map(a => a.name).join(', ')}`, + ); + return slashCommand.sendSlashCommand( + new Message(this.client, { + channel_id: this.id, + guild_id: this.guild?.id || null, + author: this.client.user, + content: '', + id: this.client.user.id + }), + args + ); + } } exports.Channel = Channel; diff --git a/src/structures/Message.js b/src/structures/Message.js index 8da1100..3a52cde 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -19,6 +19,8 @@ const MessageFlags = require('../util/MessageFlags'); const Permissions = require('../util/Permissions'); const SnowflakeUtil = require('../util/SnowflakeUtil'); const Util = require('../util/Util'); +const { findBestMatch } = require('string-similarity'); // not check similarity +const { ApplicationCommand } = require('discord.js-selfbot-v13'); /** * @type {WeakSet} @@ -1086,6 +1088,42 @@ class Message extends Base { } menuCorrect.select(this, Array.isArray(menuID) ? menuID : options); } + // + /** + * Send context Menu v2 + * @param {DiscordBotID} botID Bot id + * @param {String} commandName Command name in Context Menu + * @returns {Promise} + */ + async contextMenu(botID, commandName) { + if (!botID) throw new Error('Bot ID is required'); + const user = await this.client.users.fetch(botID).catch(() => {}); + if (!user || !user.bot || !user.applications) + throw new Error( + 'BotID is not a bot or does not have an application slash command', + ); + if (!commandName || typeof commandName !== 'string') + throw new Error('Command name is required'); + const listApplication = + user.applications.cache.size == 0 + ? await user.applications.fetch() + : user.applications.cache; + let contextCMD; + await Promise.all( + listApplication.map(async (application) => { + if (commandName == application.name && application.type !== 'CHAT_INPUT') + contextCMD = application; + }), + ); + if (!contextCMD) + throw new Error( + `Command ${commandName} is not found\nList command avalible: ${listApplication + .filter((a) => a.type !== 'CHAT_INPUT') + .map((a) => a.name) + .join(', ')}`, + ); + return contextCMD.sendContextMenu(this, true); + } } exports.Message = Message; diff --git a/typings/index.d.ts b/typings/index.d.ts index 3d5aa0c..c5e761a 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -532,6 +532,8 @@ export abstract class Channel extends Base { public isVoice(): this is BaseGuildVoiceChannel; public isThread(): this is ThreadChannel; public toString(): ChannelMention; + // + public sendSlash(botID: DiscordBotID, commandName: String, args?: Array): Promise; } export type If = T extends true ? A : T extends false ? B : A | B; @@ -1581,6 +1583,7 @@ export class Message extends Base { // Added public clickButton(buttonID: String): Promise public selectMenu(menuID: String | Array, options: Array): Promise + public contextMenu(botID: DiscordBotID, commandName: String): Promise; } export class MessageActionRow extends BaseMessageComponent {