diff --git a/README.md b/README.md index d818c0a..36c8ba1 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,10 @@ clean up p/vileimagery, its horrendous **_Note:_** _versions before this were not uploaded to the repo, this is not the first version._ + 1.11 - added PEPPERBOT VOICE CHAT CAPABILITY + +--- + 1.10 - changed all requires to imports --- diff --git a/package-lock.json b/package-lock.json index 6cb688c..4e59a44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,12 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@discordjs/voice": "^0.16.0", "discord.js": "^14.13.0", "discord.js-collector": "^1.8.9", "dotenv": "^16.3.1", "emoji-regex": "^10.2.1", + "libsodium-wrappers": "^0.7.13", "regex": "^0.1.1" } }, @@ -93,6 +95,21 @@ "node": ">=16.11.0" } }, + "node_modules/@discordjs/voice": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.16.0.tgz", + "integrity": "sha512-ToGCvHD1cBscuW3p+C7zOF5+L7MJmU4GjdOARfNk9mkHyFFZq4grK+Sxr3QXKbp27DtfDBc9uqD4GUOYgxngfA==", + "dependencies": { + "@types/ws": "^8.5.4", + "discord-api-types": "^0.37.37", + "prism-media": "^1.3.5", + "tslib": "^2.5.0", + "ws": "^8.13.0" + }, + "engines": { + "node": ">=16.9.0" + } + }, "node_modules/@discordjs/ws": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.1.tgz", @@ -526,6 +543,19 @@ "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", "integrity": "sha512-DuAEISsr1H4LOpmFLkyMc8YStiRWZCO8hMsoXAXSbgyfvs2WQhSt0+/FBv3ZU/JBFZMGcE+FWzEBSzwUU7U27w==" }, + "node_modules/libsodium": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.13.tgz", + "integrity": "sha512-mK8ju0fnrKXXfleL53vtp9xiPq5hKM0zbDQtcxQIsSmxNgSxqCj6R7Hl9PkrNe2j29T4yoDaF7DJLK9/i5iWUw==" + }, + "node_modules/libsodium-wrappers": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.13.tgz", + "integrity": "sha512-kasvDsEi/r1fMzKouIDv7B8I6vNmknXwGiYodErGuESoFTohGSKZplFtVxZqHaoQ217AynyIFgnOVRitpHs0Qw==", + "dependencies": { + "libsodium": "^0.7.13" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -1061,6 +1091,18 @@ "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz", "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA==" }, + "@discordjs/voice": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.16.0.tgz", + "integrity": "sha512-ToGCvHD1cBscuW3p+C7zOF5+L7MJmU4GjdOARfNk9mkHyFFZq4grK+Sxr3QXKbp27DtfDBc9uqD4GUOYgxngfA==", + "requires": { + "@types/ws": "^8.5.4", + "discord-api-types": "^0.37.37", + "prism-media": "^1.3.5", + "tslib": "^2.5.0", + "ws": "^8.13.0" + } + }, "@discordjs/ws": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.1.tgz", @@ -1380,6 +1422,19 @@ "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", "integrity": "sha512-DuAEISsr1H4LOpmFLkyMc8YStiRWZCO8hMsoXAXSbgyfvs2WQhSt0+/FBv3ZU/JBFZMGcE+FWzEBSzwUU7U27w==" }, + "libsodium": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.13.tgz", + "integrity": "sha512-mK8ju0fnrKXXfleL53vtp9xiPq5hKM0zbDQtcxQIsSmxNgSxqCj6R7Hl9PkrNe2j29T4yoDaF7DJLK9/i5iWUw==" + }, + "libsodium-wrappers": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.13.tgz", + "integrity": "sha512-kasvDsEi/r1fMzKouIDv7B8I6vNmknXwGiYodErGuESoFTohGSKZplFtVxZqHaoQ217AynyIFgnOVRitpHs0Qw==", + "requires": { + "libsodium": "^0.7.13" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", diff --git a/package.json b/package.json index cf0c058..d8eecec 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,12 @@ "author": "", "license": "ISC", "dependencies": { + "@discordjs/voice": "^0.16.0", "discord.js": "^14.13.0", "discord.js-collector": "^1.8.9", "dotenv": "^16.3.1", "emoji-regex": "^10.2.1", + "libsodium-wrappers": "^0.7.13", "regex": "^0.1.1" } } diff --git a/src/commands/openpepper.js b/src/commands/git.js similarity index 55% rename from src/commands/openpepper.js rename to src/commands/git.js index 8a3cec7..d8ff2b7 100644 --- a/src/commands/openpepper.js +++ b/src/commands/git.js @@ -1,8 +1,8 @@ export default { - name: "openpepper", + name: "git", description: "posts open pepper repo", arguments: "none", execute(message, args) { - message.reply("https://git.reidlab.online/ayeuhugyu/OpenPepper"); + message.reply("https://git.reidlab.online/ayeuhugyu/PepperBot"); }, }; diff --git a/src/commands/joinvc.js b/src/commands/joinvc.js new file mode 100644 index 0000000..237a7b9 --- /dev/null +++ b/src/commands/joinvc.js @@ -0,0 +1,26 @@ +import { joinVoiceChannel } from "@discordjs/voice"; +import * as dotenv from "dotenv"; +dotenv.config(); + +const guildId = process.env.GUILD_ID; + +export default { + name: "joinvc", + description: "joins the vc that the user is currently in", + arguments: "none", + execute(message, args) { + if (message.member.voice.channel) { + let voiceState = message.member.voice; + + let connection = joinVoiceChannel({ + channelId: voiceState.channelId, + guildId: voiceState.guild.id, + adapterCreator: voiceState.guild.voiceAdapterCreator, + }); + + message.reply(`connected to <#${voiceState.channelId}>`); + } else { + message.reply("u aint connected to a voice channel blud 😂😂😂"); + } + }, +}; diff --git a/src/commands/leavevc.js b/src/commands/leavevc.js new file mode 100644 index 0000000..dbff137 --- /dev/null +++ b/src/commands/leavevc.js @@ -0,0 +1,16 @@ +import { getVoiceConnection } from "@discordjs/voice"; + +export default { + name: "leavevc", + description: "leaves vc that user is currently in", + arguments: "none", + execute(message, args) { + if (getVoiceConnection(message.guild.id)) { + const connection = getVoiceConnection(message.guild.id); + connection.destroy(); + message.reply(`left voice channel <#${connection.joinConfig.channelId}>`); + } else { + message.reply("im not connected to a voice channel here mf"); + } + }, +}; diff --git a/src/commands/soundboard.js b/src/commands/soundboard.js new file mode 100644 index 0000000..308e31f --- /dev/null +++ b/src/commands/soundboard.js @@ -0,0 +1,103 @@ +import { + createAudioPlayer, + createAudioResource, + getVoiceConnection, + joinVoiceChannel, +} from "@discordjs/voice"; +import fs from "fs"; +import * as dotenv from "dotenv"; +dotenv.config(); + +const prefix = process.env.PREFIX; + +export default { + name: "soundboard", + description: "plays specified sound file", + arguments: "file", + execute(message, args) { + const audioPlayer = createAudioPlayer(); + let proposedfilename = message.content.slice( + prefix.length + this.name.length + 1 + ); + const files = fs.readdirSync("resources/soundboard"); + let file; + let lsmode = false; + let stopmode = false; + + let possibleFilenames = { + regular: proposedfilename, + spaced: proposedfilename.replaceAll(" ", "_"), + spacedmp3: proposedfilename.replaceAll(" ", "_") + ".mp3", + mp3: proposedfilename + ".mp3", + spacedogg: proposedfilename.replaceAll(" ", "_") + ".ogg", + ogg: proposedfilename + ".ogg", + spacedwav: proposedfilename.replaceAll(" ", "_") + ".wav", + wav: proposedfilename + ".wav", + spacedwebm: proposedfilename.replaceAll(" ", "_") + ".webm", + webm: proposedfilename + ".webm", + }; + for (const value of Object.values(possibleFilenames)) { + if (files.includes(value)) { + file = value; + } + } + if (proposedfilename === "ls") { + fs.writeFileSync("resources/soundboard/ls.txt", ""); + lsmode = true; + for (let file = 0; file < files.length; file++) { + if (files[file] !== "ls.txt") { + fs.appendFileSync("resources/soundboard/ls.txt", `${files[file]}\n`); + } + } + } + if (proposedfilename === "stop") { + let connection = getVoiceConnection(message.guild.id); + connection.subscribe(audioPlayer); + audioPlayer.stop(); + message.reply("stopped audio playback"); + return; + } + + if (!file && !lsmode && !stopmode) { + message.reply( + "unable to find your file in the soundboard folder put `ls` as your args to upload a file of all names. try replacing spaces with _s. you proposed: " + + proposedfilename + ); + } + if (!lsmode) { + const audioResource = createAudioResource(`resources/soundboard/${file}`); + + let connection = getVoiceConnection(message.guild.id); + if (!connection) { + if (message.member.voice.channel) { + let voiceState = message.member.voice; + + let connection = joinVoiceChannel({ + channelId: voiceState.channelId, + guildId: voiceState.guild.id, + adapterCreator: voiceState.guild.voiceAdapterCreator, + }); + + message.reply(`connected to <#${voiceState.channelId}>`); + } else { + message.reply( + "the bot is not in a voice channel so a sound cannot be played, and you are not in a voice channel so it can't auto join. IDIOT!" + ); + return; + } + } + connection = getVoiceConnection(message.guild.id); + connection.subscribe(audioPlayer); + audioPlayer.play(audioResource); + } else { + message.channel.send({ + files: [ + { + attachment: "resources/soundboard/ls.txt", + name: "ls.txt", + }, + ], + }); + } + }, +}; diff --git a/src/events/importEvents.js b/src/events/importEvents.js index f6fc2aa..c9bc161 100644 --- a/src/events/importEvents.js +++ b/src/events/importEvents.js @@ -2,12 +2,14 @@ import { default as guildMemberAdd } from "./guildMemberAdd.js"; import { default as messageCreate } from "./messageCreate.js"; import { default as messageDelete } from "./messageDelete.js"; import { default as ready } from "./ready.js"; +import { default as interactionCreate } from "./interactionCreate.js"; const events = { guildMemberAdd, messageCreate, messageDelete, ready, + interactionCreate, }; export default events; diff --git a/src/events/interactionCreate.js b/src/events/interactionCreate.js new file mode 100644 index 0000000..7a1dde5 --- /dev/null +++ b/src/events/interactionCreate.js @@ -0,0 +1,3 @@ +export default function (interaction) { + interaction.reply("stop fucking interacting"); +} diff --git a/src/index.js b/src/index.js index 553bfec..e20dfcd 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import { GatewayIntentBits, Partials, Client } from "discord.js"; import events from "./events/importEvents.js"; +import register from "./register-commands.js"; const client = new Client({ intents: [ @@ -8,6 +9,7 @@ const client = new Client({ GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.DirectMessages, + GatewayIntentBits.GuildVoiceStates, ], partials: [Partials.Message, Partials.Channel], }); @@ -28,4 +30,10 @@ client.on("messageCreate", async (message) => { events.messageCreate(message, client); }); +client.on("interactionCreate", (interaction) => { + events.interactionCreate(interaction); +}); + +register(); + client.login(process.env.TOKEN); diff --git a/src/register-commands.js b/src/register-commands.js index 462e492..9d5deba 100644 --- a/src/register-commands.js +++ b/src/register-commands.js @@ -1,52 +1,48 @@ -require('dotenv').config(); -const { REST, Routes, ApplicationCommandOptionType } = require('discord.js'); +import dotenv from "dotenv"; +import fs from "fs"; +dotenv.config(); +import { + REST, + Routes, + ApplicationCommandOptionType, + SlashCommandBuilder, +} from "discord.js"; -export const commands = [ - { - name: 'say', - description: 'forces bot to say message', - options: [ - { - name: 'message', - description: 'the message', - type: ApplicationCommandOptionType.String, - required: true - } - ] - }, - { - name: 'administer', - description: 'administer.', - options: [ - { - name: 'password', - description: 'the protections.', - type: ApplicationCommandOptionType.String, - required: true - } - ] - }, - { - name: 'commands', - description: 'sends a command list', - }, - { - name: 'test', - description: 'test command', - }, -]; +let commands = []; -const rest = new REST({ version: '10' }).setToken(process.env.TOKEN); +const commandFiles = fs + .readdirSync("src/commands/") + .filter((file) => file.endsWith(".js")); -(async () => { - try { - await rest.put( - Routes.applicationGuildCommands(process.env.CLIENT_ID, process.env.GUILD_ID), - { body: commands } - ) - - console.log("slash commands registered") - } catch (error) { - console.log(error); +async () => { + for (const file of commandFiles) { + const command = await import(`./commands/${file}`); + commands.push( + ` + { + name: "${command.name}", + description: "${command.description}" } -})(); \ No newline at end of file + `.toJSON() + ); + } +}; +console.log(commands); + +const rest = new REST().setToken(process.env.TOKEN); + +export default async () => { + try { + await rest.put( + Routes.applicationGuildCommands( + process.env.CLIENT_ID, + process.env.GUILD_ID + ), + { body: commands } + ); + + console.log("slash commands registered"); + } catch (error) { + console.log(error); + } +};