Réécriture complète en Typescript

This commit is contained in:
Angels-dev committed 2024-01-14 22:53:06 +01:00
1 parent 6ffa521888
commit 07d54abdba
108 files changed
+2477 -1943

No files matched your search

Regular → Executable
+6 -8
View File
@@ -1,9 +1,7 @@
**/.dockerignore
**/.git
**/.gitattributes
**/.gitignore
**/.vscode
**/docker-compose*
**/Dockerfile*
**/node_modules
.dockerignore
.git
.gitignore
.vscode
Dockerfile
node_modules
README.md
-9
View File
@@ -1,9 +0,0 @@
{
"parserOptions": {
"ecmaVersion": "latest"
},
"env": {
"es6": true
}
}
-63
View File
@@ -1,63 +0,0 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
Regular → Executable
+3 -3
View File
@@ -1,4 +1,4 @@
node_modules/
.env
cracks/
stronger_shorter.mp3
public/cracks/
dist/
.env*
-167
View File
@@ -1,167 +0,0 @@
;;;;
; npm projectconfig file: C:\Users\Zachary\source\repos\Discord\.npmrc
; this is a simple ini-formatted file
; lines that start with semi-colons are comments
; run `npm help 7 config` for documentation of the various options
;
; Configs like `@scope:registry` map a scope to a given registry url.
;
; Configs like `//<hostname>/:_authToken` are auth that is restricted
; to the registry host specified.
;;;;
; all available options shown below with default values
;;;;
; _auth=null
; access=null
; all=false
; allow-same-version=false
; also=null
; audit=true
; audit-level=null
; auth-type=web
; before=null
; bin-links=true
; browser=null
; ca=null
; cache=C:\Users\Zachary\AppData\Local/npm-cache
; cache-max=null
; cache-min=0
; cafile=null
; call=
; cert=null
; ci-name=null
; cidr=null
; color=true
; commit-hooks=true
; depth=null
; description=true
; dev=false
;
; diff-ignore-all-space=false
; diff-name-only=false
; diff-no-prefix=false
; diff-dst-prefix=b/
; diff-src-prefix=a/
; diff-text=false
; diff-unified=3
; dry-run=false
; editor=C:\Windows\notepad.exe
; engine-strict=false
; fetch-retries=2
; fetch-retry-factor=10
; fetch-retry-maxtimeout=60000
; fetch-retry-mintimeout=10000
; fetch-timeout=300000
; force=false
; foreground-scripts=false
; format-package-lock=true
; fund=true
; git=git
; git-tag-version=true
; global=false
; globalconfig=
; global-style=false
; heading=npm
; https-proxy=null
; if-present=false
; ignore-scripts=false
;
; include-staged=false
; include-workspace-root=false
; init-author-email=
; init-author-name=
; init-author-url=
; init-license=ISC
; init-module=~/.npm-init.js
; init-version=1.0.0
; init.author.email=
; init.author.name=
; init.author.url=
; init.license=ISC
; init.module=~/.npm-init.js
; init.version=1.0.0
; install-links=true
; install-strategy=hoisted
; json=false
; key=null
; legacy-bundling=false
; legacy-peer-deps=false
; link=false
; local-address=null
; location=user
; lockfile-version=null
; loglevel=notice
; logs-dir=null
; logs-max=10
; long=false
; maxsockets=15
; message=%s
; node-options=null
; noproxy=
; offline=false
;
; omit-lockfile-registry-resolved=false
; only=null
; optional=null
; otp=null
;
; package-lock=true
; package-lock-only=false
; pack-destination=.
; parseable=false
; prefer-offline=false
; prefer-online=false
; prefix=
; preid=
; production=null
; progress=true
; proxy=null
; read-only=false
; rebuild-bundle=true
; registry=https://registry.npmjs.org/
; replace-registry-host=npmjs
; save=true
; save-bundle=false
; save-dev=false
; save-exact=false
; save-optional=false
; save-peer=false
; save-prefix=^
; save-prod=false
; scope=
; script-shell=null
; searchexclude=
; searchlimit=20
; searchopts=
; searchstaleness=900
; shell=C:\Windows\system32\cmd.exe
; shrinkwrap=true
; sign-git-commit=false
; sign-git-tag=false
; strict-peer-deps=false
; strict-ssl=true
; tag=latest
; tag-version-prefix=v
; timing=false
; tmp=C:\Users\Zachary\AppData\Local\Temp
; umask=0
; unicode=false
; update-notifier=true
; usage=false
; user-agent=npm/{npm-version} node/{node-version} {platform} {arch} workspaces/{workspaces} {ci}
; userconfig=~/.npmrc
; version=false
; versions=false
; viewer=browser
; which=null
;
; workspaces=null
; workspaces-update=true
; yes=null
msvs_version=2022
Vendored Regular → Executable
+33 -10
View File
@@ -7,20 +7,43 @@
{
"type": "node",
"request": "launch",
"name": "Launch",
"program": "${workspaceFolder}/app.js",
"skipFiles": [
"<node_internals>/**"
]
"name": "Nodemon",
"skipFiles": ["<node_internals>/**"],
"runtimeExecutable": "nodemon",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"restart": true
},
{
"type": "node",
"request": "launch",
"name": "Nodemon",
"program": "${workspaceFolder}/app.js",
"skipFiles": [
"<node_internals>/**"
],
"name": "Nodemon Tamiseur",
"args": ["-r", "dotenv/config", "${workspaceFolder}/src/index.ts", "dotenv_config_path=${workspaceFolder}/.env1"],
"skipFiles": ["<node_internals>/**"],
"runtimeExecutable": "nodemon",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"restart": true
},
{
"type": "node",
"request": "launch",
"name": "Nodemon Groove",
"args": ["-r", "dotenv/config", "${workspaceFolder}/src/index.ts", "dotenv_config_path=${workspaceFolder}/.env2"],
"skipFiles": ["<node_internals>/**"],
"runtimeExecutable": "nodemon",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"restart": true
},
{
"type": "node",
"request": "launch",
"name": "Nodemon Funky",
"args": ["-r", "dotenv/config", "${workspaceFolder}/src/index.ts", "dotenv_config_path=${workspaceFolder}/.env3"],
"skipFiles": ["<node_internals>/**"],
"runtimeExecutable": "nodemon",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
Vendored Executable
+3
View File
@@ -0,0 +1,3 @@
{
"docker.commands.build": "${containerCommand} build --rm -f \"${dockerfile}\" --target tamiseur -t bot_tamiseur:tamiseur \"${context}\" && ${containerCommand} build --rm -f \"${dockerfile}\" --target funky -t bot_tamiseur:funky \"${context}\" && ${containerCommand} build --rm -f \"${dockerfile}\" --target groove -t bot_tamiseur:groove \"${context}\"",
}
-28
View File
@@ -1,28 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "docker-build",
"label": "Build Node Image",
"platform": "node",
"dockerBuild": {
"dockerfile": "${workspaceFolder}/Dockerfile",
"context": "${workspaceFolder}",
"pull": true
}
},
{
"type": "docker-run",
"label": "Run Node Image",
"platform": "node",
"dockerRun": {
"containerName": "BotDiscord-Tamiseur",
"restart": "always",
"network": "host"
},
"dependsOn": [
"docker-build"
]
}
]
}
Regular → Executable
+20 -3
View File
@@ -1,11 +1,28 @@
FROM node:latest
FROM node:alpine as base
ENV NODE_ENV=production
WORKDIR /usr/src/app
COPY ["package.json", "package-lock.json*", "./"]
RUN apt-get update
RUN apt-get -y install ffmpeg
RUN apk add --no-cache ffmpeg python3 make g++
RUN npm install --production --verbose && mv node_modules ../
COPY . .
RUN chown -R node /usr/src/app
USER node
FROM base as tamiseur
RUN mv .env1 .env
RUN rm .env2 .env3
CMD ["npm", "start"]
FROM base as funky
RUN mv .env2 .env
RUN rm .env1 .env3
CMD ["npm", "start"]
FROM base as groove
RUN mv .env3 .env
RUN rm .env1 .env2
CMD ["npm", "start"]
-67
View File
@@ -1,67 +0,0 @@
// PACKAGES
const { Client, Collection, GatewayIntentBits, REST, Routes } = require('discord.js')
const { YouTubeExtractor, SpotifyExtractor } = require('@discord-player/extractor')
const { Player } = require('discord-player')
const fs = require('fs')
require('dotenv').config()
// CLIENT INITIALIZATION
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) {
let event = require(`./events/${file}`)
if (event.once) client.once(event.name, (...args) => { event.execute(...args) })
else client.on(event.name, (...args) => { event.execute(...args) })
}
// COMMANDS HANDLING
client.commands = new Collection()
let commands = []
const commandFolders = fs.readdirSync('./commands')
for (folder of commandFolders) {
let folderPath = `./commands/${folder}`
let commandFiles = fs.readdirSync(folderPath).filter(file => file.endsWith('.js'))
for (file of commandFiles) {
let command = require(`${folderPath}/${file}`)
if ('data' in command && 'execute' in command) { commands.push(command.data.toJSON()); client.commands.set(command.data.name, command) }
else console.log(`\u001b[1;35m [WARNING] The command at ${`${folderPath}/${file}`} is missing a required "data" or "execute" property.`)
}
}
// COMMANDS REGISTERING
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
(async () => {
try { await rest.put(Routes.applicationCommands(process.env.DISCORD_APP_ID), { body: commands }) }
catch (error) { console.error(error) }
})()
// BUTTONS HANDLING
client.buttons = new Collection()
const buttonFiles = fs.readdirSync('./buttons').filter(file => file.endsWith('.js'))
for (file of buttonFiles) {
let button = require(`./buttons/${file}`)
if ('id' in button && 'execute' in button) client.buttons.set(button.id, button)
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) {
let event = require(`./eventsPlayer/${file}`)
if (['debug'].includes(event.name)) continue
player.events.on(event.name, (...args) => event.execute(...args))
}
// LAUNCH
client.login()
-10
View File
@@ -1,10 +0,0 @@
const { useQueue } = require('discord-player')
module.exports = {
id: 'pause',
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
await queue.node.setPaused(!queue.node.isPaused())
return interaction.followUp({ content: 'Musique mise en pause !', ephemeral: true })
}
}
-10
View File
@@ -1,10 +0,0 @@
const { useHistory } = require('discord-player')
module.exports = {
id: 'previous',
async execute(interaction) {
let history = useHistory(interaction.guild.id)
await history.previous()
return interaction.followUp({ content: 'Musique précédente jouée !', ephemeral: true })
}
}
-10
View File
@@ -1,10 +0,0 @@
const { useQueue } = require('discord-player')
module.exports = {
id: 'resume',
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
await queue.node.setPaused(!queue.node.isPaused())
return interaction.followUp({ content: 'Musique reprise !', ephemeral: true })
}
}
-10
View File
@@ -1,10 +0,0 @@
const { useQueue } = require('discord-player')
module.exports = {
id: 'shuffle',
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
await queue.tracks.shuffle()
return interaction.followUp({ content: 'File d\'attente mélangée !', ephemeral: true })
}
}
-10
View File
@@ -1,10 +0,0 @@
const { useQueue } = require('discord-player')
module.exports = {
id: 'skip',
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
await queue.node.skip()
return interaction.followUp({ content: 'Musique passée !', ephemeral: true })
}
}
-10
View File
@@ -1,10 +0,0 @@
const { useQueue } = require('discord-player')
module.exports = {
id: 'stop',
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
await queue.delete()
return interaction.followUp({ content: 'Musique arrêtée !', ephemeral: true })
}
}
-11
View File
@@ -1,11 +0,0 @@
const { useQueue } = require('discord-player')
module.exports = {
id: 'volume_down',
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
let volume = queue.node.volume - 10
await queue.node.setVolume(volume)
return interaction.followUp({ content: `🔉 | Volume modifié à ${volume}% !`, ephemeral: true })
}
}
-11
View File
@@ -1,11 +0,0 @@
const { useQueue } = require('discord-player')
module.exports = {
id: 'volume_up',
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
let volume = queue.node.volume + 10
await queue.node.setVolume(volume)
return interaction.followUp({ content: `🔊 | Volume modifié à ${volume}% !`, ephemeral: true })
}
}
-58
View File
@@ -1,58 +0,0 @@
const { SlashCommandBuilder, EmbedBuilder, hyperlink } = require('discord.js')
const fs = require('fs')
const appDir = require('path').dirname(require.main.filename)
require('require-all')(appDir + '/utilsCrack')
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)),
async execute(interaction) {
await interaction.deferReply()
let query = interaction.options.getString('jeu')
let games = await search(query, headers.h1)
if (!Array.isArray(games)) {
if (games.toString() == "TypeError: Cannot read properties of undefined (reading 'split')") return interaction.followUp({ content: `J'ai rien trouvé pour "${query}" !` })
else return interaction.followUp({ content: "Une erreur s'est produite ! ```" + games + "```" })
}
let game
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]
let url = await repo(game, headers.h2)
let file = await torrent(url, headers.h2)
let path = await download(url, file, headers.h2)
let link = await magnet(path)
let embed = new EmbedBuilder()
.setColor('#ffc370')
.setTitle(game.name)
.setURL(game.link)
.setDescription(`Voici ce que j'ai trouvé pour "${query}".\nTu peux aussi cliquer sur [ce lien](https://angels-dev.fr/magnet/${link}) pour pouvoir télécharger le jeu direct !`)
await interaction.followUp({ embeds: [embed], files: [path] })
//fs.unlink(path, (err) => { if (err) throw err })
}
}
-28
View File
@@ -1,28 +0,0 @@
const { SlashCommandBuilder } = require('discord.js')
const { getVoiceConnection, joinVoiceChannel } = require('@discordjs/voice')
module.exports = {
data: new SlashCommandBuilder()
.setName('papa')
.setDescription('Si papa m\'appelle, je le rejoins !'),
async execute(interaction) {
if (interaction.user.id !== '223831938346123275') return interaction.reply({ content: 'T\'es pas mon père, dégage !' })
let botChannel = interaction.guild.members.me.voice.channel
let papaChannel = interaction.member.voice.channel
if (!papaChannel && botChannel) {
getVoiceConnection(botChannel.guild.id).destroy()
return interaction.reply({ content: 'Je quitte le vocal, papa !' })
}
else if (!botChannel || botChannel.id !== papaChannel.id) {
joinVoiceChannel({
channelId: papaChannel.id,
guildId: papaChannel.guild.id,
adapterCreator: papaChannel.guild.voiceAdapterCreator,
})
return interaction.reply({ content: 'Je rejoins ton vocal, papa !' })
}
else return interaction.reply({ content: 'Je suis déjà dans ton vocal, papa !' })
}
}
-13
View File
@@ -1,13 +0,0 @@
const { SlashCommandBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
module.exports = {
data: new SlashCommandBuilder()
.setName('pause')
.setDescription('Met en pause la musique.'),
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
queue.node.setPaused(!queue.node.isPaused())
return await interaction.reply('Musique mise en pause !')
}
}
-15
View File
@@ -1,15 +0,0 @@
const { SlashCommandBuilder } = require('discord.js')
const appDir = require('path').dirname(require.main.filename)
const generatePlayer = require(appDir + '/utilsPlayer/generate.js')
module.exports = {
data: new SlashCommandBuilder()
.setName('player')
.setDescription('Afficher une interface de contrôle de la musique.'),
async execute(interaction) {
let { embed, components } = await generatePlayer(interaction.guild)
if (!components) return await interaction.reply({ embeds: [embed] })
else return await interaction.reply({ embeds: [embed], components })
}
}
-13
View File
@@ -1,13 +0,0 @@
const { SlashCommandBuilder } = require('discord.js')
const { useHistory } = require('discord-player')
module.exports = {
data: new SlashCommandBuilder()
.setName('previous')
.setDescription('Joue la musique précédente.'),
async execute(interaction) {
let history = useHistory(interaction.guild.id)
await history.previous()
return await interaction.reply('Musique précédente jouée !')
}
}
-13
View File
@@ -1,13 +0,0 @@
const { SlashCommandBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
module.exports = {
data: new SlashCommandBuilder()
.setName('resume')
.setDescription('Reprendre la musique.'),
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
queue.node.setPaused(!queue.node.isPaused())
return await interaction.reply('Musique reprise !')
}
}
-13
View File
@@ -1,13 +0,0 @@
const { SlashCommandBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
module.exports = {
data: new SlashCommandBuilder()
.setName('shuffle')
.setDescription('Mélange la file d\'attente.'),
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
queue.tracks.shuffle()
return await interaction.reply('File d\'attente mélangée !')
}
}
-13
View File
@@ -1,13 +0,0 @@
const { SlashCommandBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
module.exports = {
data: new SlashCommandBuilder()
.setName('skip')
.setDescription('Passer la musique en cours.'),
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
queue.node.skip()
return await interaction.reply('Musique passée !')
}
}
-19
View File
@@ -1,19 +0,0 @@
const { SlashCommandBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
module.exports = {
data: new SlashCommandBuilder()
.setName('stop')
.setDescription('Arrêter la musique.'),
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
queue.delete()
writeEnv('DISCORD_MUSIC_TEXTCHANNEL_ID', '')
writeEnv('DISCORD_MUSIC_VOICECHANNEL_ID', '')
writeEnv('DISCORD_MUSIC_CURRENT_TRACK', '')
writeEnv('DISCORD_MUSIC_CURRENT_PROGRESS', '')
return await interaction.reply('Musique arrêtée !')
}
}
-30
View File
@@ -1,30 +0,0 @@
const { Events } = require('discord.js')
require('dotenv').config()
const appDir = require('path').dirname(require.main.filename)
const replay = require(appDir + '/utilsPlayer/replay.js')
const disco = require(appDir + '/utilsPlayer/disco.js')
//const { DataTypes } = require("sequelize")
//const sequelize = require('../utils/initSequelize.js')
module.exports = {
name: Events.ClientReady,
once: true,
async execute(client) {
console.log(`\u001b[1;35m Ready! Logged in as ${client.user.tag}`)
// Check if a music session was active before the bot was restarted
if (process.env.DISCORD_MUSIC_CURRENT_TRACK) await replay(client)
//try {
// sequelize.authenticate()
// console.log('Connection has been established successfully.')
//} catch (error) { console.error('Unable to connect to the database:', error) }
var interval = setInterval(async () => {
let state = await disco(client)
if (state === 'clear') clearInterval(interval)
}, 2000)
}
}
-7
View File
@@ -1,7 +0,0 @@
module.exports = {
name: 'audioTracksAdd',
async execute(queue, track) {
// Emitted when the player adds multiple songs to its queue
queue.metadata.channel.send(`Ajout de ${track.length} musiques à la file d'attente !`)
}
}
-7
View File
@@ -1,7 +0,0 @@
module.exports = {
name: 'emptyQueue',
async execute(queue, track) {
// Emitted when the player queue has finished
queue.metadata.channel.send("File d'attente vide !")
}
}
-8
View File
@@ -1,8 +0,0 @@
module.exports = {
name: 'error',
async execute(queue, error) {
// Emitted when the player queue encounters error
console.log(`\u001b[1;31m General player error event: ${error.message}`)
console.error(error)
}
}
-7
View File
@@ -1,7 +0,0 @@
module.exports = {
name: 'playerSkip',
async execute(queue, track) {
// Emitted when the audio player fails to load the stream for a song
queue.metadata.channel.send(`Musique **${track.title}** de **${track.author}** passée !`)
}
}
-9
View File
@@ -1,9 +0,0 @@
module.exports = {
name: 'playerStart',
async execute(queue, track) {
// Emitted when the player starts to play a song
writeEnv('DISCORD_MUSIC_CURRENT_TRACK', track.url)
queue.metadata.channel.send(`Lecture de **${track.title}** de **${track.author}** !`)
}
}
Generated Regular → Executable
+1362 -919
View File
File diff suppressed because it is too large. Load diff
+29 -30
View File
@@ -1,42 +1,41 @@
{
"name": "bot_tamiseur",
"version": "1.0.0",
"description": "bot_Tamiseur",
"main": "app.js",
"scripts": {
"format": "prettier --write .",
"start": "node app.js",
"dev": "nodemon -e js"
},
"description": "Listen to music and use fun commands with your friends!",
"version": "2.0.0",
"author": {
"name": "Zachary Guénot"
},
"devDependencies": {
"eslint": "^8.42.0",
"nodemon": "^2.0.22",
"prettier": "^2.8.8"
"main": "src/index.ts",
"scripts": {
"format": "prettier --write .",
"start": "node src/index.ts",
"dev": "nodemon -e ts src/index.ts",
"build": "tsc"
},
"eslintConfig": {},
"dependencies": {
"@discord-player/equalizer": "^0.2.1",
"@discord-player/extractor": "^4.3.1",
"@discord-player/equalizer": "^0.2.3",
"@discord-player/extractor": "^4.4.6",
"@discordjs/opus": "^0.9.0",
"@discordjs/voice": "^0.16.0",
"axios": "^1.4.0",
"bufferutil": "^4.0.7",
"discord-player": "^6.5.0",
"discord.js": "^14.11.0",
"dotenv": "^16.1.4",
"@discordjs/voice": "^0.16.1",
"axios": "^1.6.5",
"bufferutil": "^4.0.8",
"discord-player": "^6.6.7",
"discord.js": "^14.14.1",
"dotenv": "^16.3.1",
"iconv-lite": "^0.6.3",
"libsodium-wrappers": "^0.7.11",
"mariadb": "^3.1.2",
"opusscript": "^0.0.8",
"parse-torrent": "^11.0.12",
"play-dl": "^1.9.6",
"prism-media": "^1.3.5",
"jsdom": "^23.2.0",
"libsodium-wrappers": "^0.7.13",
"mariadb": "^3.2.3",
"parse-torrent": "^9.1.5",
"require-all": "^3.0.0",
"sequelize": "^6.32.0",
"sqlite3": "^5.1.6",
"utf-8-validate": "^6.0.3"
"sqlite3": "^5.1.7",
"utf-8-validate": "^6.0.3",
"youtube-ext": "^1.1.16"
},
"devDependencies": {
"@types/parse-torrent": "^5.8.7",
"eslint": "^8.56.0",
"nodemon": "^3.0.2",
"prettier": "^3.2.1"
}
}
+8 -3
View File
@@ -1,9 +1,14 @@
const { useQueue } = require('discord-player')
import { ButtonInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
id: 'loop',
async execute(interaction) {
let queue = useQueue(interaction.guild.id)
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let queue = useQueue(guild.id)
if (!queue) return
let loop = queue.repeatMode === 0 ? 1 : queue.repeatMode === 1 ? 2 : queue.repeatMode === 2 ? 3 : 0
await queue.setRepeatMode(loop)
await interaction.followUp({ content:`Boucle ${loop === 0 ? 'désactivée' : loop === 1 ? 'en mode Titre' : loop === 2 ? 'en mode File d\'Attente' : 'en autoplay'}.`, ephemeral: true })
+15
View File
@@ -0,0 +1,15 @@
import { ButtonInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
id: 'pause',
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let queue = useQueue(guild.id)
if (!queue) return
await queue.node.setPaused(!queue.node.isPaused())
return interaction.followUp({ content: 'Musique mise en pause !', ephemeral: true })
}
}
+15
View File
@@ -0,0 +1,15 @@
import { ButtonInteraction } from 'discord.js'
import { useHistory } from 'discord-player'
module.exports = {
id: 'previous',
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let history = useHistory(guild.id)
if (!history) return
await history.previous()
return interaction.followUp({ content: 'Musique précédente jouée !', ephemeral: true })
}
}
+15
View File
@@ -0,0 +1,15 @@
import { ButtonInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
id: 'resume',
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let queue = useQueue(guild.id)
if (!queue) return
await queue.node.setPaused(!queue.node.isPaused())
return interaction.followUp({ content: 'Musique reprise !', ephemeral: true })
}
}
+15
View File
@@ -0,0 +1,15 @@
import { ButtonInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
id: 'shuffle',
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let queue = useQueue(guild.id)
if (!queue) return
await queue.tracks.shuffle()
return interaction.followUp({ content: 'File d\'attente mélangée !', ephemeral: true })
}
}
+15
View File
@@ -0,0 +1,15 @@
import { ButtonInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
id: 'skip',
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let queue = useQueue(guild.id)
if (!queue) return
await queue.node.skip()
return interaction.followUp({ content: 'Musique passée !', ephemeral: true })
}
}
+15
View File
@@ -0,0 +1,15 @@
import { ButtonInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
id: 'stop',
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let queue = useQueue(guild.id)
if (!queue) return
await queue.delete()
return interaction.followUp({ content: 'Musique arrêtée !', ephemeral: true })
}
}
+16
View File
@@ -0,0 +1,16 @@
import { ButtonInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
id: 'volume_down',
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let queue = useQueue(guild.id)
if (!queue) return
let volume = queue.node.volume - 10
await queue.node.setVolume(volume)
return interaction.followUp({ content: `🔉 | Volume modifié à ${volume}% !`, ephemeral: true })
}
}
+16
View File
@@ -0,0 +1,16 @@
import { ButtonInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
id: 'volume_up',
async execute(interaction: ButtonInteraction) {
let guild = interaction.guild
if (!guild) return
let queue = useQueue(guild.id)
if (!queue) return
let volume = queue.node.volume + 10
await queue.node.setVolume(volume)
return interaction.followUp({ content: `🔊 | Volume modifié à ${volume}% !`, ephemeral: true })
}
}
+55 -28
View File
@@ -1,12 +1,34 @@
const { SlashCommandBuilder, EmbedBuilder, inlineCode } = require('discord.js')
const dotenv = require('dotenv')
dotenv.config()
import { SlashCommandBuilder, ChatInputCommandInteraction, AutocompleteInteraction, EmbedBuilder, inlineCode } from 'discord.js'
import * as AMP from '../../utils/amp'
import 'dotenv/config'
const appDir = require('path').dirname(require.main.filename)
const API = require('require-all')(appDir + '/utilsAMP')
interface ListInstancesResult {
status: string
data: {
result: [
Host: {
AvailableInstances: any[]
FriendlyName: string
}
]
}
}
interface InstanceFields {
name: string
value: string
inline: boolean
}
function failMsg(data) { return `La commande a échouée !\n${inlineCode(`${data.Title}: ${data.Message}`)}` }
function errorMsg(data) { return `Y'a eu une erreur !\n${inlineCode(`${data.error_code}`)}` }
interface failData {
Title: string
Message: string
}
interface errorData {
error_code: string
}
function failMsg(data: any) { return `La commande a échouée !\n${inlineCode(`${data.Title}: ${data.Message}`)}` }
function errorMsg(data: any) { return `Y'a eu une erreur !\n${inlineCode(`${data.error_code}`)}` }
module.exports = {
data: new SlashCommandBuilder().setName('amp').setDescription('Accède à mon panel de jeu AMP !')
@@ -25,12 +47,13 @@ module.exports = {
/*.addSubcommand(subcommand => subcommand.setName('restart').setDescription('Redémarre une instance.')
.addStringOption(option => option.setName('name').setDescription("Nom de l'instance").setRequired(true)))*/),
async autocompleteRun(interaction) {
async autocompleteRun(interaction: AutocompleteInteraction) {
let query = interaction.options.getString('instance', true)
// Check if the SessionID is still valid
let sessionID = dotenv.config().parsed.AMP_SESSIONID
let session = await API.CheckSession(sessionID)
//let sessionID = dotenv.config().parsed.AMP_SESSIONID
let sessionID = process.env.AMP_SESSIONID as string
let session = await AMP.CheckSession(sessionID)
if (session.status === 'fail') {
if (process.env.AMP_REMEMBER_TOKEN) {
// Refresh the SessionID if the RememberMeToken is available
@@ -40,7 +63,7 @@ module.exports = {
token: process.env.AMP_REMEMBER_TOKEN,
rememberMe: true
}
let result = await API.Core.Login(details)
let result = await AMP.Core.Login(details)
console.log(result)
if (result.status === 'success') sessionID = result.data.sessionID
else if (result.status === 'fail') return interaction.respond([])
@@ -48,17 +71,18 @@ module.exports = {
}
else {
// If no RememberMeToken is available, ask to login
return await interaction.followUp(`Tu dois te connecter avant d'effectuer une autre commande !`)
//return await interaction.followUp(`Tu dois te connecter avant d'effectuer une autre commande !`)
return await interaction.respond([])
}
}
else if (session.status === 'error') return interaction.respond([])
let choices = []
let result = await API.ADSModule.GetInstances(sessionID)
let choices: any = []
let result = await AMP.ADSModule.GetInstances(sessionID)
if (result.status === 'success') {
let hosts = result.data.result
let hosts = result.data.result as any[]
hosts.forEach(host => {
let instances = host.AvailableInstances
let instances = host.AvailableInstances as any[]
instances.forEach(instance => {
if (instance.FriendlyName.includes(query)) choices.push({ name: `${host.FriendlyName} - ${instance.FriendlyName}`, value: instance.InstanceID })
})
@@ -69,7 +93,7 @@ module.exports = {
return interaction.respond(choices)
},
async execute(interaction) {
async execute(interaction: ChatInputCommandInteraction) {
// Let the user login
if (interaction.options.getSubcommand() == 'login') {
// Get a SessionID and a RememberMeToken if wanted
@@ -82,7 +106,7 @@ module.exports = {
rememberMe: interaction.options.getBoolean('remember')
}
let result = await API.Core.Login(details)
let result = await AMP.Core.Login(details)
if (result.status === 'success') return await interaction.followUp(`Tu es connecté au panel sous **${result.data.userInfo.Username}** !`)
else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data))
else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data))
@@ -90,8 +114,9 @@ module.exports = {
await interaction.deferReply()
// Check if the SessionID is still valid
let sessionID = dotenv.config().parsed.AMP_SESSIONID
let session = await API.CheckSession(sessionID)
//let sessionID = dotenv.config().parsed.AMP_SESSIONID
let sessionID = process.env.AMP_SESSIONID as string
let session = await AMP.CheckSession(sessionID)
if (session.status === 'fail') {
console.log(session)
@@ -103,7 +128,7 @@ module.exports = {
token: process.env.AMP_REMEMBER_TOKEN,
rememberMe: true
}
let result = await API.Core.Login(details)
let result = await AMP.Core.Login(details)
console.log(result)
if (result.status === 'success') sessionID = result.data.sessionID
else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data))
@@ -118,12 +143,12 @@ module.exports = {
if (interaction.options.getSubcommandGroup() == 'instances') {
if (interaction.options.getSubcommand() == 'list') {
let result = await API.ADSModule.GetInstances(sessionID)
let result = await AMP.ADSModule.GetInstances(sessionID) as ListInstancesResult
if (result.status === 'success') {
await interaction.followUp({ content: `${result.data.result.length} hôtes trouvés !` })
result.data.result.forEach(async host => {
let fields = []
let fields = [] as InstanceFields[]
host.AvailableInstances.forEach(instance => {
fields.push({
name: instance.FriendlyName,
@@ -134,10 +159,10 @@ module.exports = {
let embed = new EmbedBuilder()
.setTitle(host.FriendlyName)
.setDescription(`Liste des ${host.AvailableInstances.length} instances :`)
.setColor(interaction.guild.members.me.displayColor)
.setColor(interaction.guild?.members.me?.displayColor || '#ffc370')
.setTimestamp()
.setFields(fields)
return await interaction.channel.send({ embeds: [embed] })
return await interaction.channel?.send({ embeds: [embed] })
})
}
else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data))
@@ -145,10 +170,10 @@ module.exports = {
}
else if (interaction.options.getSubcommand() == 'manage') {
let instanceID = interaction.options.getString('instance', true)
let result = await API.ADSModule.ManageInstance(sessionID, instanceID)
let result = await AMP.ADSModule.ManageInstance(sessionID, instanceID)
if (result.status === 'success') {
let server = await API.ADSModule.Servers(sessionID, instanceID)
let server = await AMP.ADSModule.Servers(sessionID, instanceID)
console.log(server)
if (server.status === 'success') return await interaction.followUp(`Ok !`)
@@ -160,7 +185,9 @@ module.exports = {
}
else if (interaction.options.getSubcommand() == 'restart') {
let query = interaction.options.getString('name')
let result = await API.ADSModule.RestartInstance(sessionID, query)
if (!query) return
let result = await AMP.ADSModule.RestartInstance(sessionID, query)
if (result.status === 'success') return await interaction.followUp(`Ok !`)
else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data))
+58
View File
@@ -0,0 +1,58 @@
import { SlashCommandBuilder, EmbedBuilder, ChatInputCommandInteraction, MessageReaction, User }from 'discord.js'
import * as crack from '../../utils/crack'
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)),
async execute(interaction: ChatInputCommandInteraction) {
await interaction.deferReply()
let query = interaction.options.getString('jeu')
if (!query) return
let games = await crack.search(query) as crack.Game[]
if (!Array.isArray(games)) {
//if (games.toString() == "TypeError: Cannot read properties of undefined (reading 'split')") return interaction.followUp({ content: `J'ai rien trouvé pour "${query}" !` })
//else return interaction.followUp({ content: "Une erreur s'est produite ! ```" + games + "```" })
return interaction.followUp({ content: `J'ai rien trouvé pour "${query}" !` })
}
let game = {} as crack.Game
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: any = (reaction: MessageReaction, user: User) => { if (reaction.emoji.name) return emojis.includes(reaction.emoji.name) && user.id === interaction.user.id }
await message.awaitReactions({ filter, max: 1, time: 5000, errors: ['time'] }).then(collected => {
console.log(collected)
if (!collected.first) return
let reaction = collected.first()
let index = emojis.indexOf(reaction?.emoji.name ?? '')
game = games[index]
}).catch(() => { return interaction.followUp({ content: 'T\'as mis trop de temps à choisir !' }) })
}
else game = games[0]
let url = await crack.repo(game)
if (!url) return
let file = await crack.torrent(url)
if (!file) return
let filePath = await crack.download(url, file)
if (!filePath) return
let link = await crack.magnet(filePath)
let embed = new EmbedBuilder()
.setColor('#ffc370')
.setTitle(game.name)
.setURL(game.link)
.setDescription(`Voici ce que j'ai trouvé pour "${query}".\nTu peux aussi cliquer sur [ce lien](https://angels-dev.fr/magnet/${link}) pour pouvoir télécharger le jeu direct !`)
await interaction.followUp({ embeds: [embed], files: [filePath] })
}
}
+34
View File
@@ -0,0 +1,34 @@
import { SlashCommandBuilder, ChatInputCommandInteraction, GuildMember } from 'discord.js'
import { getVoiceConnection, joinVoiceChannel } from '@discordjs/voice'
module.exports = {
data: new SlashCommandBuilder()
.setName('papa')
.setDescription('Si papa m\'appelle, je le rejoins !'),
async execute(interaction: ChatInputCommandInteraction) {
if (interaction.user.id !== '223831938346123275') return interaction.reply({ content: 'T\'es pas mon père, dégage !' })
let guild = interaction.guild
if (!guild) return interaction.reply({ content: 'Je ne peux pas rejoindre ton vocal en message privé, papa !' })
let member = interaction.member as GuildMember
let botChannel = guild.members.me?.voice.channel
let papaChannel = member.voice.channel
if (!papaChannel && botChannel) {
const voiceConnection = getVoiceConnection(guild.id);
if (voiceConnection) voiceConnection.destroy()
return interaction.reply({ content: 'Je quitte le vocal, papa !' })
}
else if (papaChannel && (!botChannel || botChannel.id !== papaChannel.id)) {
joinVoiceChannel({
channelId: papaChannel.id,
guildId: papaChannel.guild.id,
adapterCreator: papaChannel.guild.voiceAdapterCreator,
})
return interaction.reply({ content: 'Je rejoins ton vocal, papa !' })
}
else return interaction.reply({ content: 'Je suis déjà dans ton vocal, papa !' })
}
}
@@ -1,21 +1,26 @@
const { SlashCommandBuilder } = require('discord.js')
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, EndBehaviorType } = require('@discordjs/voice')
const appDir = require('path').dirname(require.main.filename)
import { SlashCommandBuilder, ChatInputCommandInteraction, GuildMember } from 'discord.js'
import { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, EndBehaviorType } from '@discordjs/voice'
module.exports = {
data: new SlashCommandBuilder()
.setName('parle')
.setDescription('Fais moi parler par dessus quelqu\'un de chiant dans le vocal')
.addUserOption(option => option.setName('user').setDescription('La personne en question').setRequired(true)),
async execute(interaction) {
async execute(interaction: ChatInputCommandInteraction) {
if (interaction.user.id !== '223831938346123275') return await interaction.reply({ content: 'Tu n\'as pas le droit d\'utiliser cette commande !', ephemeral: true })
let user = interaction.options.getUser('user')
let member = interaction.guild.members.cache.get(user.id)
if (!user) return
let guild = interaction.guild
if (!guild) return
let member = guild.members.cache.get(user.id) as GuildMember
if (!member) return
let caller = interaction.member as GuildMember
if (!caller) return
if (!interaction.member.voice.channel) return await interaction.reply({ content: 'You must be in a voice channel to use this command.', ephemeral: true })
if (!caller.voice.channel) return await interaction.reply({ content: 'You must be in a voice channel to use this command.', ephemeral: true })
if (!member.voice.channel) return await interaction.reply({ content: 'The member must be in a voice channel to use this command.', ephemeral: true })
if (interaction.member.voice.channelId !== member.voice.channelId) return await interaction.reply({ content: 'You must be in the same voice channel than the member to use this command.', ephemeral: true })
if (caller.voice.channelId !== member.voice.channelId) return await interaction.reply({ content: 'You must be in the same voice channel than the member to use this command.', ephemeral: true })
await interaction.reply({ content: 'Je vais parler par dessus cette personne !', ephemeral: true })
@@ -45,26 +50,27 @@ module.exports = {
player.on(AudioPlayerStatus.Idle, () => { playing = false })
let connection = joinVoiceChannel({
channelId: interaction.member.voice.channelId,
guildId: interaction.guildId,
adapterCreator: interaction.guild.voiceAdapterCreator,
channelId: caller.voice.channelId as string,
guildId: interaction.guildId as string,
adapterCreator: guild.voiceAdapterCreator,
selfDeaf: false
})
connection.subscribe(player)
let stream = connection.receiver.subscribe(user.id, { end: { behavior: EndBehaviorType.Manual } })
stream.on('data', (chunk) => {
if (!user) return
if (connection.receiver.speaking.users.has(user.id) && !playing) {
playing = true
let resource = createAudioResource(appDir + '/parle.mp3', { inlineVolume: true })
let resource = createAudioResource('../../static/parle.mp3', { inlineVolume: true })
//let resource = createAudioResource(file.attachments.first().url, { inlineVolume: true })
resource.volume.setVolume(0.2)
if (resource.volume) resource.volume.setVolume(0.2)
player.play(resource)
}
})
interaction.client.on('voiceStateUpdate', (oldState, newState) => {
if (oldState.id === member.id && newState.channelId !== interaction.member.voice.channelId) {
if (oldState.id === member.id && newState.channelId !== caller.voice.channelId) {
stream.destroy()
connection.disconnect()
}
@@ -1,10 +1,10 @@
const { SlashCommandBuilder } = require('discord.js')
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Check the latency of the bot'),
async execute(interaction) {
async execute(interaction: ChatInputCommandInteraction) {
let sent = await interaction.reply({ content: 'Pinging...', fetchReply: true })
interaction.editReply(`Websocket heartbeat: ${interaction.client.ws.ping}ms.\nRoundtrip latency: ${sent.createdTimestamp - interaction.createdTimestamp}ms`)
}
@@ -1,4 +1,4 @@
const { SlashCommandBuilder } = require('discord.js')
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
module.exports = {
data: new SlashCommandBuilder()
@@ -7,14 +7,18 @@ module.exports = {
.addUserOption(option => option.setName('user').setDescription('Spam').setRequired(true))
.addStringOption(option => option.setName('string').setDescription('Spam').setRequired(true))
.addIntegerOption(option => option.setName('integer').setDescription('Spam').setRequired(true)),
async execute(interaction) {
async execute(interaction: ChatInputCommandInteraction) {
let user = interaction.options.getUser('user')
let string = interaction.options.getString('string')
let integer = interaction.options.getInteger('integer')
await interaction.reply({ content: 'Spam', ephemeral: true })
let i = 0
function myLoop() {
setTimeout(function () {
if (!user) return
if (!string) return
if (!integer) return
user.send(string).catch(error => console.error(error))
i++
if (i < integer) myLoop()
@@ -1,15 +1,17 @@
const { SlashCommandBuilder } = require('discord.js')
import { SlashCommandBuilder, ChatInputCommandInteraction, Guild } from 'discord.js'
module.exports = {
data: new SlashCommandBuilder()
.setName('update')
.setDescription('Update the member count channel.'),
async execute(interaction) {
let guild = interaction.guild
async execute(interaction: ChatInputCommandInteraction) {
let guild = interaction.guild as Guild
guild.members.fetch().then(() => {
var i = 0
guild.members.cache.forEach(async member => { if (!member.user.bot) i++ })
let channel = guild.channels.cache.get('1091140609139560508')
if (!channel) return
channel.setName(`${i} Gens Posés`)
interaction.reply(`${i} Gens Posés !`)
}).catch(console.error)
@@ -1,5 +1,5 @@
const { SlashCommandBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'
import { useQueue } from'discord-player'
module.exports = {
data: new SlashCommandBuilder()
@@ -10,10 +10,12 @@ module.exports = {
.setRequired(true)
.setMinValue(0)
.setMaxValue(3)),
async execute(interaction) {
async execute(interaction: ChatInputCommandInteraction) {
let loop = interaction.options.getInteger('loop')
let queue = useQueue(interaction.guild.id)
queue.setRepeatMode(loop)
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.setRepeatMode(loop as number)
return await interaction.reply(`Boucle ${loop === 0 ? 'désactivée' : loop === 1 ? 'en mode Titre' : loop === 2 ? 'en mode File d\'Attente' : 'en autoplay'}.`)
}
}
@@ -1,18 +1,18 @@
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
const { lyricsExtractor } = require('@discord-player/extractor')
import { ChatInputCommandInteraction, SlashCommandBuilder, EmbedBuilder } from 'discord.js'
import { useQueue } from 'discord-player'
import { lyricsExtractor } from '@discord-player/extractor'
module.exports = {
data: new SlashCommandBuilder()
.setName('lyrics')
.setDescription('Rechercher les paroles d\'une musique.')
.addStringOption(option => option.setName('recherche').setDescription('Chercher une musique spécifique')),
async execute(interaction) {
async execute(interaction: ChatInputCommandInteraction) {
await interaction.deferReply()
let query = interaction.options.getString('recherche', false)
if (!query) {
let queue = useQueue(interaction.guild.id)
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
let track = queue.currentTrack
if (!track) return interaction.followUp({ content: 'Aucune musique en cours, recherche en une plutôt !' })
+15
View File
@@ -0,0 +1,15 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
data: new SlashCommandBuilder()
.setName('pause')
.setDescription('Met en pause la musique.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.node.setPaused(!queue.node.isPaused())
return await interaction.reply('Musique mise en pause !')
}
}
@@ -1,16 +1,19 @@
const { SlashCommandBuilder } = require('discord.js')
const { useMasterPlayer, useQueue, QueryType } = require('discord-player')
import { SlashCommandBuilder, ChatInputCommandInteraction, AutocompleteInteraction, GuildMember } from 'discord.js'
import { useMainPlayer, useQueue, QueryType } from 'discord-player'
import writeEnv from '../../utils/writeEnv'
export interface TrackSearchResult { name: string, value: string }
module.exports = {
data: new SlashCommandBuilder()
.setName('play')
.setDescription('Jouer une musique.')
.addStringOption(option => option.setName('recherche').setDescription('Titre de la musique à chercher').setRequired(true).setAutocomplete(true)),
async autocompleteRun(interaction) {
async autocompleteRun(interaction: AutocompleteInteraction) {
let query = interaction.options.getString('recherche', true)
if (!query) return interaction.respond([])
let player = useMasterPlayer()
let player = useMainPlayer()
const resultsYouTube = await player.search(query, { searchEngine: QueryType.YOUTUBE })
const resultsSpotify = await player.search(query, { searchEngine: QueryType.SPOTIFY_SEARCH })
@@ -24,27 +27,28 @@ module.exports = {
value: t.url
}))
const tracks = []
tracksYouTube.forEach((t) => tracks.push({ name: t.name, value: t.value }));
tracksSpotify.forEach((t) => tracks.push({ name: t.name, value: t.value }));
const tracks: TrackSearchResult[] = []
tracksYouTube.forEach((t) => tracks.push({ name: t.name, value: t.value }))
tracksSpotify.forEach((t) => tracks.push({ name: t.name, value: t.value }))
return interaction.respond(tracks)
},
async execute(interaction) {
let voiceChannel = interaction.member.voice.channel
if (!voiceChannel) return await interaction.reply({ content: "T'es pas dans un vocal, idiot !", ephemeral: true })
async execute(interaction: ChatInputCommandInteraction) {
let member = interaction.member as GuildMember
let voiceChannel = member.voice.channel
if (!voiceChannel) return await interaction.reply({ content: 'T\'es pas dans un vocal, idiot !', ephemeral: true })
let botChannel = interaction.guild.members.me.voice.channel
if (botChannel && voiceChannel.id !== botChannel.id) return await interaction.reply({ content: "T'es pas dans mon vocal !", ephemeral: true })
let botChannel = interaction.guild?.members.me?.voice.channel
if (botChannel && voiceChannel.id !== botChannel.id) return await interaction.reply({ content: 'T\'es pas dans mon vocal !', ephemeral: true })
await interaction.deferReply()
let query = interaction.options.getString('recherche', true)
let player = useMasterPlayer()
let queue = useQueue(interaction.guild.id)
let player = useMainPlayer()
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) {
queue = player.nodes.create(interaction.guild, {
if (!queue) {
if (interaction.guild) queue = player.nodes.create(interaction.guild, {
metadata: {
channel: interaction.channel,
client: interaction.guild.members.me,
@@ -53,32 +57,35 @@ module.exports = {
selfDeaf: true,
volume: 20,
leaveOnEmpty: true,
leaveOnEmptyCooldown: 300000,
leaveOnEmptyCooldown: 30000,
leaveOnEnd: true,
leaveOnEndCooldown: 300000,
skipOnNoStream: true
leaveOnEndCooldown: 300000
})
else return
}
try { if (!queue.connection) await queue.connect(voiceChannel) }
catch (error) { console.error(error); return interaction.followUp(`Y'a eu un problème, <@223831938346123275> ! (${error.message})`) }
catch (error: any) { console.error(error); return interaction.followUp(`Y'a eu un problème, <@223831938346123275> ! (${error.message})`) }
// Write the values in the .env file to recover the player if the bot restarts
writeEnv('DISCORD_MUSIC_TEXTCHANNEL_ID', interaction.channel?.id ?? '')
writeEnv('DISCORD_MUSIC_VOICECHANNEL_ID', voiceChannel.id)
// Search the song
let result = await player.search(query, { requestedBy: interaction.user })
if (!result.hasTracks()) return interaction.followUp(`Aucune musique trouvée pour **${query}** !`)
let track = result.tracks[0]
console.log(track.duration)
console.log(track.durationMS)
let entry = queue.tasksQueue.acquire()
await entry.getTask()
queue.addTrack(track)
// Write the values in the .env file to recover the player if the bot restarts
writeEnv('DISCORD_MUSIC_TEXTCHANNEL_ID', interaction.channel.id)
writeEnv('DISCORD_MUSIC_VOICECHANNEL_ID', voiceChannel.id)
try {
if (!queue.isPlaying()) await queue.node.play()
let track_source = track.source === 'youtube' ? 'Youtube' : track.source === 'spotify' ? 'Spotify' : 'Inconnu'
return interaction.followUp(`Chargement de la musique **${track.title}** de **${track.author}** sur **${track_source}**...`)
} catch (error) { console.error(error); return interaction.followUp(`Y'a eu un problème, <@223831938346123275> ! (${error.message})`) }
} catch (error: any) { console.error(error); return interaction.followUp(`Y'a eu un problème, <@223831938346123275> ! (${error.message})`) }
finally { queue.tasksQueue.release() }
}
}
+15
View File
@@ -0,0 +1,15 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useHistory } from 'discord-player'
module.exports = {
data: new SlashCommandBuilder()
.setName('previous')
.setDescription('Joue la musique précédente.'),
async execute(interaction: ChatInputCommandInteraction) {
let history = useHistory(interaction.guild?.id ?? '')
if (!history) return await interaction.reply('Il n\'y a pas d\'historique de musique !')
await history.previous()
return await interaction.reply('Musique précédente jouée !')
}
}
+15
View File
@@ -0,0 +1,15 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
data: new SlashCommandBuilder()
.setName('resume')
.setDescription('Reprendre la musique.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.node.setPaused(!queue.node.isPaused())
return await interaction.reply('Musique reprise !')
}
}
+15
View File
@@ -0,0 +1,15 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
data: new SlashCommandBuilder()
.setName('shuffle')
.setDescription('Mélange la file d\'attente.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.tracks.shuffle()
return await interaction.reply('File d\'attente mélangée !')
}
}
+15
View File
@@ -0,0 +1,15 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
data: new SlashCommandBuilder()
.setName('skip')
.setDescription('Passer la musique en cours.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.node.skip()
return await interaction.reply('Musique passée !')
}
}
+21
View File
@@ -0,0 +1,21 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
import writeEnv from '../../utils/writeEnv'
module.exports = {
data: new SlashCommandBuilder()
.setName('stop')
.setDescription('Arrêter la musique.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.delete()
writeEnv('DISCORD_MUSIC_TEXTCHANNEL_ID', '')
writeEnv('DISCORD_MUSIC_VOICECHANNEL_ID', '')
writeEnv('DISCORD_MUSIC_CURRENT_TRACK', '')
writeEnv('DISCORD_MUSIC_CURRENT_PROGRESS', '')
return await interaction.reply('Musique arrêtée !')
}
}
@@ -1,5 +1,5 @@
const { SlashCommandBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = {
data: new SlashCommandBuilder()
@@ -10,10 +10,12 @@ module.exports = {
.setRequired(true)
.setMinValue(1)
.setMaxValue(100)),
async execute(interaction) {
async execute(interaction: ChatInputCommandInteraction) {
let volume = interaction.options.getInteger('volume')
let queue = useQueue(interaction.guild.id)
queue.node.setVolume(volume)
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.node.setVolume(volume as number)
return await interaction.reply(`Volume modifié à ${volume}% !`)
}
}
+2 -2
View File
@@ -1,8 +1,8 @@
const { Events } = require('discord.js')
import { Events } from 'discord.js'
module.exports = {
name: Events.Error,
execute(error) {
execute(error: any) {
console.error(error)
}
}
@@ -1,13 +1,15 @@
const { Events } = require('discord.js')
import { Events, GuildMember } from 'discord.js'
module.exports = {
name: Events.GuildMemberAdd,
async execute(member) {
async execute(member: GuildMember) {
if (member.guild.id !== '1086577543651524699') return
member.guild.members.fetch().then(() => {
var i = 0
member.guild.members.cache.forEach(async member => { if (!member.user.bot) i++ })
let channel = member.guild.channels.cache.get('1091140609139560508')
if (!channel) return
console.log(channel.name)
console.log(`${i} Gens Posés`)
channel.setName('Changement...')
@@ -1,13 +1,15 @@
const { Events } = require('discord.js')
import { Events, GuildMember } from 'discord.js'
module.exports = {
name: Events.GuildMemberRemove,
async execute(member) {
async execute(member: GuildMember) {
if (member.guild.id !== '1086577543651524699') return
member.guild.members.fetch().then(() => {
var i = 0
member.guild.members.cache.forEach(async member => { if (!member.user.bot) i++ })
let channel = member.guild.channels.cache.get('1091140609139560508')
if (!channel) return
console.log(channel.name)
console.log(`${i} Gens Posés`)
channel.setName('Changement...')
@@ -1,37 +1,38 @@
const { Events } = require('discord.js')
const appDir = require('path').dirname(require.main.filename)
const editPlayer = require(appDir + '/utilsPlayer/edit.js')
const playerButtons = require(appDir + '/utilsPlayer/buttons.js')
import { Events, Interaction, ChatInputCommandInteraction, AutocompleteInteraction, ButtonInteraction } from 'discord.js'
import editPlayer from '../utilsPlayer/edit'
import playerButtons from '../utilsPlayer/buttons'
module.exports = {
name: Events.InteractionCreate,
async execute(interaction) {
async execute(interaction: Interaction) {
//if (!interaction.isAutocomplete() && !interaction.isChatInputCommand() && !interaction.isButton()) return console.error(`Interaction ${interaction.commandName} is not a command.`)
if (interaction.isChatInputCommand()) {
let command = interaction.client.commands.get(interaction.commandName)
if (!command) return console.error(`No command matching ${interaction.commandName} was found.`)
interaction = interaction as ChatInputCommandInteraction
let chatInputCommand = interaction.client.commands.get(interaction.commandName)
if (!chatInputCommand) return console.error(`No chat input command matching ${interaction.commandName} was found.`)
console.log(`\u001b[1;33m Command '${interaction.commandName}' launched by ${interaction.user.tag}`)
console.log(`Command '${interaction.commandName}' launched by ${interaction.user.tag}`)
try { await command.execute(interaction) }
try { await chatInputCommand.execute(interaction) }
catch (error) { console.error(`Error executing ${interaction.commandName}:`, error) }
}
else if (interaction.isAutocomplete()) {
interaction = interaction as AutocompleteInteraction
let autoCompleteRun = interaction.client.commands.get(interaction.commandName)
if (!autoCompleteRun) return console.error(`No autoCompleteRun matching ${interaction.commandName} was found.`)
console.log(`\u001b[1;33m AutoCompleteRun '${interaction.commandName}' launched by ${interaction.user.tag}`)
console.log(`AutoCompleteRun '${interaction.commandName}' launched by ${interaction.user.tag}`)
try { await autoCompleteRun.autocompleteRun(interaction) }
catch (error) { console.error(`Error autocompleting ${interaction.commandName}:`, error) }
}
else if (interaction.isButton()) {
interaction = interaction as ButtonInteraction
let button = interaction.client.buttons.get(interaction.customId)
if (!button) return console.error(`No button id matching ${interaction.customId} was found.`)
console.log(`\u001b[1;33m Button '${interaction.customId}' clicked by ${interaction.user.tag}`)
console.log(`Button '${interaction.customId}' clicked by ${interaction.user.tag}`)
if (playerButtons.includes(interaction.customId)) { await editPlayer(interaction) }
+30
View File
@@ -0,0 +1,30 @@
import { Events, Client, ActivityType } from 'discord.js'
import { useMainPlayer } from 'discord-player'
import replay from '../utilsPlayer/replay'
import disco from '../utilsPlayer/disco'
import 'dotenv/config'
declare module "discord.js" {
export interface Client {
disco: { interval: NodeJS.Timeout }
}
}
module.exports = {
name: Events.ClientReady,
once: true,
async execute(client: Client) {
console.log(`Ready! Logged in as ${client.user?.tag ?? 'unknown'}`)
client.user?.setActivity('some bangers...', { type: ActivityType.Listening })
await useMainPlayer().extractors.loadDefault(ext => ext === 'YouTubeExtractor' || ext === 'SpotifyExtractor').then(() => console.log('YouTube and Spotify extractors loaded.')).catch(console.error)
if (process.env.DISCORD_MUSIC_CURRENT_TRACK) await replay(client)
client.disco = { interval: {} as NodeJS.Timeout }
client.disco.interval = setInterval(async () => {
let state = await disco(client)
if (state === 'clear') clearInterval(client.disco.interval)
}, 2000)
}
}
@@ -1,8 +1,8 @@
const { Events, AuditLogEvent } = require('discord.js')
import { Events, VoiceState } from 'discord.js'
module.exports = {
name: Events.VoiceStateUpdate,
async execute(oldState, newState) {
async execute(oldState: VoiceState, newState: VoiceState) {
/*
let oldMute = oldState.serverMute
let newMute = newState.serverMute
+5 -2
View File
@@ -1,6 +1,9 @@
module.exports = {
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'audioTrackAdd',
async execute(queue, track) {
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the player adds a single song to its queue
queue.metadata.channel.send(`Musique **${track.title}** de **${track.author}** ajoutée à la file d'attente !`)
}
+10
View File
@@ -0,0 +1,10 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'audioTracksAdd',
async execute(queue: GuildQueue<PlayerMetadata>, track: Array<Track>) {
// Emitted when the player adds multiple songs to its queue
queue.metadata.channel.send(`Ajout de ${track.length} musiques à la file d'attente !`)
}
}
+4 -2
View File
@@ -1,6 +1,8 @@
module.exports = {
import { GuildQueue } from 'discord-player'
export default {
name: 'debug',
async execute (queue, message) {
async execute(queue: GuildQueue, message: string) {
// Emitted when the player queue sends debug info
// Useful for seeing what state the current queue is at
console.log(`Player debug event: ${message}`)
+6 -2
View File
@@ -1,6 +1,10 @@
module.exports = {
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
import writeEnv from '../utils/writeEnv'
export default {
name: 'disconnect',
async execute(queue, track) {
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the bot leaves the voice channel
queue.metadata.channel.send("J'ai quitté le vocal !")
+5 -2
View File
@@ -1,6 +1,9 @@
module.exports = {
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'emptyChannel',
async execute(queue, track) {
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the voice channel has been empty for the set threshold
// Bot will automatically leave the voice channel with this event
queue.metadata.channel.send(`Je quitte le vocal car il est vide depuis trop longtemps.`)
+10
View File
@@ -0,0 +1,10 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'emptyQueue',
async execute(queue: GuildQueue<PlayerMetadata>) {
// Emitted when the player queue has finished
queue.metadata.channel.send("File d'attente vide !")
}
}
+10
View File
@@ -0,0 +1,10 @@
import { GuildQueue } from 'discord-player'
export default {
name: 'error',
async execute(queue: GuildQueue, error: Error) {
// Emitted when the player queue encounters error
console.log(`General player error event: ${error.message}`)
console.error(error)
}
}
+4 -2
View File
@@ -1,6 +1,8 @@
module.exports = {
import { GuildQueue } from 'discord-player'
export default {
name: 'playerError',
async execute(queue, error) {
async execute(queue: GuildQueue, error: Error) {
// Emitted when the audio player errors while streaming audio track
console.log(`\u001b[1;31m Player error event: ${error.message}`)
console.error(error)
+10
View File
@@ -0,0 +1,10 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'playerSkip',
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the audio player fails to load the stream for a song
queue.metadata.channel.send(`Musique **${track.title}** de **${track.author}** passée !`)
}
}
+13
View File
@@ -0,0 +1,13 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
import writeEnv from '../utils/writeEnv'
export default {
name: 'playerStart',
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the player starts to play a song
queue.metadata.channel.send(`Lecture de **${track.title}** de **${track.author}** !`)
writeEnv(`DISCORD_MUSIC_CURRENT_TRACK`, track.url)
}
}
Executable
+89
View File
@@ -0,0 +1,89 @@
// PACKAGES
import { Client, Collection, GatewayIntentBits, REST, Routes, ChatInputCommandInteraction, AutocompleteInteraction, ButtonInteraction } from 'discord.js'
import { Player } from 'discord-player'
import path from 'path'
import fs from 'fs'
import 'dotenv/config'
export interface Command {
name: string,
description: string,
data: any,
autocompleteRun: (interaction: AutocompleteInteraction) => any,
execute: (interaction: ChatInputCommandInteraction) => any
}
export interface Button {
name: string,
description: string,
id: string,
execute: (interaction: ButtonInteraction) => any
}
declare module 'discord.js' {
export interface Client {
commands: Collection<unknown, Command>
buttons: Collection<unknown, Button>
}
}
// CLIENT INITIALIZATION
let intents = [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildVoiceStates]
const client = new Client({ intents })
// EVENTS HANDLING
const eventFiles = fs.readdirSync(path.join(__dirname, './events')).filter(file => file.endsWith('.ts'))
eventFiles.forEach(file => {
let event = require(path.join(__dirname, './events', file))
if (event.once) client.once(event.name, (...args) => { event.execute(...args) })
else client.on(event.name, (...args) => { event.execute(...args) })
})
// COMMANDS HANDLING
client.commands = new Collection()
const commandFolders = fs.readdirSync(path.join(__dirname, './commands'))
commandFolders.forEach(folder => {
let folderPath = path.join(__dirname, './commands', folder)
let commandFiles = fs.readdirSync(folderPath).filter(file => file.endsWith('.ts'))
commandFiles.forEach(file => {
let command = require(path.join(folderPath, file))
if ('data' in command && 'execute' in command) {
const commandData = command.data.toJSON()
if (commandData) client.commands.set(commandData.name, command)
} else console.log(`[WARNING] The command at ${`${folderPath}/${file}`} is missing a required "data" or "execute" property.`)
})
})
// COMMANDS REGISTERING
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN as string)
async () => {
try { await rest.put(Routes.applicationCommands(process.env.DISCORD_APP_ID as string), { body: client.commands }) }
catch (error) { console.error(error) }
}
// BUTTONS HANDLING
client.buttons = new Collection()
const buttonFiles = fs.readdirSync(path.join(__dirname, './buttons')).filter(file => file.endsWith('.ts'))
buttonFiles.forEach(file => {
let button = require(path.join(__dirname, './buttons', file))
if ('id' in button && 'execute' in button) client.buttons.set(button.id, button)
else console.log(`[WARNING] The button ${file} is missing a required "id" or "execute" property.`)
})
// PLAYER INITIALIZATION
const player = new Player(client)
// PLAYER EVENTS HANDLING
const eventPlayerFiles = fs.readdirSync(path.join(__dirname, './eventsPlayer')).filter(file => file.endsWith('.ts'))
eventPlayerFiles.forEach(async file => {
let event = await import(path.join(__dirname, './eventsPlayer', file))
if (event.default.name === 'debug') return
player.events.on(event.default.name, (...args: any[]) => event.default.execute(...args))
})
// LAUNCH
client.login()
View File
File renamed without changes.
File renamed without changes.
+95
View File
@@ -0,0 +1,95 @@
import axios from 'axios'
import writeEnv from './writeEnv'
export const ADSModule = {
async GetInstances(SESSIONID: string) {
return await axios.post(`${process.env.AMP_HOST}/API/ADSModule/GetInstances`, {
SESSIONID
}).then(response => {
if (!response.data.result) return { status: 'fail', data: response.data }
return { status: 'success', data: response.data }
}).catch(error => {
console.error(error)
return { status: 'error', data: error }
})
},
async ManageInstance(SESSIONID: string, InstanceId: string) {
return await axios.post(`${process.env.AMP_HOST}/API/ADSModule/ManageInstance`, {
SESSIONID,
InstanceId
}).then(response => {
console.log(response.data)
if (!response.data.result) return { status: 'fail', data: response.data }
return { status: 'success', data: response.data }
}).catch(error => {
console.error(error)
return { status: 'error', data: error }
})
},
async RestartInstance(SESSIONID: string, InstanceName: string) {
return await axios.post(`${process.env.AMP_HOST}/API/ADSModule/RestartInstance`, {
SESSIONID,
InstanceName
}).then(response => {
console.log(response.data)
//if (!response.data.success) return { status: 'fail', data: response.data }
return { status: 'success', data: response.data }
}).catch(error => {
console.error(error)
return { status: 'error', data: error }
})
},
async Servers(SESSIONID: string, InstanceId: string) {
return await axios.get(`${process.env.AMP_HOST}/API/ADSModule/Servers`, {
data: {
SESSIONID,
InstanceId
}
}).then(response => {
console.log(response)
console.log(response.data)
if (!response.data.result) return { status: 'fail', data: response.data }
return { status: 'success', data: response.data }
}).catch(error => {
console.error(error)
return { status: 'error', data: error }
})
}
}
export const Core = {
async Login(details: any) {
return await axios.post(`${process.env.AMP_HOST}/API/Core/Login`,
details
).then(response => {
if (!response.data.success) return { status: 'fail', data: response.data }
writeEnv('AMP_USERNAME', response.data.userInfo.Username)
writeEnv('AMP_SESSIONID', response.data.sessionID)
writeEnv('AMP_REMEMBER_TOKEN', response.data.rememberMeToken)
return { status: 'success', data: response.data }
}).catch(error => {
console.error(error)
return { status: 'error', data: error }
})
}
}
export async function CheckSession(SESSIONID: string) {
return await axios.post(`${process.env.AMP_HOST}/API/ADSModule/GetInstances`, {
SESSIONID
}).then(response => {
if (!response.data.result) return { status: 'fail', data: response.data }
return { status: 'success', data: response.data }
}).catch(error => {
console.error(error)
return { status: 'error', data: error }
})
}
+98
View File
@@ -0,0 +1,98 @@
import parseTorrent, { toMagnetURI } from 'parse-torrent'
import iconv from 'iconv-lite'
import axios from 'axios'
import path from 'path'
import fs from 'fs'
export declare class Game {
name: string
link: string
}
const headers = {
h1: {
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"x-requested-with": "XMLHttpRequest"
},
h2: {
"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",
"cache-control": "no-cache",
"pragma": "no-cache",
"sec-ch-ua": "\"Not=A?Brand\";v=\"8\", \"Chromium\";v=\"110\", \"Opera GX\";v=\"96\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"cookie": "online_fix_auth=gAAAAABkKM0s9WNLe_V6euTnJD7UQjppVty9B7OOyHBYOyVcbcejj8F6KveBcLxlf3mlx_vE7JEFPHlrpj-Aq6BFJyKPGzxds_wpcPV2MdXPyDGQLsz4mAvt3qgTgGg25MapWo_fSIOMiAAsF4Gv_uh4kUOiR_jgbHCZWJGPgpNQwU2HFFyvahYR6MzR7nYE9-fCmrev3obkRbro43vIVTTX4UyJMRHadrsY5Q-722TzinCZVmAuJfc=; dle_password=89465c26673e0199e5272e4730772c35; _ym_uid=1670534560361937997; _ym_d=1680394955; _ym_isad=2; dle_user_id=2619796; PHPSESSID=3v8sd281sr0n1n9f1p66q25sa2",
"Referer": "https://online-fix.me/",
"Referrer-Policy": "strict-origin-when-cross-origin"
}
}
export async function search(query: string) {
let body = await fetch("https://online-fix.me/engine/ajax/search.php", { headers: headers.h1, body: `query=${query}`, method: "POST" })
.then(response => response.arrayBuffer())
.then(arrayBuffer => { return iconv.decode(Buffer.from(arrayBuffer), 'win1251') })
.catch(console.error)
try {
if (!body) return
let matches = body.split('</div>')[1].split('<span class="seperator fastfullsearch">')[0].split('</a>')
let games = [] as Game[]
matches.pop()
matches.forEach(async match => {
let name = match.split('"><span class="searchheading">')[1].split('</span>')[0].slice(0, -8)
let link = match.split('<a href="')[1].split('"><span class="searchheading">')[0]
games.push({ name, link })
})
return games
} catch (error) { return error }
}
export async function repo(game: Game) {
let body = await fetch(game.link, { headers: headers.h2, body: null, method: "GET" })
.then(response => response.arrayBuffer())
.then(arrayBuffer => { return iconv.decode(Buffer.from(arrayBuffer), 'win1251') })
.catch(console.error)
try {
if (!body) return
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) }
}
export async function torrent(url: string) {
let response = await fetch(url, { headers: headers.h2, body: null, method: "GET" }).catch(console.error)
try {
if (!response) return
let body = await response.text()
let file = body.split('<a href="')[2].split('">')[0]
return file
} catch (error) { console.error(error) }
}
export async function download(url: string, file: string) {
let filePath = path.join(__dirname, '../../public/cracks/', file)
let writer = fs.createWriteStream(filePath)
try {
await axios({ url: url + file, method: 'GET', responseType: 'stream', headers: headers.h2 }).then(response => {
return new Promise((resolve, reject) => {
response.data.pipe(writer)
let error = null as unknown as Error
writer.on('error', err => { error = err; writer.close(); reject(err) })
writer.on('close', () => { if (!error) resolve(true) })
})
}).catch(console.error)
return filePath
} catch (error) { console.error(error) }
}
export async function magnet(filePath: string) {
let torrentData = parseTorrent(fs.readFileSync(filePath))
let uri = toMagnetURI(torrentData)
return uri
}
+4 -1
View File
@@ -1,4 +1,7 @@
module.exports = function (uptime) {
import { Client } from 'discord.js'
export default function (uptime: Client["uptime"]) {
if (!uptime) return '0J, 0H, 0M et 0S'
let days = Math.floor(uptime / 86400000)
let hours = Math.floor(uptime / 3600000) % 24
let minutes = Math.floor(uptime / 60000) % 60
+2 -2
View File
@@ -1,6 +1,6 @@
const fs = require('fs')
import fs from 'fs'
module.exports = writeEnv = ((variable, value) => {
export default ((variable: string, value: string) => {
let parsedFile = fs.readFileSync('./.env', 'utf8')
parsedFile = parsedFile.replace(new RegExp(`${variable} = .*`, 'g'), `${variable} = ${value}`)
fs.writeFileSync('./.env', parsedFile)
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
+1
View File
@@ -0,0 +1 @@
export default ['loop', 'pause', 'previous', 'resume', 'shuffle', 'skip', 'stop', 'volume_down', 'volume_up']
+40
View File
@@ -0,0 +1,40 @@
import { Client, TextChannel } from 'discord.js'
import { useQueue } from 'discord-player'
import getUptime from '../utils/getUptime'
import writeEnv from '../utils/writeEnv'
import generate from './generate'
export default async (client: Client) => {
let guild = client.guilds.cache.get(process.env.DISCORD_GUILD_ID as string)
if (!guild) {
clearInterval(client.disco.interval)
console.log(`Aucun serveur trouvé avec l'id \`${process.env.DISCORD_GUILD_ID}\`, veuillez utiliser la commande \`/setchannel\` !`)
return 'clear'
}
// Keep track of the music progress if the bot reboots
let queue = useQueue(guild.id)
if (queue) if (queue.isPlaying()) writeEnv('DISCORD_MUSIC_CURRENT_PROGRESS', queue.node.playbackTime.toString())
let channel = client.channels.cache.get(process.env.DISCORD_PLAYERCHANNEL_ID as string) as TextChannel
if (!channel) {
clearInterval(client.disco.interval)
console.log(`Aucun channel trouvé avec l'id \`${process.env.DISCORD_PLAYERCHANNEL_ID}\`, veuillez utiliser la commande \`/setchannel\` !`)
return 'clear'
}
let { embed, components } = await generate(guild)
if (components && embed.data.footer) embed.setFooter({ text: `Uptime: ${getUptime(client.uptime)} \n ${embed.data.footer.text}` })
else embed.setFooter({ text: `Uptime: ${getUptime(client.uptime)}` })
let messages = await channel.messages.fetch()
messages.forEach(msg => { if (msg.member) if (!msg.author.bot && !msg.member.roles.cache.has(process.env.DISCORD_ROLE_ID as string)) msg.delete() })
let botMessage = messages.find(msg => client.user && msg.author.id === client.user.id)
if (botMessage) {
if (!components && botMessage.components.length > 0) {
await botMessage.delete()
return channel.send({ embeds: [embed] })
} else if (components) return botMessage.edit({ embeds: [embed], components })
} else return channel.send({ embeds: [embed] })
}
+13
View File
@@ -0,0 +1,13 @@
import { ButtonInteraction } from 'discord.js'
import generatePlayer from './generate'
export default async (interaction: ButtonInteraction) => {
let guild = interaction.guild
if (!guild) return await interaction.reply({ content: 'Cette commande n\'est pas disponible en message privé.', ephemeral: true })
let { components } = await generatePlayer(guild)
if (!components) return
components.forEach((actionRow) => actionRow.components.forEach((button) => button.setDisabled(true)))
await interaction.update({ components })
}
+10 -11
View File
@@ -1,7 +1,7 @@
const { EmbedBuilder, ButtonBuilder, ActionRowBuilder } = require('discord.js')
const { useQueue } = require('discord-player')
import { EmbedBuilder, ButtonBuilder, ActionRowBuilder, Guild } from 'discord.js'
import { useQueue } from 'discord-player'
module.exports = async (guild) => {
export default async (guild: Guild) => {
let embed = new EmbedBuilder().setColor('#ffc370')
let queue = useQueue(guild.id)
@@ -24,15 +24,14 @@ module.exports = async (guild) => {
{ name: 'Durée', value: track.duration, inline: true },
{ name: 'Source', value: track.source === 'youtube' ? 'Youtube' : track.source === 'spotify' ? 'Spotify' : 'Inconnu', inline: true },
{ name: 'Volume', value: `${queue.node.volume}%`, inline: true },
{ name: queue.node.isPaused() ? 'Progression (en pause)' : 'Progression', value: queue.node.createProgressBar() },
{ name: 'Loop', value: queue.repeatMode ? queue.repeatMode === 2 ? "File d'Attente" : "Titre" : "Off", inline: true },
{ name: 'Autoplay', value: queue.autoplay ? "On" : "Off", inline: true }
{ name: queue.node.isPaused() ? 'Progression (en pause)' : 'Progression', value: queue.node.createProgressBar() || 'Aucune' },
{ name: 'Loop', value: queue.repeatMode === 3 ? 'Autoplay' : queue.repeatMode === 2 ? 'File d\'Attente' : queue.repeatMode === 1 ? 'Titre' : 'Off', inline: true }
)
.setDescription(`**Musique suivante :** ${queue.tracks.data[0] ? queue.tracks.data[0].title : 'Aucune'}`)
.setFooter({ text: `Demandé par ${track.requestedBy.tag}` })
.setFooter({ text: `Demandé par ${track.requestedBy ? track.requestedBy.tag : 'Inconnu'}` })
let components = [
new ActionRowBuilder().addComponents(
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setLabel(queue.node.isPaused() ? '▶️' : '⏸️')
.setStyle(2)
@@ -57,7 +56,7 @@ module.exports = async (guild) => {
.setCustomId('volume_up')
.setDisabled(queue.node.volume === 100)
),
new ActionRowBuilder().addComponents(
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setLabel('🔀')
.setStyle(2)
@@ -70,7 +69,7 @@ module.exports = async (guild) => {
.setLabel('⏮️')
.setStyle(2)
.setCustomId('previous')
.setDisabled(queue.previousTracks ? !queue.previousTracks[0] : true)
.setDisabled(queue.history.previousTrack ? false : true)
)
]
return ({ embed, components })
Loaded 100 of 108 files, more files were not shown because too many files have changed in this diff. Show more