bot/src/main.js

730 lines
19 KiB
JavaScript
Raw Normal View History

2023-04-22 14:29:35 +00:00
if ("ENV" in process.env) {
if(process.env.ENV == "TEST") {
process.exit(0)
}
}
2023-04-10 15:41:59 +00:00
2023-04-26 21:50:58 +00:00
const { error } = require("node:console")
const log = require("./sublog.js")
const { config } = require("node:process")
const { platform } = require("node:os")
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
function startDiscordBot() {
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
const { Client, GatewayIntentBits, Collection } = require("discord.js")
const { REST, Routes } = require("discord.js")
const fs = require("node:fs")
const config = require("./config.json")
const path = require("path")
const { Manager, TrackUtils } = require("erela.js")
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
const client = new Client({
intents:[GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers]
})
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
client.commands = new Collection()
client.dictator = false;
const commands = [];
// Grab all the command files from the commands directory you created earlier
const commandsPath = path.join(__dirname , 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.data.name, command)
commands.push(command.data.toJSON());
}
// Construct and prepare an instance of the REST module
const rest = new REST().setToken(config.token);
// and deploy your commands!
(async () => {
try {
log.bot(`Started refreshing ${commands.length} application (/) commands.`);
// The put method is used to fully refresh all commands in the guild with the current set
const data = await rest.put(
Routes.applicationGuildCommands(config.clientID, config.guildID),
{ body: commands },
);
log.bot(`Successfully reloaded ${data.length} application (/) commands.`);
} catch (error) {
// And of course, make sure you catch and log any errors!
log.bot.error(error);
}
})();
// Command Slash
// Client Event
client.once("ready", () => {
log.bot("Le meilleur groupe de musique est prêt !")
client.user.setActivity(`beaucoup de choses !`, { type: "LISTENING" })
client.manager.init(client.user.id);
const commandManager = client.application.commands;
if (!commandManager) {
log.bot('Command manager not available.');
} else {
commandManager.set([]);
}
})
client.on("voiceStateUpdate", (oldMember, newMember) => {
let player = client.manager.players.get(oldMember.guild.id)
if(player) {
client.channels.fetch(player.options.voiceChannel).then(channel => {
if(channel.members.size <= 1) {
player.destroy()
}
})
}
})
client.on("interactionCreate", (interaction) => {
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
if(!interaction.isCommand()) return;
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
const command = client.commands.get(interaction.commandName)
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
try {
log.bot(interaction.member.displayName + "-> /" + interaction.commandName)
command.execute(client, interaction)
} catch(error) {
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
interaction.reply({content:"Erreur lors de l'éxécution de la commande !", ephemeral: true})
}
})
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
const nodes = [
{
host: "lavalink.devamop.in",
password: "DevamOP",
port: 443,
secure: true
}
];
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
client.manager = new Manager({
// The nodes to connect to, optional if using default lavalink options
nodes,
// Method to send voice data to Discord
send: (id, payload) => {
const guild = client.guilds.cache.get(id);
// NOTE: FOR ERIS YOU NEED JSON.stringify() THE PAYLOAD
if (guild) guild.shard.send(payload);
}
});
// Emitted whenever a node connects
client.manager.on("nodeConnect", node => {
log.bot(`Node "${node.options.identifier}" connected.`)
})
// Emitted whenever a node encountered an error
client.manager.on("nodeError", (node, error) => {
log.bot(`Node "${node.options.identifier}" encountered an error: ${error.message}.`)
})
// THIS IS REQUIRED. Send raw events to Erela.js
client.on("raw", d => client.manager.updateVoiceState(d));
// Client Manager
startServer(client)
client.login(config.token)
}
function startServer(client) {
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
var cookieParser = require('cookie-parser')
const { Server } = require("socket.io");
const io = new Server(server);
const uuid = require("uuid")
const fs = require("fs")
const path = require("path")
2023-04-27 09:22:02 +00:00
var link = null
var discordlink = null
if(process.env.DEV == "true") {
log.server("DEV MOD ENABLED")
link = "http://localhost:4000" //DEV
discordlink = "https://discord.com/api/oauth2/authorize?client_id=1094727789682380922&redirect_uri=http%3A%2F%2Flocalhost%3A4000%2Fredirect&response_type=code&scope=guilds%20identify" //DEV
} else {
discordlink = "https://discord.com/api/oauth2/authorize?client_id=1094727789682380922&redirect_uri=https%3A%2F%2Fsubsonics.raphix.fr%2Fredirect&response_type=code&scope=identify%20guilds" //OFFICIEL
link = "https://subsonics.raphix.fr"
}
2023-04-26 21:50:58 +00:00
var authTokenWait = new Map()
var users = new Map()
var onlineNumber = 0;
const tokens = require(__dirname + path.sep + "tokens.json")
users = new Map()
for(var user in tokens) {
users.set(user , tokens[user])
2023-04-10 12:52:23 +00:00
}
2023-04-26 21:50:58 +00:00
app.use(cookieParser())
2023-04-22 14:52:19 +00:00
2023-04-26 21:50:58 +00:00
io.on('connection', (socket) => {
log.server("Nouvelle Connexion - Client : " + socket.id)
onlineNumber += 1
actualize()
2023-04-23 15:46:50 +00:00
2023-04-26 21:50:58 +00:00
socket.on('disconnect', () => {
log.server("Déconnexion - Client : " + socket.id);
onlineNumber -= 1
actualize()
});
2023-04-23 15:46:50 +00:00
2023-04-26 21:50:58 +00:00
socket.on("find", (token, value) => {
2023-04-23 15:46:50 +00:00
2023-04-26 21:50:58 +00:00
async function find() {
2023-04-22 14:52:19 +00:00
2023-04-26 21:50:58 +00:00
const searchList = await client.manager.search(value)
await socket.emit("findResult", searchList)
2023-04-23 15:46:50 +00:00
}
2023-04-26 21:50:58 +00:00
if(users.has(token)) {
log.server("Recherche avec les mots clés : " + value + " de musique de " + users.get(token).username + "#" + users.get(token).discriminator)
find()
}
2023-04-23 15:46:50 +00:00
})
2023-04-22 14:52:19 +00:00
2023-04-26 21:50:58 +00:00
socket.on("addQueue", (token, url) => {
async function play() {
if(users.has(token)) {
let player = client.manager.players.get("137291455336022018")
if(!player) {
player = client.manager.create({
guild: "137291455336022018",
voiceChannel: "664355808250953739",
textChannel: "664355808250953739",
});
player.connect();
}
const songtrack = await client.manager.search(url)
player.queue.add(songtrack.tracks[0])
log.server("Lecture / Ajout du titre : " + songtrack.tracks[0].title + " de musique de " + users.get(token).username + "#" + users.get(token).discriminator)
if(!player.playing) {
player.play()
}
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
}
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
actualize()
}
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
play()
})
socket.on("authNeedLogin", () => {
log.server("Discord Auth : Demande Token de " + socket.id)
const token = uuid.v4().toString()
authTokenWait.set(token, socket)
socket.emit("authOpenLink", link + "/" + token)
app.get("/" + token, (req, res) => {
res.cookie("authLoginFollow", token)
log.server("Discord Auth : Redirection vers le service Discord pour " + socket.id)
res.redirect(discordlink)
})
//socket.emit("authFailed")
})
socket.on("authByToken", (token) => {
var answer = false
if(users.has(token)) {
answer = true
log.server("Connexion au serveur par Token - SOCKET_ID : " + socket.id + " - DISCORD_USER : " + users.get(token).username + "#" + users.get(token).discriminator)
actualize()
}
socket.emit("authByTokenAnswer", answer, token)
})
socket.on("getState", (token) => {
actualize()
sendState(socket, token)
})
socket.on("play", (token) => {
if(users.has(token)) {
log.server("Mise en Play / Pause demandé par " + users.get(token).username + "#" + users.get(token).discriminator)
let player = client.manager.players.get("137291455336022018")
if(player && player.playing == true && player.paused == false) {
player.pause(true)
} else if(player && player.playing == false && player.paused == true) {
player.pause(false)
}
actualize()
} else {
socket.emit("authFailed")
}
})
process.on("discordDoing", () => {
log.server("Discord BOT - Doing an action need actualisation !")
actualize()
})
socket.on("listClear", (token) => {
if(users.has(token)) {
log.server("Clear liste demandé par " + users.get(token).username + "#" + users.get(token).discriminator)
let player = client.manager.players.get("137291455336022018")
if(player) {
player.queue.clear()
}
actualize()
} else {
socket.emit("authFailed")
}
})
socket.on("deleteQueue", (token, identifier) => {
if(users.has(token)) {
let player = client.manager.players.get("137291455336022018")
if(player) {
log.server("Supression (n°" + identifier + ") d'un morceau demandé par " + users.get(token).username + "#" + users.get(token).discriminator)
player.queue.remove(identifier)
}
actualize()
} else {
socket.emit("authFailed")
}
})
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
socket.on("backward", (token) => {
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
if(users.has(token)) {
log.server("Retour arrière demandé par " + users.get(token).username + "#" + users.get(token).discriminator)
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
let player = client.manager.players.get("137291455336022018")
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
if(player && player.queue.previous) {
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
player.play(player.queue.previous)
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
} else if(player && player.queue.current) {
player.play(player.queue.current)
}
actualize()
} else {
socket.emit("authFailed")
}
})
socket.on("forward", (token) => {
if(users.has(token)) {
log.server("Skip demandé par " + users.get(token).username + "#" + users.get(token).discriminator)
let player = client.manager.players.get("137291455336022018")
if(player && player.queue.length != 0) {
player.stop()
} else if(player && player.queue.current) {
player.play(player.queue.current)
}
actualize()
} else {
socket.emit("authFailed")
}
})
socket.on("exit", (token) => {
if(users.has(token)) {
log.server("Skip demandé par " + users.get(token).username + "#" + users.get(token).discriminator)
let player = client.manager.players.get("137291455336022018")
if(player) {
player.destroy()
}
actualize()
} else {
socket.emit("authFailed")
}
})
});
client.manager.on("playerCreate", () => {
log.server("Player : Player Created -> Actualize all client !")
actualize()
})
client.manager.on("playerDestroy", () => {
log.server("Player : Player Destroyed -> Actualize all client !")
actualize("end")
})
client.manager.on("trackStart", () => {
log.server("Player : New Track Start-> Actualize all client !")
actualize()
})
client.manager.on("queueEnd", () => {
log.server("Player : End Queue -> Actualize all client !")
actualize()
})
function actualize(action) {
let player = client.manager.players.get("137291455336022018")
const data = {
"onlineNumber":onlineNumber,
"playing": 0,
"current":null,
"isOnline": false,
"queue": null
}
if(player) {
data["current"] = player.queue.current
if(player.playing == true && player.paused == false) {
data["playing"] = 1
} else {
data["playing"] = 0
}
data["queue"] = player.queue;
if(player.playing == true) {
log.server("Musique : Musique actuelle : " + player.queue.current.title)
}
data["isOnline"] = true
}
log.server("Actualisation Client : Online Number : " + data.onlineNumber + " - PlayingState : " + data.playing + " - Current : " + data.current + " - Player : " + player)
if(action == "end") {
data["current"] = null;
data["isOnline"] = false
}
try {
io.sockets.emit("actualize", data)
} catch(error) {
log.server("ERROR OF ACT")
}
2023-04-10 12:52:23 +00:00
}
2023-04-26 21:50:58 +00:00
function sendState(socket, token) {
const data = {
"username":users.get(token).username + "#" + users.get(token).discriminator,
"avatar": users.get(token).avatar,
"id": users.get(token).id,
}
socket.emit("updateState", data)
2023-04-10 12:52:23 +00:00
}
2023-04-26 21:50:58 +00:00
app.get("/redirect", (req, res) => {
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
let token = req.cookies.authLoginFollow
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
if(token != null) {
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
if(authTokenWait.has(token) == true) {
const socket = authTokenWait.get(token)
2023-04-10 12:52:23 +00:00
2023-04-26 21:50:58 +00:00
const code = req.query.code
log.server("Discord Auth : Récupération du service Discord : Token de Connexion : " + token + " associé à Client ID : " + socket.id)
if(code) {
try {
log.server("Discord Auth : REQUESTING DATA - TOKEN : " + token + " - DISCORD_CODE : " + code)
const params = new URLSearchParams();
params.append('client_id', "1094727789682380922");
params.append('client_secret', "uwtyPOPKCgw6ciBs20qiJ7LJrW9Ziclo");
params.append('grant_type', 'authorization_code');
params.append('code', code);
2023-04-27 09:44:47 +00:00
params.append('redirect_uri', link + "/redirect");
2023-04-26 21:50:58 +00:00
params.append('scope', 'identify guild');
2023-04-23 15:46:50 +00:00
2023-04-26 21:50:58 +00:00
fetch('https://discord.com/api/oauth2/token', {
method: "POST",
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}, body : params
}).then(resp => resp.json()).then(resp => createIdentity(resp, token, socket)).catch(error => log.server.error(error))
2023-04-23 15:46:50 +00:00
2023-04-10 19:37:47 +00:00
2023-04-26 21:50:58 +00:00
res.clearCookie("authLoginFollow")
res.send("SubSonics Manager : Vous pouvez fermer cette fenêtre ! Si rien ne ce passe sur l'application, prévenez Raphix !")
2023-04-10 15:41:59 +00:00
2023-04-10 19:37:47 +00:00
2023-04-26 21:50:58 +00:00
} catch(error) {
2023-04-10 19:37:47 +00:00
2023-04-26 21:50:58 +00:00
console.log(error)
}
} else {
res.send("SubSonics Manager : ERREUR : DISCORD AUTH FAILED !")
}
} else {
res.send("SubSonics Manager : ERREUR : AUCUN TOKEN ENREGISTRÉ !")
}
} else {
res.send("SubSonics Manager : ERREUR : AUCUN TOKEN ENREGISTRÉ !")
}
})
function createIdentity(response, token, socket) {
2023-04-27 09:43:20 +00:00
console.log(response)
2023-04-26 21:50:58 +00:00
log.server("Discord Auth : REQUESTING DATA - TOKEN : " + token + " - DISCORD_ACCESS_TOKEN : " + response.access_token)
fetch('https://discord.com/api/users/@me', {
headers: {
authorization: `${response.token_type} ${response.access_token}`,
},
}).then(resp => resp.json()).then(resp => addIdentity(resp, token, socket)).catch(error => log.server.error(error))
2023-04-10 19:37:47 +00:00
}
2023-04-26 21:50:58 +00:00
function addIdentity(response, token, socket) {
2023-04-27 09:41:40 +00:00
2023-04-27 09:43:20 +00:00
console.log(response)
2023-04-26 21:50:58 +00:00
log.server("Discord Auth : [IDENTITE] : Nouvelle identité - SOCKET_ID : " + socket.id + " - DISCORD_USER : " + response.username + "#" + response.discriminator)
socket.emit("registerToken", token)
socket.emit("successLogin")
const tokens = require(__dirname + path.sep + "tokens.json")
tokens[token] = response
fs.writeFileSync(__dirname + path.sep + "tokens.json", JSON.stringify(tokens, null, 2))
users = new Map()
for(var user in tokens) {
users.set(user , tokens[user])
}
actualize()
authTokenWait.delete(token)
}
var port = 4000;
server.listen(port, () => {
log.server("Ecoute sur le PORT : " + port)
});
}
function handleFatalError(error) {
log.bot.error('Erreur fatale :', error);
console.log(error)
2023-04-11 20:26:27 +00:00
client = null
2023-04-26 21:50:58 +00:00
2023-04-11 20:26:27 +00:00
}
2023-04-10 15:41:59 +00:00
2023-04-11 20:26:27 +00:00
process.on('uncaughtException', handleFatalError);
2023-04-10 15:41:59 +00:00
2023-04-26 21:50:58 +00:00
startDiscordBot();