const { ButtonStyles, Client, ComponentTypes, ChannelTypes } = require("oceanic.js"); const client = new Client({ auth: `Bot ${process.env.DISCORD_TOKEN}`, gateway: { intents: ["GUILD_MESSAGES"] // If the message does not start with a mention to or somehow relate to your client, you will need the MESSAGE_CONTENT intent as well } }); client.on("ready", () => console.log("Ready as", client.user.tag)); client.on("messageCreate", async (msg) => { console.log(msg.content) if(msg.content.includes("!test")) { await client.rest.channels.createMessage(msg.channelID, { content: `HGERE IZ BUTTN'z 5 u, ${msg.author.mention}.`, components: [ { // The top level component must always be an action row. // Full list of types: https://docs.oceanic.ws/latest/enums/Constants.ComponentTypes.html // https://docs.oceanic.ws/latest/interfaces/Types_Channels.MessageActionRow.html type: ComponentTypes.ACTION_ROW, components: [ { // https://docs.oceanic.ws/latest/interfaces/Types_Channels.TextButton.html type: ComponentTypes.BUTTON, style: ButtonStyles.PRIMARY, // The style of button - full list: https://docs.oceanic.ws/latest/enums/Constants.ButtonStyles.html customID: "some-string-you-will-see-later", label: "Click!", disabled: false, // If the button is disabled, false by default. }, { type: ComponentTypes.BUTTON, style: ButtonStyles.PRIMARY, customID: "some-other-string", label: "This Is Disabled", disabled: true }, { // https://docs.oceanic.ws/latest/interfaces/Types_Channels.URLButton.html type: ComponentTypes.BUTTON, style: ButtonStyles.LINK, label: "Open Link", url: "https://docs.oceanic.ws" } ] }, { // The top level component must always be an action row. // Full list of types: https://docs.oceanic.ws/latest/enums/Constants.ComponentTypes.html // https://docs.oceanic.ws/latest/interfaces/Types_Channels.MessageActionRow.html type: ComponentTypes.ACTION_ROW, components: [ { // https://docs.oceanic.ws/latest/interfaces/Types_Channels.SelectMenu.html type: ComponentTypes.STRING_SELECT, customID: "string-select", disabled: false, maxValues: 1, // The maximum number of values that can be selected (default 1) minValues: 1, // The minimum number of values that can be selected (default 1) options: [ // https://docs.oceanic.ws/latest/interfaces/Types_Channels.SelectOption.html { default: true, // If this option is selected by default description: "The description of the option", // Optional description label: "Option One", value: "value-1" }, { label: "Option Two", value: "option-2" } ], placeholder: "Some Placeholder Text" } ] }, { // The top level component must always be an action row. // Full list of types: https://docs.oceanic.ws/latest/enums/Constants.ComponentTypes.html // https://docs.oceanic.ws/latest/interfaces/Types_Channels.MessageActionRow.html type: ComponentTypes.ACTION_ROW, components: [ { // https://docs.oceanic.ws/latest/interfaces/Types_Channels.SelectMenu.html type: ComponentTypes.CHANNEL_SELECT, channelTypes: [ChannelTypes.GUILD_TEXT, ChannelTypes.GUILD_VOICE], // The types of channels that can be selected customID: "channel-select", disabled: false, maxValues: 1, // The maximum number of values that can be selected (default 1) minValues: 1, // The minimum number of values that can be selected (default 1) placeholder: "Some Placeholder Text" } ] } ] }); } }); client.on("interactionCreate", async(interaction) => { console.log(`interaction!@`) console.log(interaction) switch(interaction.type) { // https://docs.oceanic.ws/latest/classes/CommandInteraction.CommandInteraction.html case InteractionTypes.APPLICATION_COMMAND: { // defer interactions as soon as possible, you have three seconds to send any initial response // if you wait too long, the interaction may be invalidated await interaction.defer(); // If you want the response to be ephemeral, you can provide the flag to the defer function, like so: // await interaction.defer(MessageFlags.EPHEMERAL); // data = https://docs.oceanic.ws/latest/interfaces/Types_Interactions.ApplicationCommandInteractionData.html switch(interaction.data.type) { // Chat Input commands are what you use in the chat, i.e. slash commands case ApplicationCommandTypes.CHAT_INPUT: { if(interaction.data.name === "greet") { // assume we have two options, user (called user) then string (called greeting) - first is required, second is not // Get an option named `user` with the type USER - https://docs.oceanic.ws/dev/classes/InteractionOptionsWrapper.InteractionOptionsWrapper.html#getUser // Setting the second parameter to true will throw an error if the option is not present const user = interaction.data.options.getUser("user", true); const greeting = interaction.data.options.getString("greeting", false) || "Hello, "; // since we've already deferred the interaction, we cannot use createMessage (this is an initial response) // we can only have one initial response, so we use createFollowup await interaction.createFollowup({ content: `${greeting} ${user.mention}!`, allowedMentions: { users: [user.id] } }); } // Chat Input application command interactions also have a set of resolved data, which is structured as so: // https://docs.oceanic.ws/latest/interfaces/Types_Interactions.ApplicationCommandInteractionResolvedData.html // the options wrapper pulls values out of resolved automatically, if you use the right method break; } // User application commands are shown in the context menu when right-clicking on users // `data` will have a target (and targetID) property with the user that the command was executed on // These don't have options case ApplicationCommandTypes.USER: { if(interaction.data.name === "ping") { await interaction.createFollowup({ content: `Pong! ${interaction.data.target.mention}`, allowedMentions: { users: [interaction.data.target.id] } }); } break; } // Message application commands are shown in the context menu when right-clicking on messages // `data` will have a target (and targetID) property with the message that the command was executed on // Same as user commands, these don't have options case ApplicationCommandTypes.MESSAGE: { if(interaction.data.name === "author") { await interaction.createFollowup({ content: `${interaction.data.target.author.mention} is the author of that message!`, allowedMentions: { users: [interaction.data.target.author.id] } }); } break; } } break; } // https://docs.oceanic.ws/latest/classes/ComponentInteraction.ComponentInteraction.html case InteractionTypes.MESSAGE_COMPONENT: { // same spiel as above await interaction.defer(); // when you create a message with components, this will correspond with what you provided as the customID there if(interaction.data.componentType === ComponentTypes.BUTTON) { if(interaction.data.customID === "edit-message") { // Edits the original message. This has an initial response variant: editParent await interaction.editOriginal({ content: `This message was edited by ${interaction.user.mention}!`, allowedMentions: { users: [interaction.user.id] } }); } else if(interaction.data.customID === "my-amazing-button") { await interaction.createFollowup({ content: "You clicked an amazing button!" }); } } else if(interaction.data.componentType === ComponentTypes.SELECT_MENU) { // The `values` property under data contains all the selected values await interaction.createFollowup({ content: `You selected: **${interaction.data.values.join("**, **")}**` }); } break; } // https://docs.oceanic.ws/latest/classes/AutocompleteInteraction.AutocompleteInteraction.html case InteractionTypes.APPLICATION_COMMAND_AUTOCOMPLETE: { // Autocomplete Interactions cannot be deferred switch(interaction.data.name) { case "test-autocomplete": { // Autocomplete interactions data has a partial `options` property, which is the tree of options that are currently being filled in // along with one at the end, which will have focused // Setting the first parameter to true will throw an error if no focused option is present const option = interaction.data.options.getFocused(true); switch(option.name) { case "test-option": { return interaction.result([ { name: "Choice 1", nameLocalizations: { "es-ES": "Opción 1" }, value: "choice-1" }, { name: "Choice 2", nameLocalizations: { "es-ES": "Opción 2" }, value: "choice-2" } ]); break; } } } } break; } // https://docs.oceanic.ws/latest/classes/ModalSubmitInteraction.ModalSubmitInteraction.html case InteractionTypes.MODAL_SUBMIT: { // this will correspond with the customID you provided when creating the modal switch(interaction.data.customID) { case "test-modal": { // the `components` property under data contains all the components that were submitted // https://docs.oceanic.ws/latest/interfaces/Types_Channels.ModalActionRow.html console.log(interaction.data.components); break; } } break; } } }); // An error handler client.on("error", (error) => { console.error("Something went wrong:", error); }); // Connect to Discord client.connect();