diff --git a/app.js b/app.js index db9ac23..79c0514 100755 --- a/app.js +++ b/app.js @@ -1,8 +1,8 @@ // PACKAGES -const fs = require('fs') const { Client, Collection, GatewayIntentBits, REST, Routes } = require('discord.js') -const { Player } = require('discord-player') const { YouTubeExtractor, SpotifyExtractor } = require('@discord-player/extractor') +const { Player } = require('discord-player') +const fs = require('fs') require('dotenv').config() @@ -10,7 +10,6 @@ require('dotenv').config() let intents = [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildVoiceStates] const client = new Client({ intents }) - // EVENTS HANDLING const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js')) for (file of eventFiles) { @@ -19,7 +18,6 @@ for (file of eventFiles) { else client.on(event.name, (...args) => { event.execute(...args) }) } - // COMMANDS HANDLING client.commands = new Collection() let commands = [] @@ -35,7 +33,6 @@ for (folder of commandFolders) { } } - // COMMANDS REGISTERING const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN); (async () => { @@ -43,7 +40,6 @@ const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN); catch (error) { console.error(error) } })() - // BUTTONS HANDLING client.buttons = new Collection() @@ -54,13 +50,11 @@ for (file of buttonFiles) { else console.log(`\u001b[1;35m [WARNING] The button ${file} is missing a required "id" or "execute" property.`) } - // PLAYER INITIALIZATION const player = new Player(client, { autoRegisterExtractor: false }) player.extractors.register(YouTubeExtractor) player.extractors.register(SpotifyExtractor) - // PLAYER EVENTS HANDLING const eventPlayerFiles = fs.readdirSync('./eventsPlayer').filter(file => file.endsWith('.js')) for (file of eventPlayerFiles) { @@ -69,6 +63,5 @@ for (file of eventPlayerFiles) { player.events.on(event.name, (...args) => event.execute(...args)) } - // LAUNCH client.login() \ No newline at end of file diff --git a/commands/global/amp.js b/commands/global/amp.js new file mode 100644 index 0000000..d65c592 --- /dev/null +++ b/commands/global/amp.js @@ -0,0 +1,96 @@ +const { SlashCommandBuilder } = require('discord.js') +require('dotenv').config() +require('require-all')(__dirname + '/../../utilsAMP') + +module.exports = { + data: new SlashCommandBuilder().setName('amp').setDescription('Accède à mon panel de jeu AMP !') + //.addSubcommand(subcommand => subcommand.setName('api_info').setDescription('Prints info about the API.')) + .addSubcommand(subcommand => subcommand.setName('login').setDescription("Connectez-vous avant d'effectuer une autre commande !") + .addStringOption(option => option.setName('username').setDescription("Nom d'Utilisateur").setRequired(true)) + .addStringOption(option => option.setName('password').setDescription('Mot de Passe').setRequired(true)) + .addBooleanOption(option => option.setName('remember').setDescription('Mémoriser les identifiants').setRequired(true)) + .addStringOption(option => option.setName('otp').setDescription('Code de double authentification'))) + .addSubcommandGroup(subcommandgroup => subcommandgroup.setName('instances').setDescription('Intéragir avec les instances AMP.') + .addSubcommand(subcommand => subcommand.setName('manage').setDescription('Gérer une instance.') + .addStringOption(option => option.setName('name').setDescription("Nom de l'instance").setRequired(true))) + .addSubcommand(subcommand => subcommand.setName('list').setDescription('Liste toutes les instances disponibles.')) + .addSubcommand(subcommand => subcommand.setName('restart').setDescription('Redémarre une instance.') + .addStringOption(option => option.setName('name').setDescription("Nom de l'instance").setRequired(true)))), + + async execute(interaction) { + const base_url = process.env.AMP_HOST + '/API' + + if (interaction.options.getSubcommand() == 'login') { + await interaction.deferReply({ ephemeral: true }) + + let result = await login(base_url, interaction.options) + //if (result) return await interaction.followUp({ content: `Sorry, something bad happened !` }) + //else return await interaction.followUp({ content: `You are successfully logged in as **${result}** !` }) + //await interaction.editReply(`You are successfully logged in as **${response.data.userInfo.Username}** !`) + if (result.status === 'success') return await interaction.editReply(`You are successfully logged in as **${result.data.userInfo.Username}** !`) + else if (result.status === 'fail') { + + return await interaction.editReply(`Sorry, something bad happened ! (${result.data.Message})`) + } + else if (result.status === 'error') { + return await interaction.editReply(`Sorry, there has been an error ! (${result.data.error_code})`) + } + } + /*else if (interaction.options.getSubcommand() == 'api_info') { + await interaction.deferReply() + let url = `${base_url}/Core/GetAPISpec` + let headers = { headers: { SESSIONID: localStorage.getItem("AMP_sessionID") } } + try { + let response = await axios.post(url, headers) + console.log(response.data) + await interaction.editReply('Ok !') + } catch (error) { console.log(error), await interaction.editReply("HTTP Error !") } + }*/ + else if (interaction.options.getSubcommandGroup() == 'instances') { + if (interaction.options.getSubcommand() == 'manage') { + await interaction.deferReply() + let friendlyName = interaction.options.getString('name') + let url = `${base_url}/ADSModule/GetInstances` + let headers = { SESSIONID: localStorage.getItem("AMP_sessionID") } + try { + let response = await axios.post(url, headers) + response.data.result[0].AvailableInstances.forEach(element => { + if (element.FriendlyName == friendlyName) { return instanceID = element.InstanceID } + }) + } catch (error) { console.log(error), await interaction.editReply("HTTP Error !") } + + if (!instanceID) { await interaction.editReply(`Aucune instance trouv�e au nom de ${friendlyName} !`) } + + url = `${base_url}/ADSModule/ManageInstance` + headers = { SESSIONID: localStorage.getItem("AMP_sessionID"), + InstanceId: instanceID } + try { + let response = await axios.post(url, headers) + console.log(response) + await interaction.editReply('Ok !') + } catch (error) { console.log(error), await interaction.editReply("HTTP Error !") } + } + else if (interaction.options.getSubcommand() == 'list') { + await interaction.deferReply() + let url = `${base_url}/ADSModule/GetInstances` + let headers = { SESSIONID: localStorage.getItem("AMP_sessionID") } + try { + let response = await axios.post(url, headers) + console.log(response.data.result[0].AvailableInstances) + await interaction.editReply('Ok !') + } catch (error) { console.log(error), await interaction.editReply("HTTP Error !") } + } + else if (interaction.options.getSubcommand() == 'restart') { + await interaction.deferReply() + let url = `${base_url}/ADSModule/RestartInstance` + let headers = { SESSIONID: localStorage.getItem("AMP_sessionID"), + InstanceName: interaction.options.getString('name') } + try { + let response = await axios.post(url, headers) + console.log(response.data) + await interaction.editReply('Ok !') + } catch (error) { console.log(error), await interaction.editReply("HTTP Error !") } + } + } + } +} \ No newline at end of file diff --git a/commands/global/crack.js b/commands/global/crack.js index d845f87..e3bf70a 100644 --- a/commands/global/crack.js +++ b/commands/global/crack.js @@ -1,13 +1,11 @@ const { SlashCommandBuilder } = require('discord.js') -const iconv = require('iconv-lite') -const axios = require('axios') const fs = require('fs') +require('require-all')(__dirname + '/../../utilsCrack') var headers1 = { "content-type": "application/x-www-form-urlencoded; charset=UTF-8", "x-requested-with": "XMLHttpRequest" } - var headers2 = { "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "accept-language": "fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7", @@ -26,89 +24,46 @@ var headers2 = { "Referrer-Policy": "strict-origin-when-cross-origin" } -async function search(query, headers) { - let body = await fetch("https://online-fix.me/engine/ajax/search.php", { headers, body: `query=${query}`, method: "POST" }) - .then(response => response.arrayBuffer()) - .then(arrayBuffer => { return iconv.decode(Buffer.from(arrayBuffer), 'win1251') }) - .catch(error => console.error(error)) - try { - let matches = body.split('')[1].split('')[0].split('') - let games = [] - matches.pop() - matches.forEach(async match => { - let name = match.split('">')[1].split('')[0].slice(0, -8) - let link = match.split('')[0] - games.push({ name, link }) - }) - return games - } catch (error) { - console.error(error) - await interaction.followUp({ content: `Y'a eu une erreur !\n${error.toString()}` }) - } -} - -async function repo(game, headers) { - let body = await fetch(game.link, { headers, body: null, method: "GET" }) - .then(response => response.arrayBuffer()) - .then(arrayBuffer => { return iconv.decode(Buffer.from(arrayBuffer), 'win1251') }) - .catch(error => console.error(error)) - try { - let name = body.split('https://uploads.online-fix.me:2053/torrents/')[1].split('"')[0] - let url = `https://uploads.online-fix.me:2053/torrents/${name}` - return url - } catch (error) { - console.error(error) - await interaction.followUp({ content: `Y'a eu une erreur !\n${error.toString()}` }) - } -} - -async function torrent(url, headers) { - let response = await fetch(url, { headers, body: null, method: "GET" }) - .catch(error => console.error(error)) - try { - let body = await response.text() - let file = body.split('')[0] - return file - } catch (error) { - console.error(error) - await interaction.followUp({ content: `Y'a eu une erreur !\n${error.toString()}` }) - } -} - -async function download(url, file, headers) { - let path = `./cracks/${file}` - let writer = fs.createWriteStream(path) - try { - await axios({ url: url + file, method: 'GET', responseType: 'stream', headers }).then(response => { - return new Promise((resolve, reject) => { - response.data.pipe(writer) - let error = null - writer.on('error', err => { - error = err - writer.close() - reject(err) - }) - writer.on('close', () => { if (!error) resolve(true) }) - }) - }).catch(error => console.error(error)) - return path - } catch (error) { - console.error(error) - await interaction.followUp({ content: `Y'a eu une erreur !\n${error.toString()}` }) - } -} - module.exports = { - data: new SlashCommandBuilder() .setName('crack') .setDescription('Télécharge un crack sur le site online-fix.me !') - .addStringOption(option => option.setName('jeu').setDescription('Quel jeu tu veux DL ?').setRequired(true)), + data: new SlashCommandBuilder().setName('crack').setDescription('Télécharge un crack sur le site online-fix.me !') + .addStringOption(option => option.setName('jeu').setDescription('Quel jeu tu veux DL ?').setRequired(true)), async execute(interaction) { await interaction.deferReply() + let query = interaction.options.getString('jeu') let games = await search(query, headers1) - let url = await repo(games[0], headers2) + + let game + if (games.length === 0) return await interaction.followUp({ content: `J'ai rien trouvé pour "${query}" !` }) + else if (games.length > 1) { + games = games.slice(0, 9) + let list = '' + for (let i = 0; i < games.length; i++) list += `\n${i + 1}. ${games[i].name} (${games[i].link})` + let message = await interaction.followUp({ content: `J'ai trouvé plusieurs jeux pour "${query}" ! ${list}` }) + + let emojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣'] + for (let i = 0; i < games.length; i++) await message.react(emojis[i]) + + // Wait for a reaction to be added by the interaction author. + const filter = (reaction, user) => { + return emojis.includes(reaction.emoji.name) && user.id === interaction.user.id + } + let collected = await message.awaitReactions({ filter, max: 1, time: 5000, errors: ['time'] }) + .catch(() => { return interaction.followUp({ content: 'T\'as mis trop de temps à choisir !' }) }) + console.log(collected) + if (!collected.first) return + let reaction = collected.first() + let index = emojis.indexOf(reaction.emoji.name) + game = games[index] + } + else game = games[0] + console.log(interaction.user.id) + + let url = await repo(game, headers2) let file = await torrent(url, headers2) let path = await download(url, file, headers2) + await interaction.followUp({ content: `Voici ce que j'ai trouvé pour "${query}" !`, files: [path] }) - await fs.unlink(path, (err) => { if (err) throw err }) + fs.unlink(path, (err) => { if (err) throw err }) } } \ No newline at end of file diff --git a/commands/music/player.js b/commands/music/player.js index 6f48a89..e8f61e8 100755 --- a/commands/music/player.js +++ b/commands/music/player.js @@ -1,5 +1,5 @@ const { SlashCommandBuilder } = require('discord.js') -const generatePlayer = require('../../utils/generatePlayer.js') +const generatePlayer = require('../../utilsPlayer/generate.js') module.exports = { data: new SlashCommandBuilder() diff --git a/events/interactionCreate.js b/events/interactionCreate.js index 3ca898d..8864207 100755 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -1,6 +1,6 @@ const { Events } = require('discord.js') -const editPlayer = require('../utils/editPlayer.js') -const playerButtons = require('../utils/playerButtons.js') +const editPlayer = require('../utilsPlayer/edit.js') +const playerButtons = require('../utilsPlayer/buttons.js') module.exports = { name: Events.InteractionCreate, diff --git a/events/ready.js b/events/ready.js index e111828..213246f 100755 --- a/events/ready.js +++ b/events/ready.js @@ -1,7 +1,7 @@ const { Events } = require('discord.js') //const { DataTypes } = require("sequelize") //const sequelize = require('../utils/initSequelize.js') -const generatePlayer = require('../utils/generatePlayer.js') +const generatePlayer = require('../utilsPlayer/generate.js') const getUptime = require('../utils/getUptime.js') require('dotenv').config() diff --git a/package-lock.json b/package-lock.json index 0d581c2..74d247a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "opusscript": "^0.0.8", "play-dl": "^1.9.6", "prism-media": "^1.3.5", + "require-all": "^3.0.0", "sequelize": "^6.31.1", "sqlite3": "^5.1.6", "utf-8-validate": "^6.0.3" @@ -2803,6 +2804,14 @@ "node": ">=8.10.0" } }, + "node_modules/require-all": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/require-all/-/require-all-3.0.0.tgz", + "integrity": "sha512-jPGN876lc5exWYrMcgZSd7U42P0PmVQzxnQB13fCSzmyGnqQWW4WUz5DosZ/qe24hz+5o9lSvW2epBNZ1xa6Fw==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", diff --git a/package.json b/package.json index c847e70..1ea1519 100755 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "opusscript": "^0.0.8", "play-dl": "^1.9.6", "prism-media": "^1.3.5", + "require-all": "^3.0.0", "sequelize": "^6.31.1", "sqlite3": "^5.1.6", "utf-8-validate": "^6.0.3" diff --git a/utils/writeEnv.js b/utils/writeEnv.js new file mode 100644 index 0000000..47a5cc6 --- /dev/null +++ b/utils/writeEnv.js @@ -0,0 +1,7 @@ +const fs = require('fs') + +module.exports = writeEnv = ((variable, value) => { + let parsedFile = fs.readFileSync('./.env', 'utf8') + parsedFile = parsedFile.replace(new RegExp(`${variable} = .*`, 'g'), `${variable} = ${value}`) + fs.writeFileSync('./.env', parsedFile) +}) \ No newline at end of file diff --git a/utilsAMP/login.js b/utilsAMP/login.js new file mode 100644 index 0000000..80f666e --- /dev/null +++ b/utilsAMP/login.js @@ -0,0 +1,22 @@ +const axios = require('axios') +const writeEnv = require('../utils/writeEnv') + +module.exports = login = (async (url, options) => { + return await axios.post(`${url}/Core/Login`, { + username: options.getString('username'), + password: options.getString('password'), + token: options.getString('otp') || '', + rememberMe: options.getBoolean('remember') + }).then(response => { + console.log(response.data) + if (!response.data.success) return { status: 'fail', data: response.data } + + writeEnv('AMP_SESSIONID', response.data.sessionID) + if (options.getBoolean('remember')) writeEnv('AMP_REMEMBER_TOKEN', response.data.rememberMeToken) + + return { status: 'success', data: response.data } + }).catch(error => { + console.error(error) + return { status: 'error', data: error } + }) +}) \ No newline at end of file diff --git a/utilsCrack/download.js b/utilsCrack/download.js new file mode 100644 index 0000000..5830bf7 --- /dev/null +++ b/utilsCrack/download.js @@ -0,0 +1,18 @@ +const axios = require('axios') +const fs = require('fs') + +module.exports = download = (async (url, file, headers) => { + let path = `./cracks/${file}` + let writer = fs.createWriteStream(path) + try { + await axios({ url: url + file, method: 'GET', responseType: 'stream', headers }).then(response => { + return new Promise((resolve, reject) => { + response.data.pipe(writer) + let error = null + writer.on('error', err => { error = err; writer.close(); reject(err) }) + writer.on('close', () => { if (!error) resolve(true) }) + }) + }).catch(console.error) + return path + } catch (error) { console.error(error) } +}) \ No newline at end of file diff --git a/utilsCrack/repo.js b/utilsCrack/repo.js new file mode 100644 index 0000000..8be882d --- /dev/null +++ b/utilsCrack/repo.js @@ -0,0 +1,13 @@ +const iconv = require('iconv-lite') + +module.exports = repo = (async (game, headers) => { + let body = await fetch(game.link, { headers, body: null, method: "GET" }) + .then(response => response.arrayBuffer()) + .then(arrayBuffer => { return iconv.decode(Buffer.from(arrayBuffer), 'win1251') }) + .catch(console.error) + try { + let name = body.split('https://uploads.online-fix.me:2053/torrents/')[1].split('"')[0] + let url = `https://uploads.online-fix.me:2053/torrents/${name}` + return url + } catch (error) { console.error(error) } +}) \ No newline at end of file diff --git a/utilsCrack/search.js b/utilsCrack/search.js new file mode 100644 index 0000000..90c7e95 --- /dev/null +++ b/utilsCrack/search.js @@ -0,0 +1,19 @@ +const iconv = require('iconv-lite') + +module.exports = search = (async (query, headers) => { + let body = await fetch("https://online-fix.me/engine/ajax/search.php", { headers, body: `query=${query}`, method: "POST" }) + .then(response => response.arrayBuffer()) + .then(arrayBuffer => { return iconv.decode(Buffer.from(arrayBuffer), 'win1251') }) + .catch(console.error) + try { + let matches = body.split('')[1].split('')[0].split('') + let games = [] + matches.pop() + matches.forEach(async match => { + let name = match.split('">')[1].split('')[0].slice(0, -8) + let link = match.split('')[0] + games.push({ name, link }) + }) + return games + } catch (error) { console.error(error) } +}) \ No newline at end of file diff --git a/utilsCrack/torrent.js b/utilsCrack/torrent.js new file mode 100644 index 0000000..e6644d1 --- /dev/null +++ b/utilsCrack/torrent.js @@ -0,0 +1,8 @@ +module.exports = torrent = (async (url, headers) => { + let response = await fetch(url, { headers, body: null, method: "GET" }).catch(console.error) + try { + let body = await response.text() + let file = body.split('')[0] + return file + } catch (error) { console.error(error) } +}) \ No newline at end of file diff --git a/utils/playerButtons.js b/utilsPlayer/buttons.js similarity index 100% rename from utils/playerButtons.js rename to utilsPlayer/buttons.js diff --git a/utils/editPlayer.js b/utilsPlayer/edit.js similarity index 100% rename from utils/editPlayer.js rename to utilsPlayer/edit.js diff --git a/utils/generatePlayer.js b/utilsPlayer/generate.js similarity index 100% rename from utils/generatePlayer.js rename to utilsPlayer/generate.js