AudioBot/index_old.js
2024-01-25 22:08:47 -05:00

312 lines
10 KiB
JavaScript

// This is the old version of the bot, written by DarkOK, and is kept here for archival purposes.
// It no longer works due to discord api changes, hence the rewrite.
const Discord = require('discord.js-v11'); // update this you lazy prick and rewrite the bot
const client = new Discord.Client();
const {execSync, exec, spawnSync, spawn} = require('child_process');
var token = ""; // token used for authentication to discord
var ownerIds = []; // user ids of people that can eval, change servers to non-whitelisted ones, etc
var pf = "cvm!"; // command prefix
var vncServers = [
"localhost:5900"
]; // servers that appears in the list, and ones that people don't need admin to switch to (first item in array is default server)
// (if this is public, keep this as the one (Hm i should really make all VMs use one broadcast for all servers to fix this))
// dont modify
var vncServer = vncServers[0];
var vncName = "";
// especially dont modify these
var arecord;
var broadcast;
var bp={txt:"",type:"",status:""};
function changeStatus(txt, type, status) {
bp.txt = txt;
bp.type = type ? type : "LISTENING";
bp.status = status ? status : "online";
if (bp.txt != txt || bp.type != type || bp.status != status) {
client.user.setPresence({
activity: {
name: pf + "help" + " | " + bp.txt,
type: bp.type
},
status: bp.status
});
}
};
function startStream() {
console.log("Connecting to " + vncServer);
changeStatus("Connecting");
exec("./name " + vncServer, (error, stdout, stderr) => {
if (error) {
//vncName = "Failed to get VM name";
console.log("Error getting VM name: " + error.message);
} else {
vncName = stdout;
console.log("VNC name: " + vncName);
changeStatus(vncName);
};
});
arecord = spawn('./audio', [vncServer]);
arecord.stderr.setEncoding("utf8");
arecord.stderr.on("data", data => {
console.log(data);
});
arecord.on("close", code => {
console.log("Audio process exited with " + code);
setTimeout(()=>{
startStream();
for (var a of client.voice.connections.values()) {
a.play(broadcast);
}
}, 2000);
});
broadcast = client.voice.createBroadcast();
broadcast.play(
arecord.stdout.on("data", data => {
return data;
}),
{
type: "converted",
volume: false,
highWaterMark: 1
}
);
};
client.login(token);
client.on("ready", ()=>{
console.log(`Logged in as: ${client.user.tag} (ID: ${client.user.id})`);
console.log(`Prefix is: ${pf}`);
console.log(`Currently in ${Array.from(client.guilds.cache.values()).length} servers\n`);
startStream();
});
client.on("error", async err => {
console.log("An error occurred: " + err.message);
});
// HURR NO GOOD COMMAND HANDLER HURR DURR
client.on("message", async message => {
if (!message.guild) return;
if (!message.member) return;
if (message.member.id == client.user.id) return;
// i could put it in the same one if i want to BUT I CANT BE BOTHERED
var args = message.content.split(' ');
var cmd = args.shift();
//console.log(`[Message] <${message.author.tag} in ${message.guild.name}> ${message.content}`);
if (cmd.startsWith(pf)) {
cmd = cmd.slice(pf.length).toLowerCase();
console.log(`[Command] <${message.author.tag} in #${message.channel.name}@${message.guild.name}> ${message.content}`);
switch (cmd) {
case "play":
case "join":
case "connect":
if (message.member.voice.channel) {
message.member.voice.channel.join().then(connection => {
connection.play(broadcast);
message.reply("joined");
}).catch(err =>{
message.reply("an error occurred while trying to join the voice channel: `" + err.message + '`');
console.log(err.message);
});
} else {
message.reply("join a voice channel");
};
break;
case "stop":
case "leave":
case "disconnect":
if (message.member.voice.channel) {
message.member.voice.channel.leave();
message.reply("left");
} else {
message.reply("join a voice channel so I know where to leave");
// i can probably make it not do it this way but Cannot Be Bothered
};
break;
case "eval":
if (ownerIds.includes(message.member.id)) {
try {
//console.log("Evaluating " + args.join(' '));
var evalOutput = eval(args.join(' '));
//var evalOutputChunks = evalOutput.match(/.{1,1950}/g);
message.reply("```\n" + evalOutput + "\n```");
//for (var i = 0; i < evalOutputChunks.length; i++) {
// message.channel.send(`Part ${i + 1} of ${evalOutputChunks.length}` + "```\n" + evalOutputChunks[i] + "\n```");
//}
console.log(evalOutput);
} catch (err) {
message.reply("fuck!\n```\n" + err.stack + "\n```");
}
} else {
message.reply("you need to be in the owner list");
};
break;
case "rs":
case "restartstream":
if (ownerIds.includes(message.member.id)) {
arecord.kill("SIGTERM");
console.log("Terminated the audio process");
message.reply("terminated the audio process");
} else {
message.reply("you need to be in the owner list");
};
break;
case "ss":
case "setserver":
// to do: maybe I could make it so each server can choose which VM in the list it plays audio from, instead of using the same broadcast
// (although maybe still use broadcasts for multiple connections to the same server, for optimisation, and less connections to the same server)
if (vncServers.includes(args[0]) || ownerIds.includes(message.member.id)) {
if (args[0] != undefined) {
vncServer = args[0];
arecord.kill("SIGTERM");
console.log("Set the VNC server to " + args[0] + " and terminated the audio process");
message.reply("set the VNC server to `" + args[0] + "` and terminated the audio process");
} else {
message.reply("specify a server you dumb fuck");
};
} else {
message.reply("you need to be in the owner list to connect to VNC servers not in the VNC server list (check `" + pf + "list`)");
// having the ability for anybody to connect to literally any host + tcp port maybe isn't a good idea
};
break;
case "cs":
case "currentserver":
if (ownerIds.includes(message.member.id)) {
message.reply(`\nIP: \`${vncServer}\`\nName: \`${vncName}\``);
} else {
message.reply("you need to be in the owner list");
};
break;
case "list":
var vmlist = "VM List:\n";
vncServers.forEach(server => {
var vmname = spawnSync("./name", [server], {timeout: 2000});
if (!vmname.status && vmname.stdout) {
vmlist += `\`${server}\` - **${vmname.stdout}**\n`;
} else {
vmlist += `\`${server}\` - Failed to get name\n`;
};
});
if (vmlist.length < 2000) message.reply(vmlist);
else message.reply("VM list is too big to fit in a message (oops!)");
break;
case "guilds":
if (ownerIds.includes(message.member.id)) {
let guildsOnEachPage = 10;
let guildsTmp = Array.from(client.guilds.cache.values());
let pageCount = Math.ceil(guildsTmp.length / guildsOnEachPage);
if (args[0] == "all") {
for (var i = 1; i <= pageCount; ++i) {
let guildList = `Guild list - __**Page ${i}/${pageCount}**__:\n`;
guildsTmp.slice((i * guildsOnEachPage) - guildsOnEachPage, (i * guildsOnEachPage)).forEach(guild => {
guildList += `**\`${guild.name}\`** - owned by ${guild.ownerID}, with ${guild.memberCount} users ${client.voice.connections.has(guild.id) ? `__**[Voice connected, ${Array.from(client.voice.connections.get(guild.id).channel.members).length} users]**__` : ""}\n`; // obese as shit holy FUCK
});
if (guildList.length < 2000) message.channel.send(guildList);
else message.reply("Guild list is too big to fit in a message (oops!)");
};
} else {
let page = isNaN(parseInt(args[0])) ? 1 : parseInt(args[0]);
let guildList = `Guild list - __**Page ${page}/${pageCount}**__:\n`;
guildsTmp.slice((page * guildsOnEachPage) - guildsOnEachPage, (page * guildsOnEachPage)).forEach(guild => {
guildList += `**\`${guild.name}\`** - owned by ${guild.ownerID}, with ${guild.memberCount} users ${client.voice.connections.has(guild.id) ? `__**[Voice connected, ${Array.from(client.voice.connections.get(guild.id).channel.members).length} users]**__` : ""}\n`; // obese as shit holy FUCK
});
if (guildList.length < 2000) message.channel.send(guildList);
else message.reply("Guild list is too big to fit in a message (oops!)");
};
} else {
message.reply("you need to be in the owner list");
};
break;
case "stats":
let uptimeSeconds = (client.uptime / 1000);
let botStats = "Bot stats:\n";
botStats += "**Server count**: " + Array.from(client.guilds.cache).length + '\n';
botStats += "**Voice connection count**: " + Array.from(client.voice.connections).length + '\n';
botStats += "**Bot uptime**: ";
botStats += Math.floor(uptimeSeconds / 86400) + " days, ";
uptimeSeconds %= 86400;
botStats += Math.floor(uptimeSeconds / 3600) + " hrs, ";
uptimeSeconds %= 3600;
botStats += Math.floor(uptimeSeconds / 60) + " mins, ";
botStats += Math.floor(uptimeSeconds % 60) + " secs\n";
botStats += "**Current VM name**: `" + vncName + "`\n";
if (botStats.length < 2000) message.reply(botStats);
else message.reply("stats are too big to fit in a message (oops!)");
// i should probably calculate how big the mention part is too, but this somewhat works for now
break;
case "about":
message.reply("this uses DarkOK's own QEMU_VNC_Audio->Discord bot");
break;
case "invite":
message.reply(`my invite URL is: https://discord.com/oauth2/authorize?client_id=${client.user.id}&permissions=36703232&scope=bot`);
break;
case "help":
message.reply(
"Command list:\n" +
`**${pf}join** - Join a voice channel\n` +
`**${pf}leave** - Leave a voice channel\n` +
`**${pf}invite** - Sends the invite URL for the bot\n` +
`**${pf}stats** - Display some statistics about the bot\n` +
'\n' +
"and that's about it\n" +
"sometimes audio just stops working, try making the bot leave and rejoin the voice channel to see if it solves the issue\n" +
"this bot is relatively unstable as of now, expect crashes/things not working\n\n" +
"contact? dark@darkok.xyz"
);
// really shitty but it's the best I can do since there's no proper command handler
break;
};
};
});
client.on("guildCreate", async guild => {
console.log(`[Server Joined] ${guild.name} - ${guild.memberCount} members, ID: ${guild.id}`);
});
client.on("guildDelete", async guild => {
console.log(`[Server Left] ${guild.name} - ${guild.memberCount} members, ID: ${guild.id}`);
});
process.on("unhandledRejection", async err => {
console.error("Unhandled promise rejection:", err);
});