Init WIP Bot

This commit is contained in:
Logan Cusano
2022-12-11 06:09:25 -05:00
parent f1f4cb7750
commit 4e1b82c557
43 changed files with 6766 additions and 0 deletions

69
Client/discord-bot/app.js Normal file
View File

@@ -0,0 +1,69 @@
//Config
import { getTOKEN, getGuildID, getApplicationID } from './utilities/configHandler.js';
// Commands
import ping from './controllers/ping.js';
import { join, leave } from './controllers/voiceController.js';
// Debug
import Debug from 'debug';
const debug = Debug("bot:app");
// Modules
import { Client, GatewayIntentBits } from 'discord.js';
// Utilities
import registerCommands from './utilities/registerCommands.js';
// Create the Discord client
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildVoiceStates
]
});
// When the client is connected and ready
client.on('ready', () =>{
debug(`${client.user.tag} is ready`)
console.log(`${client.user.tag} is ready`)
});
/*
* Saved For later
client.on('messageCreate', (message) => {
debug(`Message Sent by: ${message.author.tag}\n\t'${message.content}'`);
console.log(`Message Sent by: ${message.author.tag}\n\t'${message.content}'`);
});
*/
// When a command is sent
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand()){
switch (interaction.commandName) {
case "ping":
ping(interaction);
break;
case "join":
join(interaction);
break;
case "leave":
leave(interaction);
break;
default:
interaction.reply({ content: 'Command not found, try one that exists', fetchReply: true })
.then((message) => console.log(`Reply sent with content ${message.content}`))
.catch(console.error);
}
}
})
function loginBot(){
client.login(getTOKEN());
}
function main(){
registerCommands(() => {
loginBot();
});
}
main();

View File

@@ -0,0 +1,7 @@
{
"TOKEN": "OTQzNzQyMDQwMjU1MTE1MzA0.Yg3eRA.ZxEbRr55xahjfaUmPY8pmS-RHTY",
"ApplicationID": "943742040255115304",
"GuildID": "367396189529833472",
"DeviceID": "25",
"DeviceName": "VoiceMeeter Aux Output (VB-Audio VoiceMeeter AUX VAIO)"
}

View File

@@ -0,0 +1,37 @@
// Config
import { getDeviceID, getDeviceName } from '../utilities/configHandler.js'
// Modules
import portAudio from 'naudiodon';
import {createAudioResource} from "@discordjs/voice";
export function getAudioDevice({deviceName = undefined, deviceId = undefined}){
const deviceList = getAudioDevices();
if (!deviceName && !deviceId) throw new Error("No device given");
if (deviceName) return deviceList.find(device => device.name === deviceName);
if (deviceId) return deviceList.find(device => device.id === deviceId);
}
export function getAudioDevices(){
const deviceList = portAudio.getDevices();
console.log("Devices:", deviceList);
return deviceList;
}
export function createAudioInstance() {
//const resource = createAudioResource();
const selectedDevice = getAudioDevice({deviceId: getDeviceID()});//{deviceName: "VoiceMeeter VAIO3 Output (VB-Au"});
console.log(selectedDevice);
// Create an instance of AudioIO with outOptions (defaults are as below), which will return a WritableStream
const audioInstance = new portAudio.AudioIO({
inOptions: {
channelCount: 2,
sampleFormat: portAudio.SampleFormat16Bit,
sampleRate: 44100,
deviceId: selectedDevice.id, // Use -1 or omit the deviceId to select the default device
closeOnError: false, // Close the stream if an audio error is detected, if set false then just log the error
framesPerBuffer: 0 // 44100 / 1000 * 120 / 2 // Get 120ms of audio
}
});
//audioInstance.start();
return audioInstance;
}

View File

@@ -0,0 +1,6 @@
// Utilities
import { replyToInteraction } from '../utilities/messageHandler.js';
export default function ping(interaction) {
return replyToInteraction(interaction, "Pong! I have Aids and now you do too!");
}

View File

@@ -0,0 +1,62 @@
// Modules
import {
joinVoiceChannel,
getVoiceConnection,
createAudioResource,
createAudioPlayer,
NoSubscriberBehavior, StreamType
} from '@discordjs/voice';
import OpusEncoderPkg from "@discordjs/opus";
const { OpusEncoder } = OpusEncoderPkg;
// Utilities
import { replyToInteraction } from '../utilities/messageHandler.js';
import { createAudioInstance } from "./audioController.js";
/**
* Join the specified voice channel
*
* @param interaction Message interaction from discord
*/
export function join(interaction){
const voiceChannel = interaction.options.getChannel('voicechannel');
const voiceConnection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guildId,
adapterCreator: interaction.guild.voiceAdapterCreator,
selfMute: false,
selfDeaf: false,
});
replyToInteraction(interaction, `Ok, Joining ${voiceChannel.name}`);
// Declare the encoder
const encoder = new OpusEncoder(44100, 2);
const player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Play,
},
});
const audioInstance = createAudioInstance();
const audioResource = createAudioResource(audioInstance, { inputType: StreamType.Raw });
audioInstance.start();
//audioInstance.on('data', buffer => {
// Do on buffer event
//})
player.play(audioResource);
voiceConnection.subscribe(player);
}
/**
* If in a voice channel for the specified guild, leave
*
* @param interaction Message interaction from discord
*/
export function leave(interaction){
const guildId = interaction.guild.id;
const voiceConnection = getVoiceConnection(guildId);
if (!voiceConnection) return replyToInteraction(interaction, "Not in a voice channel.");
voiceConnection.destroy();
return replyToInteraction(interaction, `Goodbye`);
}

2907
Client/discord-bot/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
{
"name": "discord-bot",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@discordjs/builders": "^1.4.0",
"@discordjs/opus": "^0.9.0",
"@discordjs/rest": "^1.4.0",
"@discordjs/voice": "^0.14.0",
"@mapbox/node-pre-gyp": "^1.0.10",
"debug": "^4.3.4",
"discord.js": "^14.7.1",
"naudiodon": "^2.3.6",
"node-gyp": "^9.3.0",
"libsodium-wrappers": "^0.7.10"
},
"type": "module"
}

View File

@@ -0,0 +1,36 @@
import { readFileSync } from 'fs';
export function getConfig() {
return JSON.parse(readFileSync("./config/botConfig.json"));
}
export function getTOKEN() {
const parsedJSON = getConfig();
return parsedJSON.TOKEN;
}
export function getGuildID() {
const parsedJSON = getConfig();
parsedJSON.GuildID = BigInt(parsedJSON.GuildID);
//console.log("Guild ID: ", parsedJSON.GuildID);
return parsedJSON.GuildID;
}
export function getApplicationID() {
const parsedJSON = getConfig();
parsedJSON.ApplicationID = BigInt(parsedJSON.ApplicationID);
//console.log("Application ID: ", parsedJSON.ApplicationID);
return parsedJSON.ApplicationID;
}
export function getDeviceID(){
const parsedJSON = getConfig();
//console.log("Device ID: ", parseInt(parsedJSON.DeviceID));
return parseInt(parsedJSON.DeviceID);
}
export function getDeviceName(){
const parsedJSON = getConfig();
//console.log("Device Name: ", parseInt(parsedJSON.DeviceName));
return parsedJSON.DeviceName;
}

View File

@@ -0,0 +1,5 @@
export function replyToInteraction(interaction, message){
interaction.reply({ content: message, fetchReply: true })
.then((message) => console.log(`Reply sent with content ${message.content}`))
.catch(console.error);
}

View File

@@ -0,0 +1,45 @@
import {SlashCommandBuilder} from "@discordjs/builders";
import {REST} from "@discordjs/rest";
import {getApplicationID, getGuildID, getTOKEN} from "./configHandler.js";
import { Routes, ChannelType } from "discord.js";
const pingCommand = new SlashCommandBuilder()
.setName("ping")
.setDescription("Confirm the bot is online")
.toJSON();
const joinCommand = new SlashCommandBuilder()
.setName('join')
.setDescription('Joins a voice channel')
.addChannelOption((option) => option
.setName('voicechannel')
.setDescription('The Channel to voiceController')
.setRequired(false)
.addChannelTypes(ChannelType.GuildVoice))
.toJSON();
const leaveCommand = new SlashCommandBuilder()
.setName("leave")
.setDescription("Leave current voice channel")
.toJSON();
export default async function registerCommands(callback){
const commands = [
pingCommand,
joinCommand,
leaveCommand
];
try {
const rest = new REST({ version: '10' }).setToken(getTOKEN());
const clientID = getApplicationID();
const guildID = getGuildID();
await rest.put(Routes.applicationGuildCommands(clientID, guildID), {
body: commands,
});
callback();
} catch (err) {
console.log(err);
}
}