init commit (not really)

This commit is contained in:
Jill 2021-10-19 15:02:03 +00:00
parent b7697967fe
commit 1a61f89856
4 changed files with 4073 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
config.json

3762
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

21
package.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "foggy",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@discordjs/opus": "^0.5.3",
"@discordjs/voice": "^0.6.0",
"discord.js": "^13.2.0",
"ffmpeg-static": "^4.4.0",
"got": "^11.8.2",
"sodium": "^3.0.2",
"youtube-dl": "^3.5.0",
"youtube-dl-wrap": "^2.1.1"
}
}

288
src/index.js Normal file
View File

@ -0,0 +1,288 @@
// Require the necessary discord.js classes
const Discord = require('discord.js');
const Voice = require('@discordjs/voice');
const { token } = require('../config.json');
const { exec } = require('child_process');
const { promisify } = require('util');
const got = require('got');
const youtubedl = require('youtube-dl')
const bot = new Discord.Client({
intents: [
Discord.Intents.FLAGS.GUILDS,
Discord.Intents.FLAGS.GUILD_MESSAGES,
Discord.Intents.FLAGS.GUILD_VOICE_STATES,
Discord.Intents.FLAGS.GUILD_MESSAGE_REACTIONS
],
});
bot.once('ready', () => {
console.log('Ready!');
});
const prefix = ';';
const embedColor = 0xa0ffa5;
const foggyImg = 'https://cdn.discordapp.com/attachments/789023763396165633/898908687299657728/552bb191-93e3-4eaa-b935-d5031f3845e7.gif';
const ffprobeRegex = /Audio: ([^,\n]+), (\d+) ?Hz, ?([^,\n]+), ?([^,\n]+)(, ?([^,\n]+))?/;
async function checkVoiceChannel(msg) {
if (!msg.guild) return;
const clientVoiceState = msg.guild.me.voice;
const memberVoiceState = msg.member.voice;
const voiceConnection = await Voice.getVoiceConnection(msg.guild.id);
if (clientVoiceState.channelId === memberVoiceState.channelId && voiceConnection) {
console.log('reusing connection');
return voiceConnection;
}
if (!memberVoiceState.channelId) {
msg.channel.send('you aren\'t in a voice channel!');
return;
}
if (clientVoiceState.channelId && clientVoiceState.channelId !== memberVoiceState.channelId) {
msg.channel.send('you are in a different voice channel!');
return;
}
console.log('creating new connection');
return Voice.joinVoiceChannel({
channelId: msg.member.voice.channelId,
guildId: msg.guild.id,
adapterCreator: msg.guild.voiceAdapterCreator,
});
}
/*
{
url: string,
}
*/
let queue = {};
let players = {};
let playerStartTime = {};
function advanceQueue(id, channel, subscription, connection) {
if (queue[id][1]) {
const song = queue[id][1];
const embed = new Discord.MessageEmbed()
.setDescription(`now playing: **${song.titleFormat}**`)
.setThumbnail(song.thumbnail)
.setColor(embedColor)
.setAuthor('foggy ♫', foggyImg);
channel.send({embeds: [embed]});
play(queue[id][1], id, connection);
queue[id] = queue[id].slice(1);
} else {
channel.send('no songs left, leaving');
console.log('destroyig');
subscription.unsubscribe();
delete players[id];
connection.destroy();
queue[id] = [];
}
}
async function play(song, id, connection, channel) {
// const stream = ytdl(url, { filter: 'audioonly' });
let player;
let subscription;
let url = song.directUrl;
if (song.redownload) {
let err, out
try {
err, out = await promisify(exec)('youtube-dl -f bestaudio --youtube-skip-dash-manifest --force-ipv4 -g "' + song.originalUrl + '"');
} catch(err_) {
err = err_;
}
if (err) {
console.log(err);
channel.send(`failed to retrieve youtube-dl info!: \`\`\`${err}\`\`\``);
advanceQueue(id, channel, subscription, connection);
return;
}
url = out.stdout;
}
const stream = got(url, {isStream: true});
const resource = Voice.createAudioResource(stream, { inputType: Voice.StreamType.Arbitrary });
if (players[id]) {
console.log('reusing player');
player = players[id];
} else {
console.log('creating new player');
player = Voice.createAudioPlayer();
players[id] = player;
subscription = connection.subscribe(player);
player.on(Voice.AudioPlayerStatus.Idle, () => {
advanceQueue(id, channel, subscription, connection);
});
player.on(Voice.AudioPlayerStatus.Playing, () => {
playerStartTime[id] = Date.now();
})
}
player.play(resource);
return player;
}
function rawYTDLQueue(info) {
let song = {
originalUrl: info.webpage_url || url,
directUrl: info.url,
redownload: true,
title: info.title,
thumbnail: info.thumbnail,
titleFormat: info.title,
duration: info._duration_raw,
fileType: info.acodec,
bitrate: info.abr,
};
if (song.track && song.artist && song.album) {
song.titleFormat = `${song.artist} - [${song.track}](${info.webpage_url}) from ${song.album}`;
} else {
if (song.originalUrl.startsWith('http')) song.titleFormat = `[${song.title}](${song.originalUrl})`;
}
return song;
}
async function queueUp(url, id) {
if (!queue[id]) queue[id] = [];
let song = {};
let err, info;
try {
err, info = await promisify(youtubedl.getInfo)(url, ['--force-ipv4']);
} catch(err_) {
err = err_;
}
if (err) {
return [null, `failed to retrieve youtube-dl info!: \`\`\`${err}\`\`\``];
} else {
if (info.length) {
info.forEach(i => {
let song = rawYTDLQueue(i);
queue[id].push(song);
});
return [info.length, null];
} else {
song = rawYTDLQueue(info);
}
}
queue[id].push(song)
return [1, null];
}
bot.on('messageCreate', async (msg) => {
const content = msg.content;
const params = content.replace(prefix, '').split(' ');
const cmd = params[0];
if (!msg.guild) return;
if ((cmd === 'play' || cmd === 'p') && params[1]) {
const connection = await checkVoiceChannel(msg);
if (!connection) return;
const url = params.slice(1).join(" ");
console.log('queueing');
msg.channel.send('queueing...');
let [q, e] = await queueUp(url, msg.guild.id);
if (!q && e) [q, e] = await queueUp('ytsearch:' + url, msg.guild.id);
if (!q && e) return msg.channel.send(e);
const song = queue[msg.guild.id][queue[msg.guild.id].length - 1];
if (queue[msg.guild.id].length === 1) {
const embed = new Discord.MessageEmbed()
.setDescription(`now playing: **${song.titleFormat}**`)
.setThumbnail(song.thumbnail)
.setColor(embedColor)
.setAuthor('foggy ♫', foggyImg);
msg.channel.send({embeds: [embed]});
play(queue[msg.guild.id][0], msg.guild.id, connection, msg.channel);
} else {
let queueString = `queued: **${song.titleFormat}** _at position ${queue[msg.guild.id].length - 1}_`;
if (q > 1) queueString = `queued **${q} songs** _at positions ${queue[msg.guild.id].length - q} - ${queue[msg.guild.id].length - 1}_`;
const embed = new Discord.MessageEmbed()
.setDescription(queueString)
.setColor(embedColor)
.setAuthor('foggy ♫', foggyImg);
msg.channel.send({embeds: [embed]});
if (!players[msg.guild.id] || players[msg.guild.id].state === Voice.AudioPlayerStatus.Idle || players[msg.guild.id].state === Voice.AudioPlayerStatus.Paused) {
play(queue[msg.guild.id][0], msg.guild.id, connection, msg.channel);
}
}
} else if (cmd === 'skip' || cmd === 's') {
const player = players[msg.guild.id];
if (!player) return msg.channel.send('the bot isn\'t playing any music!');
const song = queue[msg.guild.id][0];
const embed = new Discord.MessageEmbed()
.setDescription(`skipped **${song.titleFormat}**`)
.setColor(embedColor)
.setAuthor('foggy ♫', foggyImg);
msg.channel.send({embeds: [embed]});
player.stop();
} else if (cmd === 'queue' || cmd === 'q') {
const q = queue[msg.guild.id] || [];
if (q.length === 0) {
msg.channel.send('no songs queued!');
} else {
msg.channel.send('```' + q.map((m, i) => `${i === 0 ? 'now playing:' : i + '.'} ${m.title}`).join('\n') + '```');
}
} else if (cmd === 'np' || cmd === 'nowplaying') {
const song = (queue[msg.guild.id] || [])[0];
if (!song) return msg.channel.send('no song playing!');
let progress = (Date.now() - (playerStartTime[msg.guild.id] || 0)) / 1000 / song.duration;
let progressLength = 20;
let progressStr = '';
if (song.duration === -1) {
progressStr = '🔘 `where?..`';
} else if (progress < 0 || progress > 1) {
progressStr = '🔘 `buffering,,`';
} else {
progressStr = `${'▬'.repeat(Math.floor(Math.abs(progress) * progressLength))}🔘${'▬'.repeat(Math.floor((1 - Math.abs(progress)) * progressLength))}`;
}
let embed = new Discord.MessageEmbed()
.setDescription(`now playing: **${song.titleFormat}**\n${progressStr}`)
.setFooter(`${song.fileType}${song.bitrate}KB/s`)
.setThumbnail(song.thumbnail)
.setColor(embedColor)
.setAuthor('foggy ♫', foggyImg);
if (queue[msg.guild.id].length !== 1) {
embed = embed.addField('up next', '```' + queue[msg.guild.id].slice(1, 5).map((m, i) => {
if (i === 3) {
return '...';
} else {
return `${i + 1}. ${m.title}`;
}
}).join('\n') + '```')
}
msg.channel.send({embeds: [embed]});
}
});
// Login to Discord with your bot's token
bot.login(token);