Réécriture complète en Typescript
This commit is contained in:
14
.dockerignore
Normal file → Executable file
14
.dockerignore
Normal file → Executable file
@@ -1,9 +1,7 @@
|
||||
**/.dockerignore
|
||||
**/.git
|
||||
**/.gitattributes
|
||||
**/.gitignore
|
||||
**/.vscode
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
.dockerignore
|
||||
.git
|
||||
.gitignore
|
||||
.vscode
|
||||
Dockerfile
|
||||
node_modules
|
||||
README.md
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest"
|
||||
},
|
||||
|
||||
"env": {
|
||||
"es6": true
|
||||
}
|
||||
}
|
||||
63
.gitattributes
vendored
63
.gitattributes
vendored
@@ -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
|
||||
6
.gitignore
vendored
Normal file → Executable file
6
.gitignore
vendored
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
node_modules/
|
||||
.env
|
||||
cracks/
|
||||
stronger_shorter.mp3
|
||||
public/cracks/
|
||||
dist/
|
||||
.env*
|
||||
167
.npmrc
167
.npmrc
@@ -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
|
||||
43
.vscode/launch.json
vendored
Normal file → Executable file
43
.vscode/launch.json
vendored
Normal file → Executable 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",
|
||||
|
||||
3
.vscode/settings.json
vendored
Executable file
3
.vscode/settings.json
vendored
Executable 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
.vscode/tasks.json
vendored
28
.vscode/tasks.json
vendored
@@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
23
Dockerfile
Normal file → Executable file
23
Dockerfile
Normal file → Executable 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
app.js
67
app.js
@@ -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()
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 !' })
|
||||
}
|
||||
}
|
||||
@@ -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 !')
|
||||
}
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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 !')
|
||||
}
|
||||
}
|
||||
@@ -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 !')
|
||||
}
|
||||
}
|
||||
@@ -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 !')
|
||||
}
|
||||
}
|
||||
@@ -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 !')
|
||||
}
|
||||
}
|
||||
@@ -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 !')
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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 !`)
|
||||
}
|
||||
}
|
||||
@@ -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 !")
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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 !`)
|
||||
}
|
||||
}
|
||||
@@ -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}** !`)
|
||||
}
|
||||
}
|
||||
2281
package-lock.json
generated
Normal file → Executable file
2281
package-lock.json
generated
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
59
package.json
59
package.json
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
11
buttons/loop.js → src/buttons/loop.ts
Normal file → Executable file
11
buttons/loop.js → src/buttons/loop.ts
Normal file → Executable 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
src/buttons/pause.ts
Executable file
15
src/buttons/pause.ts
Executable 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
src/buttons/previous.ts
Executable file
15
src/buttons/previous.ts
Executable 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
src/buttons/resume.ts
Executable file
15
src/buttons/resume.ts
Executable 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
src/buttons/shuffle.ts
Executable file
15
src/buttons/shuffle.ts
Executable 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
src/buttons/skip.ts
Executable file
15
src/buttons/skip.ts
Executable 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
src/buttons/stop.ts
Executable file
15
src/buttons/stop.ts
Executable 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
src/buttons/volume_down.ts
Executable file
16
src/buttons/volume_down.ts
Executable 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
src/buttons/volume_up.ts
Executable file
16
src/buttons/volume_up.ts
Executable 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 })
|
||||
}
|
||||
}
|
||||
83
commands/global/amp.js → src/commands/global/amp.ts
Normal file → Executable file
83
commands/global/amp.js → src/commands/global/amp.ts
Normal file → Executable 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
src/commands/global/crack.ts
Executable file
58
src/commands/global/crack.ts
Executable 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
src/commands/global/papa.ts
Executable file
34
src/commands/global/papa.ts
Executable 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
src/commands/player/pause.ts
Executable file
15
src/commands/player/pause.ts
Executable 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
src/commands/player/previous.ts
Executable file
15
src/commands/player/previous.ts
Executable 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
src/commands/player/resume.ts
Executable file
15
src/commands/player/resume.ts
Executable 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
src/commands/player/shuffle.ts
Executable file
15
src/commands/player/shuffle.ts
Executable 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
src/commands/player/skip.ts
Executable file
15
src/commands/player/skip.ts
Executable 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
src/commands/player/stop.ts
Executable file
21
src/commands/player/stop.ts
Executable 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}% !`)
|
||||
}
|
||||
}
|
||||
4
events/error.js → src/events/error.ts
Normal file → Executable file
4
events/error.js → src/events/error.ts
Normal file → Executable 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
src/events/ready.ts
Executable file
30
src/events/ready.ts
Executable 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
|
||||
7
eventsPlayer/audioTrackAdd.js → src/eventsPlayer/audioTrackAdd.ts
Normal file → Executable file
7
eventsPlayer/audioTrackAdd.js → src/eventsPlayer/audioTrackAdd.ts
Normal file → Executable 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
src/eventsPlayer/audioTracksAdd.ts
Executable file
10
src/eventsPlayer/audioTracksAdd.ts
Executable 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 !`)
|
||||
}
|
||||
}
|
||||
6
eventsPlayer/debug.js → src/eventsPlayer/debug.ts
Normal file → Executable file
6
eventsPlayer/debug.js → src/eventsPlayer/debug.ts
Normal file → Executable 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}`)
|
||||
8
eventsPlayer/disconnect.js → src/eventsPlayer/disconnect.ts
Normal file → Executable file
8
eventsPlayer/disconnect.js → src/eventsPlayer/disconnect.ts
Normal file → Executable 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 !")
|
||||
|
||||
7
eventsPlayer/emptyChannel.js → src/eventsPlayer/emptyChannel.ts
Normal file → Executable file
7
eventsPlayer/emptyChannel.js → src/eventsPlayer/emptyChannel.ts
Normal file → Executable 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
src/eventsPlayer/emptyQueue.ts
Executable file
10
src/eventsPlayer/emptyQueue.ts
Executable 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
src/eventsPlayer/error.ts
Executable file
10
src/eventsPlayer/error.ts
Executable 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)
|
||||
}
|
||||
}
|
||||
6
eventsPlayer/playerError.js → src/eventsPlayer/playerError.ts
Normal file → Executable file
6
eventsPlayer/playerError.js → src/eventsPlayer/playerError.ts
Normal file → Executable 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
src/eventsPlayer/playerSkip.ts
Executable file
10
src/eventsPlayer/playerSkip.ts
Executable 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
src/eventsPlayer/playerStart.ts
Executable file
13
src/eventsPlayer/playerStart.ts
Executable 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)
|
||||
}
|
||||
}
|
||||
89
src/index.ts
Executable file
89
src/index.ts
Executable 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()
|
||||
0
parle.mp3 → src/static/parle.mp3
Normal file → Executable file
0
parle.mp3 → src/static/parle.mp3
Normal file → Executable file
95
src/utils/amp.ts
Normal file
95
src/utils/amp.ts
Normal 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
src/utils/crack.ts
Normal file
98
src/utils/crack.ts
Normal 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
|
||||
}
|
||||
5
utils/getUptime.js → src/utils/getUptime.ts
Normal file → Executable file
5
utils/getUptime.js → src/utils/getUptime.ts
Normal file → Executable 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
|
||||
4
utils/writeEnv.js → src/utils/writeEnv.ts
Normal file → Executable file
4
utils/writeEnv.js → src/utils/writeEnv.ts
Normal file → Executable 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)
|
||||
0
utilsAMP/ADSModule/GetInstances.js → src/utilsAMP/ADSModule/GetInstances.ts
Normal file → Executable file
0
utilsAMP/ADSModule/GetInstances.js → src/utilsAMP/ADSModule/GetInstances.ts
Normal file → Executable file
0
utilsAMP/ADSModule/ManageInstance.js → src/utilsAMP/ADSModule/ManageInstance.ts
Normal file → Executable file
0
utilsAMP/ADSModule/ManageInstance.js → src/utilsAMP/ADSModule/ManageInstance.ts
Normal file → Executable file
0
utilsAMP/ADSModule/RestartInstance.js → src/utilsAMP/ADSModule/RestartInstance.ts
Normal file → Executable file
0
utilsAMP/ADSModule/RestartInstance.js → src/utilsAMP/ADSModule/RestartInstance.ts
Normal file → Executable file
0
utilsAMP/ADSModule/Servers.js → src/utilsAMP/ADSModule/Servers.ts
Normal file → Executable file
0
utilsAMP/ADSModule/Servers.js → src/utilsAMP/ADSModule/Servers.ts
Normal file → Executable file
0
utilsAMP/CheckSession.js → src/utilsAMP/CheckSession.ts
Normal file → Executable file
0
utilsAMP/CheckSession.js → src/utilsAMP/CheckSession.ts
Normal file → Executable file
0
utilsAMP/Core/Login.js → src/utilsAMP/Core/Login.ts
Normal file → Executable file
0
utilsAMP/Core/Login.js → src/utilsAMP/Core/Login.ts
Normal file → Executable file
0
utilsCrack/download.js → src/utilsCrack/download.ts
Normal file → Executable file
0
utilsCrack/download.js → src/utilsCrack/download.ts
Normal file → Executable file
0
utilsCrack/headers.js → src/utilsCrack/headers.ts
Normal file → Executable file
0
utilsCrack/headers.js → src/utilsCrack/headers.ts
Normal file → Executable file
0
utilsCrack/magnet.js → src/utilsCrack/magnet.ts
Normal file → Executable file
0
utilsCrack/magnet.js → src/utilsCrack/magnet.ts
Normal file → Executable file
0
utilsCrack/repo.js → src/utilsCrack/repo.ts
Normal file → Executable file
0
utilsCrack/repo.js → src/utilsCrack/repo.ts
Normal file → Executable file
0
utilsCrack/search.js → src/utilsCrack/search.ts
Normal file → Executable file
0
utilsCrack/search.js → src/utilsCrack/search.ts
Normal file → Executable file
0
utilsCrack/torrent.js → src/utilsCrack/torrent.ts
Normal file → Executable file
0
utilsCrack/torrent.js → src/utilsCrack/torrent.ts
Normal file → Executable file
1
src/utilsPlayer/buttons.ts
Executable file
1
src/utilsPlayer/buttons.ts
Executable file
@@ -0,0 +1 @@
|
||||
export default ['loop', 'pause', 'previous', 'resume', 'shuffle', 'skip', 'stop', 'volume_down', 'volume_up']
|
||||
40
src/utilsPlayer/disco.ts
Executable file
40
src/utilsPlayer/disco.ts
Executable 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
src/utilsPlayer/edit.ts
Executable file
13
src/utilsPlayer/edit.ts
Executable 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 })
|
||||
}
|
||||
19
utilsPlayer/generate.js → src/utilsPlayer/generate.ts
Normal file → Executable file
19
utilsPlayer/generate.js → src/utilsPlayer/generate.ts
Normal file → Executable 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 })
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user