From 94c7fc1c9839800b71db34efbb0d9909ef66ce5a Mon Sep 17 00:00:00 2001 From: Angels-dev Date: Thu, 29 Feb 2024 00:24:21 +0100 Subject: [PATCH] =?UTF-8?q?Int=C3=A9gration=20MongoDB=20+=20Fix=20export?= =?UTF-8?q?=20et=20amp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 191 ++++++++- package.json | 4 +- src/buttons/loop.ts | 30 +- src/buttons/pause.ts | 28 +- src/buttons/previous.ts | 28 +- src/buttons/resume.ts | 28 +- src/buttons/shuffle.ts | 28 +- src/buttons/skip.ts | 28 +- src/buttons/stop.ts | 28 +- src/buttons/volume_down.ts | 30 +- src/buttons/volume_up.ts | 30 +- src/commands/global/amp.ts | 396 +++++++++--------- src/commands/global/crack.ts | 114 ++--- src/commands/global/database.ts | 73 ++++ src/commands/global/papa.ts | 66 +-- src/commands/global/parle.ts | 156 +++---- src/commands/global/ping.ts | 20 +- src/commands/global/spam.ts | 56 +-- src/commands/global/update.ts | 36 +- src/commands/player/loop.ts | 40 +- src/commands/player/lyrics.ts | 88 ++-- src/commands/player/pause.ts | 28 +- src/commands/player/play.ts | 26 +- src/commands/player/previous.ts | 28 +- src/commands/player/resume.ts | 28 +- src/commands/player/shuffle.ts | 28 +- src/commands/player/skip.ts | 28 +- src/commands/player/stop.ts | 34 +- src/commands/player/volume.ts | 40 +- src/events/{ => client}/error.ts | 2 +- src/events/client/guildCreate.ts | 14 + src/events/{ => client}/guildMemberAdd.ts | 36 +- src/events/{ => client}/guildMemberRemove.ts | 36 +- src/events/client/guildUpdate.ts | 19 + src/events/{ => client}/interactionCreate.ts | 87 ++-- src/events/client/ready.ts | 55 +++ src/events/{ => client}/voiceStateUpdate.ts | 116 ++--- src/events/mongo/connected.ts | 8 + src/events/mongo/connecting.ts | 8 + src/events/mongo/disconnected.ts | 8 + src/events/mongo/error.ts | 8 + .../player}/audioTrackAdd.ts | 18 +- .../player}/audioTracksAdd.ts | 18 +- src/{eventsPlayer => events/player}/debug.ts | 18 +- src/events/player/disconnect.ts | 24 ++ .../player}/emptyChannel.ts | 20 +- .../player}/emptyQueue.ts | 18 +- src/{eventsPlayer => events/player}/error.ts | 18 +- .../player}/playerError.ts | 18 +- .../player}/playerSkip.ts | 18 +- src/events/player/playerStart.ts | 22 + src/events/ready.ts | 39 -- src/eventsPlayer/disconnect.ts | 16 - src/eventsPlayer/playerStart.ts | 13 - src/index.ts | 128 +++--- src/schemas/guild.ts | 39 ++ src/utils/amp.ts | 41 +- src/utils/dbGuildInit.ts | 20 + src/utils/rss.ts | 78 ++-- src/utils/writeEnv.ts | 7 - src/utilsPlayer/bots.ts | 1 + src/utilsPlayer/disco.ts | 33 +- src/utilsPlayer/replay.ts | 27 +- 63 files changed, 1608 insertions(+), 1161 deletions(-) create mode 100755 src/commands/global/database.ts rename src/events/{ => client}/error.ts (84%) create mode 100755 src/events/client/guildCreate.ts rename src/events/{ => client}/guildMemberAdd.ts (94%) rename src/events/{ => client}/guildMemberRemove.ts (94%) create mode 100755 src/events/client/guildUpdate.ts rename src/events/{ => client}/interactionCreate.ts (92%) create mode 100755 src/events/client/ready.ts rename src/events/{ => client}/voiceStateUpdate.ts (97%) create mode 100644 src/events/mongo/connected.ts create mode 100644 src/events/mongo/connecting.ts create mode 100644 src/events/mongo/disconnected.ts create mode 100644 src/events/mongo/error.ts rename src/{eventsPlayer => events/player}/audioTrackAdd.ts (82%) rename src/{eventsPlayer => events/player}/audioTracksAdd.ts (82%) rename src/{eventsPlayer => events/player}/debug.ts (96%) create mode 100755 src/events/player/disconnect.ts rename src/{eventsPlayer => events/player}/emptyChannel.ts (84%) rename src/{eventsPlayer => events/player}/emptyQueue.ts (77%) rename src/{eventsPlayer => events/player}/error.ts (96%) rename src/{eventsPlayer => events/player}/playerError.ts (96%) rename src/{eventsPlayer => events/player}/playerSkip.ts (82%) create mode 100755 src/events/player/playerStart.ts delete mode 100755 src/events/ready.ts delete mode 100755 src/eventsPlayer/disconnect.ts delete mode 100755 src/eventsPlayer/playerStart.ts create mode 100644 src/schemas/guild.ts create mode 100644 src/utils/dbGuildInit.ts delete mode 100755 src/utils/writeEnv.ts create mode 100644 src/utilsPlayer/bots.ts diff --git a/package-lock.json b/package-lock.json index bfa4d76..125e883 100755 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bot_tamiseur", - "version": "2.1.0", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bot_tamiseur", - "version": "2.1.0", + "version": "2.2.0", "dependencies": { "@discord-player/equalizer": "^0.2.3", "@discord-player/extractor": "^4.4.6", @@ -15,6 +15,7 @@ "@types/parse-torrent": "^5.8.7", "axios": "^1.6.7", "bufferutil": "^4.0.8", + "chalk": "^4.1.2", "discord-player": "^6.6.7", "discord.js": "^14.14.1", "dotenv": "^16.4.5", @@ -22,6 +23,7 @@ "jsdom": "^24.0.0", "libsodium-wrappers": "^0.7.13", "mariadb": "^3.2.3", + "mongoose": "^8.2.0", "parse-torrent": "^9.1.5", "play-dl": "^1.9.7", "require-all": "^3.0.0", @@ -330,6 +332,14 @@ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz", + "integrity": "sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -472,6 +482,19 @@ "@types/node": "*" } }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", @@ -585,7 +608,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -753,6 +775,14 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.3.0.tgz", + "integrity": "sha512-balJfqwwTBddxfnidJZagCBPP/f48zj9Sdp3OJswREOgsJzHiQSaOIAtApSgDQFYgHqAvFkp53AFSqjMDZoTFw==", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -842,7 +872,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -914,7 +943,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -925,8 +953,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/color-support": { "version": "1.1.3", @@ -1796,7 +1823,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2183,6 +2209,14 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2380,6 +2414,11 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -2533,6 +2572,128 @@ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, + "node_modules/mongodb": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz", + "integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^6.2.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mongoose": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.2.0.tgz", + "integrity": "sha512-la93n6zCYRbPS+c5N9oTDAktvREy5OT9OCljp1Tah0y3+p8UPMTAoabWaLZMdzYruOtF9/9GRf6MasaZjiZP1A==", + "dependencies": { + "bson": "^6.2.0", + "kareem": "2.5.1", + "mongodb": "6.3.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3433,6 +3594,11 @@ "node": ">=8" } }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -3554,6 +3720,14 @@ "undici": "^5.22.1" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/spotify-uri": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/spotify-uri/-/spotify-uri-4.0.1.tgz", @@ -3681,7 +3855,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, diff --git a/package.json b/package.json index 20ed94c..a43fc34 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bot_tamiseur", "description": "Listen to music and use fun commands with your friends!", - "version": "2.1.0", + "version": "2.2.0", "author": { "name": "Zachary Guénot" }, @@ -20,6 +20,7 @@ "@types/parse-torrent": "^5.8.7", "axios": "^1.6.7", "bufferutil": "^4.0.8", + "chalk": "^4.1.2", "discord-player": "^6.6.7", "discord.js": "^14.14.1", "dotenv": "^16.4.5", @@ -27,6 +28,7 @@ "jsdom": "^24.0.0", "libsodium-wrappers": "^0.7.13", "mariadb": "^3.2.3", + "mongoose": "^8.2.0", "parse-torrent": "^9.1.5", "play-dl": "^1.9.7", "require-all": "^3.0.0", diff --git a/src/buttons/loop.ts b/src/buttons/loop.ts index 823634c..d6e59ff 100755 --- a/src/buttons/loop.ts +++ b/src/buttons/loop.ts @@ -1,16 +1,16 @@ -import { ButtonInteraction } from 'discord.js' -import { useQueue } from 'discord-player' - -module.exports = { - id: 'loop', - 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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + id: 'loop', + 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 }) + } } \ No newline at end of file diff --git a/src/buttons/pause.ts b/src/buttons/pause.ts index 6c5bd31..f4b8b3f 100755 --- a/src/buttons/pause.ts +++ b/src/buttons/pause.ts @@ -1,15 +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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 }) + } } \ No newline at end of file diff --git a/src/buttons/previous.ts b/src/buttons/previous.ts index 07545f3..310bb1a 100755 --- a/src/buttons/previous.ts +++ b/src/buttons/previous.ts @@ -1,15 +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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useHistory } from 'discord-player' + +export default { + 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 }) + } } \ No newline at end of file diff --git a/src/buttons/resume.ts b/src/buttons/resume.ts index fbdbc92..16ad3ac 100755 --- a/src/buttons/resume.ts +++ b/src/buttons/resume.ts @@ -1,15 +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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 }) + } } \ No newline at end of file diff --git a/src/buttons/shuffle.ts b/src/buttons/shuffle.ts index 9d56664..1f212b3 100755 --- a/src/buttons/shuffle.ts +++ b/src/buttons/shuffle.ts @@ -1,15 +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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 }) + } } \ No newline at end of file diff --git a/src/buttons/skip.ts b/src/buttons/skip.ts index b0c47c8..664fafe 100755 --- a/src/buttons/skip.ts +++ b/src/buttons/skip.ts @@ -1,15 +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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 }) + } } \ No newline at end of file diff --git a/src/buttons/stop.ts b/src/buttons/stop.ts index 82f7cc1..c1095a4 100755 --- a/src/buttons/stop.ts +++ b/src/buttons/stop.ts @@ -1,15 +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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 }) + } } \ No newline at end of file diff --git a/src/buttons/volume_down.ts b/src/buttons/volume_down.ts index dfe126e..943f39d 100755 --- a/src/buttons/volume_down.ts +++ b/src/buttons/volume_down.ts @@ -1,16 +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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 }) + } } \ No newline at end of file diff --git a/src/buttons/volume_up.ts b/src/buttons/volume_up.ts index c08d4b2..e854d81 100755 --- a/src/buttons/volume_up.ts +++ b/src/buttons/volume_up.ts @@ -1,16 +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 }) - } +import { ButtonInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 }) + } } \ No newline at end of file diff --git a/src/commands/global/amp.ts b/src/commands/global/amp.ts index d03ba32..5bc00cd 100755 --- a/src/commands/global/amp.ts +++ b/src/commands/global/amp.ts @@ -1,198 +1,200 @@ -import { SlashCommandBuilder, ChatInputCommandInteraction, AutocompleteInteraction, EmbedBuilder, inlineCode } from 'discord.js' -import * as AMP from '../../utils/amp' -import 'dotenv/config' - -interface ListInstancesResult { - status: string - data: { - result: [ - Host: { - AvailableInstances: any[] - FriendlyName: string - } - ] - } -} -interface InstanceFields { - name: string - value: string - inline: boolean -} - -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 !') - .addSubcommand(subcommand => subcommand.setName('login').setDescription("Connectez-vous avant d'effectuer une autre commande !") - .addStringOption(option => option.setName('username').setDescription("Nom d'Utilisateur").setRequired(true)) - .addStringOption(option => option.setName('password').setDescription('Mot de Passe').setRequired(true)) - .addBooleanOption(option => option.setName('remember').setDescription('Mémoriser les identifiants').setRequired(true)) - .addStringOption(option => option.setName('otp').setDescription('Code de double authentification'))) - - .addSubcommandGroup(subcommandgroup => subcommandgroup.setName('instances').setDescription('Intéragir avec les instances AMP.') - .addSubcommand(subcommand => subcommand.setName('list').setDescription('Liste toutes les instances disponibles.')) - - .addSubcommand(subcommand => subcommand.setName('manage').setDescription('Gérer une instance.') - .addStringOption(option => option.setName('instance').setDescription("Nom de l'instance").setRequired(true).setAutocomplete(true))) - - /*.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: AutocompleteInteraction) { - let query = interaction.options.getString('instance', true) - - // Check if the SessionID is still valid - //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 - let details = { - username: process.env.AMP_USERNAME, - password: '', - token: process.env.AMP_REMEMBER_TOKEN, - rememberMe: true - } - 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([]) - else if (result.status === 'error') return interaction.respond([]) - } - 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.respond([]) - } - } - else if (session.status === 'error') return interaction.respond([]) - - let choices: any = [] - let result = await AMP.ADSModule.GetInstances(sessionID) - if (result.status === 'success') { - let hosts = result.data.result as any[] - hosts.forEach(host => { - let instances = host.AvailableInstances as any[] - instances.forEach(instance => { - if (instance.FriendlyName.includes(query)) choices.push({ name: `${host.FriendlyName} - ${instance.FriendlyName}`, value: instance.InstanceID }) - }) - }) - } - else if (result.status === 'fail') return interaction.respond([]) - else if (result.status === 'error') return interaction.respond([]) - - return interaction.respond(choices) - }, - async execute(interaction: ChatInputCommandInteraction) { - // Let the user login - if (interaction.options.getSubcommand() == 'login') { - // Get a SessionID and a RememberMeToken if wanted - await interaction.deferReply({ ephemeral: true }) - - let details = { - username: interaction.options.getString('username'), - password: interaction.options.getString('password'), - token: interaction.options.getString('otp') || '', - rememberMe: interaction.options.getBoolean('remember') - } - - 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)) - } - await interaction.deferReply() - - // Check if the SessionID is still valid - //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) - if (process.env.AMP_REMEMBER_TOKEN) { - // Refresh the SessionID if the RememberMeToken is available - let details = { - username: process.env.AMP_USERNAME, - password: '', - token: process.env.AMP_REMEMBER_TOKEN, - rememberMe: true - } - 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)) - else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data)) - } - else { - // If no RememberMeToken is available, ask to login - return await interaction.followUp(`Tu dois te connecter avant d'effectuer une autre commande !`) - } - } - else if (session.status === 'error') return await interaction.followUp(errorMsg(session.data)) - - if (interaction.options.getSubcommandGroup() == 'instances') { - if (interaction.options.getSubcommand() == 'list') { - 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 = [] as InstanceFields[] - host.AvailableInstances.forEach(instance => { - fields.push({ - name: instance.FriendlyName, - value: `**Running:** ${instance.Running}\n**Port:** ${instance.Port}\n**Module:** ${instance.Module}`, - inline: true - }) - }) - let embed = new EmbedBuilder() - .setTitle(host.FriendlyName) - .setDescription(`Liste des ${host.AvailableInstances.length} instances :`) - .setColor(interaction.guild?.members.me?.displayColor || '#ffc370') - .setTimestamp() - .setFields(fields) - return await interaction.channel?.send({ embeds: [embed] }) - }) - } - else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data)) - else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data)) - } - else if (interaction.options.getSubcommand() == 'manage') { - let instanceID = interaction.options.getString('instance', true) - let result = await AMP.ADSModule.ManageInstance(sessionID, instanceID) - - if (result.status === 'success') { - let server = await AMP.ADSModule.Servers(sessionID, instanceID) - console.log(server) - - if (server.status === 'success') return await interaction.followUp(`Ok !`) - else if (server.status === 'fail') return await interaction.followUp(failMsg(server.data)) - else if (server.status === 'error') return await interaction.followUp(errorMsg(server.data)) - } - else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data)) - else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data)) - } - else if (interaction.options.getSubcommand() == 'restart') { - let query = interaction.options.getString('name') - 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)) - else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data)) - } - } - } +import { SlashCommandBuilder, ChatInputCommandInteraction, AutocompleteInteraction, EmbedBuilder, inlineCode } from 'discord.js' +import * as AMP from '../../utils/amp' +import dbGuild from '../../schemas/guild' + +interface ListInstancesResult { + status: string + data: [ + Host: { + AvailableInstances: any[] + FriendlyName: string + } + ] +} +interface InstanceFields { + name: string + value: string + inline: boolean +} + +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}`)}` } + +export default { + data: new SlashCommandBuilder().setName('amp').setDescription('Accède à mon panel de jeu AMP !') + .addSubcommand(subcommand => subcommand.setName('login').setDescription("Connectez-vous avant d'effectuer une autre commande !") + .addStringOption(option => option.setName('username').setDescription("Nom d'Utilisateur").setRequired(true)) + .addStringOption(option => option.setName('password').setDescription('Mot de Passe').setRequired(true)) + .addBooleanOption(option => option.setName('remember').setDescription('Mémoriser les identifiants').setRequired(true)) + .addStringOption(option => option.setName('otp').setDescription('Code de double authentification'))) + .addSubcommandGroup(subcommandgroup => subcommandgroup.setName('instances').setDescription('Intéragir avec les instances AMP.') + .addSubcommand(subcommand => subcommand.setName('list').setDescription('Liste toutes les instances disponibles.')) + .addSubcommand(subcommand => subcommand.setName('manage').setDescription('Gérer une instance.') + .addStringOption(option => option.setName('instance').setDescription("Nom de l'instance").setRequired(true).setAutocomplete(true))) + .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: AutocompleteInteraction) { + let query = interaction.options.getString('instance', true) + + let guildProfile = await dbGuild.findOne({ guildId: interaction?.guild?.id }) + if (!guildProfile) return await interaction.respond([]) + + let dbData = guildProfile.get('guildAmp') + if (!dbData?.enabled) return await interaction.respond([]) + + let host = dbData.host as string + let username = dbData.username as string + let sessionID = dbData.sessionID as string + let rememberMeToken = dbData.rememberMeToken as string + + // Check if the SessionID is still valid + let session = await AMP.CheckSession(host, sessionID) + if (session.status === 'fail') { + if (rememberMeToken) { + // Refresh the SessionID if the RememberMeToken is available + let details = { username, password: '', token: rememberMeToken, rememberMe: true } + let result = await AMP.Core.Login(host, details) + + if (result.status === 'success') sessionID = result.data.sessionID + else if (result.status === 'fail') return interaction.respond([]) + else if (result.status === 'error') return interaction.respond([]) + } else return await interaction.respond([]) + } + else if (session.status === 'error') return interaction.respond([]) + + let choices: any = [] + let result = await AMP.ADSModule.GetInstances(host, sessionID) + if (result.status === 'success') { + let hosts = result.data.result as any[] + hosts.forEach(host => { + let instances = host.AvailableInstances as any[] + instances.forEach(instance => { + if (instance.FriendlyName.includes(query)) choices.push({ name: `${host.FriendlyName} - ${instance.FriendlyName}`, value: instance.InstanceID }) + }) + }) + } + else if (result.status === 'fail') return interaction.respond([]) + else if (result.status === 'error') return interaction.respond([]) + + return interaction.respond(choices) + }, + async execute(interaction: ChatInputCommandInteraction) { + let guildProfile = await dbGuild.findOne({ guildId: interaction?.guild?.id }) + if (!guildProfile) return interaction.reply({ content: `Database data for **${interaction.guild?.name}** does not exist, please initialize with \`/database init\` !` }) + + let dbData = guildProfile.get('guildAmp') + if (!dbData?.enabled) return interaction.reply({ content: `AMP module is disabled for **${interaction.guild?.name}**, please activate with \`/database edit guildAmp.enabled True\` !` }) + + let host = dbData.host as string + let username = dbData.username as string + let sessionID = dbData.sessionID as string + let rememberMeToken = dbData.rememberMeToken as string + + // Let the user login + if (interaction.options.getSubcommand() == 'login') { + // Get a SessionID and a RememberMeToken if wanted + await interaction.deferReply({ ephemeral: true }) + + let details = { + username: interaction.options.getString('username'), + password: interaction.options.getString('password'), + token: interaction.options.getString('otp') || '', + rememberMe: interaction.options.getBoolean('remember') + } + + let result = await AMP.Core.Login(host, details) + if (result.status === 'success') { + username = dbData['username'] = result.data.userInfo.Username + sessionID = dbData['sessionID'] = result.data.sessionID + rememberMeToken = dbData['rememberMeToken'] = result.data.rememberMeToken + + guildProfile.set('guildAmp', dbData) + guildProfile.markModified('guildAmp') + await guildProfile.save().catch(console.error) + + return await interaction.followUp(`Tu es connecté au panel sous **${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)) + } + await interaction.deferReply() + + // Check if the SessionID is still valid + let session = await AMP.CheckSession(host, sessionID) + if (session.status === 'fail') { + if (rememberMeToken) { + // Refresh the SessionID if the RememberMeToken is available + let details = { username, password: '', token: rememberMeToken, rememberMe: true } + let result = await AMP.Core.Login(host, details) + + if (result.status === 'success') sessionID = result.data.sessionID + else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data)) + else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data)) + } + else return await interaction.followUp(`Tu dois te connecter avant d'effectuer une autre commande !`) + } + else if (session.status === 'error') return await interaction.followUp(errorMsg(session.data)) + + if (interaction.options.getSubcommandGroup() == 'instances') { + if (interaction.options.getSubcommand() == 'list') { + let result = await AMP.ADSModule.GetInstances(host, sessionID) as ListInstancesResult + + if (result.status === 'success') { + await interaction.followUp({ content: `${result.data.length} hôte(s) trouvé(s) !` }) + result.data.forEach(async host => { + let fields = [] as InstanceFields[] + host.AvailableInstances.forEach(instance => { + fields.push({ + name: instance.FriendlyName, + value: `**Running:** ${instance.Running}\n**Port:** ${instance.Port}\n**Module:** ${instance.Module}`, + inline: true + }) + }) + let embed = new EmbedBuilder() + .setTitle(host.FriendlyName) + .setDescription(`Liste des ${host.AvailableInstances.length} instances :`) + .setColor(interaction.guild?.members.me?.displayColor || '#ffc370') + .setTimestamp() + .setFields(fields) + return await interaction.channel?.send({ embeds: [embed] }) + }) + } + else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data)) + else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data)) + } + else if (interaction.options.getSubcommand() == 'manage') { + let instanceID = interaction.options.getString('instance', true) + let result = await AMP.ADSModule.ManageInstance(host, sessionID, instanceID) + + if (result.status === 'success') { + let server = await AMP.ADSModule.Servers(host, sessionID, instanceID) + + if (server.status === 'success') return await interaction.followUp(`Ok !`) + else if (server.status === 'fail') return await interaction.followUp(failMsg(server.data)) + else if (server.status === 'error') return await interaction.followUp(errorMsg(server.data)) + } + else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data)) + else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data)) + } + else if (interaction.options.getSubcommand() == 'restart') { + let query = interaction.options.getString('name') + if (!query) return + + let result = await AMP.ADSModule.RestartInstance(host, sessionID, query) + + if (result.status === 'success') return await interaction.followUp(`Ok !`) + else if (result.status === 'fail') return await interaction.followUp(failMsg(result.data)) + else if (result.status === 'error') return await interaction.followUp(errorMsg(result.data)) + } + } + } } \ No newline at end of file diff --git a/src/commands/global/crack.ts b/src/commands/global/crack.ts index 508b49d..a1c7c02 100755 --- a/src/commands/global/crack.ts +++ b/src/commands/global/crack.ts @@ -1,58 +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] }) - } +import { SlashCommandBuilder, EmbedBuilder, ChatInputCommandInteraction, MessageReaction, User }from 'discord.js' +import * as crack from '../../utils/crack' + +export default { + 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] }) + } } \ No newline at end of file diff --git a/src/commands/global/database.ts b/src/commands/global/database.ts new file mode 100755 index 0000000..b1b8296 --- /dev/null +++ b/src/commands/global/database.ts @@ -0,0 +1,73 @@ +import { SlashCommandBuilder, ChatInputCommandInteraction, EmbedBuilder, APIEmbedField } from 'discord.js' + +import dbGuildInit from '../../utils/dbGuildInit' +import dbGuild from '../../schemas/guild' + +const parseObject = (obj: any, prefix = ''): { name: string, value: any }[] => { + let fields: { name: string, value: any }[] = [] + + for (let [key, value] of Object.entries(obj)) { + if (typeof value === 'object') fields.push(...parseObject(value, `${prefix}${key}.`)) + else { + if (typeof value === 'boolean') value = value ? 'True' : 'False' + else if (!value) value = 'None' + else value = value.toString() + + fields.push({ name: `${prefix}${key}`, value }) + } + } + return fields +} + +export default { + data: new SlashCommandBuilder() + .setName('database') + .setDescription('Communicate with the database') + .addSubcommand(subcommand => subcommand.setName('info').setDescription('Returns information about the current guild')) + .addSubcommand(subcommand => subcommand.setName('init').setDescription('Force initialize an entry for the current guild in the database')) + .addSubcommand(subcommand => subcommand.setName('edit').setDescription('Modify parameters for the current guild') + .addStringOption(option => option.setName('key').setDescription('Key to modify').setRequired(true)) + .addStringOption(option => option.setName('value').setDescription('Value to set').setRequired(true))), + async execute(interaction: ChatInputCommandInteraction) { + let guild = interaction.guild + if (!guild) return await interaction.reply({ content: 'This command must be used in a server.', ephemeral: true }) + + let guildProfile = await dbGuild.findOne({ guildId: guild.id }) + + if (interaction.options.getSubcommand() === 'info') { + if (!guildProfile) return await interaction.reply({ content: `Database data for **${guild.name}** does not exist !` }) + + let fields = parseObject(guildProfile.toObject()) + + let embed = new EmbedBuilder() + .setTitle('Database Information') + .setDescription(`Guild **${guildProfile.guildName}** (ID: ${guildProfile.guildId})`) + .setThumbnail(guildProfile.guildIcon as string) + .setTimestamp() + .addFields(fields as APIEmbedField[]) + return await interaction.reply({ embeds: [embed] }) + + } else if (interaction.options.getSubcommand() === 'init') { + if (guildProfile) return await interaction.reply({ content: `Database data for **${guildProfile.guildName}** already exists !` }) + + guildProfile = await dbGuildInit(guild) + if (!guildProfile) return await interaction.reply({ content: `An error occured while initializing database data for **${guild.name}** !` }) + + return await interaction.reply({ content: `Database data for **${guildProfile.guildName}** successfully initialized !` }) + + } else if (interaction.options.getSubcommand() === 'edit') { + if (!guildProfile) return await interaction.reply({ content: `Database data for **${guild.name}** does not exist, please init with \`/database init\` !` }) + + let key = interaction.options.getString('key', true) + let value = interaction.options.getString('value', true) + + let oldValue = guildProfile.get(key) + if (!oldValue) oldValue = 'None' + + guildProfile.set(key, value) + await guildProfile.save().catch(console.error) + + return await interaction.reply({ content: `Database data for **${guildProfile.guildName}** successfully updated !\n**${key}**: ${oldValue} -> ${value}` }) + } + } +} \ No newline at end of file diff --git a/src/commands/global/papa.ts b/src/commands/global/papa.ts index 5a20965..849744d 100755 --- a/src/commands/global/papa.ts +++ b/src/commands/global/papa.ts @@ -1,34 +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 !' }) - } +import { SlashCommandBuilder, ChatInputCommandInteraction, GuildMember } from 'discord.js' +import { getVoiceConnection, joinVoiceChannel } from '@discordjs/voice' + +export default { + 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 !' }) + } } \ No newline at end of file diff --git a/src/commands/global/parle.ts b/src/commands/global/parle.ts index 41dfa4a..36e95d0 100755 --- a/src/commands/global/parle.ts +++ b/src/commands/global/parle.ts @@ -1,79 +1,79 @@ -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: 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') - 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 (!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 (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 }) - - /* - // Searches for audio files uploaded in the channel - let messages = await interaction.channel.messages.fetch({ limit: 10, cache: false }) - messages = messages.filter(m => m.attachments.size > 0) - - let files = [] - await messages.forEach(m => m.attachments.forEach(a => { - if (a.contentType === 'audio/mpeg') files.push(a) - })) - if (files.size === 0) return await interaction.editReply({ content: 'Aucun fichier audio trouvé dans ce channel.', ephemeral: true }) - - // Limit the number of files to the last 10 - //files = files.sort((a, b) => b.createdTimestamp - a.createdTimestamp).first(10) - - // Ask the user to choose a file - let file = await interaction.channel.send({ content: 'Choisissez un fichier audio :', files: files }) - let filter = m => m.author.id === interaction.user.id && !isNaN(m.content) && parseInt(m.content) > 0 && parseInt(m.content) <= files.size - let response = await interaction.channel.awaitMessages({ filter, max: 1, time: 30000, errors: ['time'] }) - file = files.get(files.keyArray()[response.first().content - 1]) - */ - - let playing = false - let player = createAudioPlayer() - player.on(AudioPlayerStatus.Idle, () => { playing = false }) - - let connection = joinVoiceChannel({ - 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('../../static/parle.mp3', { inlineVolume: true }) - //let resource = createAudioResource(file.attachments.first().url, { inlineVolume: true }) - if (resource.volume) resource.volume.setVolume(0.2) - player.play(resource) - } - }) - - interaction.client.on('voiceStateUpdate', (oldState, newState) => { - if (oldState.id === member.id && newState.channelId !== caller.voice.channelId) { - stream.destroy() - connection.disconnect() - } - }) - } +import { SlashCommandBuilder, ChatInputCommandInteraction, GuildMember } from 'discord.js' +import { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, EndBehaviorType } from '@discordjs/voice' + +export default { + 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: 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') + 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 (!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 (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 }) + + /* + // Searches for audio files uploaded in the channel + let messages = await interaction.channel.messages.fetch({ limit: 10, cache: false }) + messages = messages.filter(m => m.attachments.size > 0) + + let files = [] + await messages.forEach(m => m.attachments.forEach(a => { + if (a.contentType === 'audio/mpeg') files.push(a) + })) + if (files.size === 0) return await interaction.editReply({ content: 'Aucun fichier audio trouvé dans ce channel.', ephemeral: true }) + + // Limit the number of files to the last 10 + //files = files.sort((a, b) => b.createdTimestamp - a.createdTimestamp).first(10) + + // Ask the user to choose a file + let file = await interaction.channel.send({ content: 'Choisissez un fichier audio :', files: files }) + let filter = m => m.author.id === interaction.user.id && !isNaN(m.content) && parseInt(m.content) > 0 && parseInt(m.content) <= files.size + let response = await interaction.channel.awaitMessages({ filter, max: 1, time: 30000, errors: ['time'] }) + file = files.get(files.keyArray()[response.first().content - 1]) + */ + + let playing = false + let player = createAudioPlayer() + player.on(AudioPlayerStatus.Idle, () => { playing = false }) + + let connection = joinVoiceChannel({ + 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('../../static/parle.mp3', { inlineVolume: true }) + //let resource = createAudioResource(file.attachments.first().url, { inlineVolume: true }) + if (resource.volume) resource.volume.setVolume(0.2) + player.play(resource) + } + }) + + interaction.client.on('voiceStateUpdate', (oldState, newState) => { + if (oldState.id === member.id && newState.channelId !== caller.voice.channelId) { + stream.destroy() + connection.disconnect() + } + }) + } } \ No newline at end of file diff --git a/src/commands/global/ping.ts b/src/commands/global/ping.ts index 1b78558..554fab8 100755 --- a/src/commands/global/ping.ts +++ b/src/commands/global/ping.ts @@ -1,11 +1,11 @@ -import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' - -module.exports = { - data: new SlashCommandBuilder() - .setName('ping') - .setDescription('Check the latency of the bot'), - 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`) - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' + +export default { + data: new SlashCommandBuilder() + .setName('ping') + .setDescription('Check the latency of the bot'), + 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`) + } } \ No newline at end of file diff --git a/src/commands/global/spam.ts b/src/commands/global/spam.ts index e007e7d..85dd3f1 100755 --- a/src/commands/global/spam.ts +++ b/src/commands/global/spam.ts @@ -1,29 +1,29 @@ -import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' - -module.exports = { - data: new SlashCommandBuilder() - .setName('spam') - .setDescription('Spam') - .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: 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() - }, 1000) - } - myLoop() - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' + +export default { + data: new SlashCommandBuilder() + .setName('spam') + .setDescription('Spam') + .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: 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() + }, 1000) + } + myLoop() + } } \ No newline at end of file diff --git a/src/commands/global/update.ts b/src/commands/global/update.ts index 0dfeae5..ce479a8 100755 --- a/src/commands/global/update.ts +++ b/src/commands/global/update.ts @@ -1,19 +1,19 @@ -import { SlashCommandBuilder, ChatInputCommandInteraction, Guild } from 'discord.js' - -module.exports = { - data: new SlashCommandBuilder() - .setName('update') - .setDescription('Update the member count channel.'), - 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) - } +import { SlashCommandBuilder, ChatInputCommandInteraction, Guild } from 'discord.js' + +export default { + data: new SlashCommandBuilder() + .setName('update') + .setDescription('Update the member count channel.'), + 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) + } } \ No newline at end of file diff --git a/src/commands/player/loop.ts b/src/commands/player/loop.ts index 85ed1ac..5186f53 100755 --- a/src/commands/player/loop.ts +++ b/src/commands/player/loop.ts @@ -1,21 +1,21 @@ -import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js' -import { useQueue } from'discord-player' - -module.exports = { - data: new SlashCommandBuilder() - .setName('loop') - .setDescription('Boucler la musique en cours de lecture.') - .addIntegerOption(option => option.setName('loop') - .setDescription('Mode de boucle (0 = Off, 1 = Titre, 2 = File d\'Attente; 3 = Autoplay)') - .setRequired(true) - .setMinValue(0) - .setMaxValue(3)), - async execute(interaction: ChatInputCommandInteraction) { - let loop = interaction.options.getInteger('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'}.`) - } +import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js' +import { useQueue } from'discord-player' + +export default { + data: new SlashCommandBuilder() + .setName('loop') + .setDescription('Boucler la musique en cours de lecture.') + .addIntegerOption(option => option.setName('loop') + .setDescription('Mode de boucle (0 = Off, 1 = Titre, 2 = File d\'Attente; 3 = Autoplay)') + .setRequired(true) + .setMinValue(0) + .setMaxValue(3)), + async execute(interaction: ChatInputCommandInteraction) { + let loop = interaction.options.getInteger('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'}.`) + } } \ No newline at end of file diff --git a/src/commands/player/lyrics.ts b/src/commands/player/lyrics.ts index 9c9a072..948c966 100755 --- a/src/commands/player/lyrics.ts +++ b/src/commands/player/lyrics.ts @@ -1,45 +1,45 @@ -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: ChatInputCommandInteraction) { - await interaction.deferReply() - - let query = interaction.options.getString('recherche', false) - if (!query) { - 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 !' }) - - if (track.raw.source === 'spotify') query = `${track.author} ${track.title}` - else query = track.title - } - - let lyricsFinder = lyricsExtractor() - - let lyrics = await lyricsFinder.search(query).catch(() => null) - if (!lyrics) return interaction.followUp({ content: 'Pas de paroles trouvées !' }) - - let trimmedLyrics = lyrics.lyrics.substring(0, 1997) - - let embed = new EmbedBuilder() - .setColor('#ffc370') - .setTitle(lyrics.title) - .setURL(lyrics.url) - .setThumbnail(lyrics.thumbnail) - .setAuthor({ - name: lyrics.artist.name, - iconURL: lyrics.artist.image, - url: lyrics.artist.url - }) - .setDescription(trimmedLyrics.length === 1997 ? `${trimmedLyrics}...` : trimmedLyrics) - - return interaction.followUp({ embeds: [embed] }) - } +import { ChatInputCommandInteraction, SlashCommandBuilder, EmbedBuilder } from 'discord.js' +import { useQueue } from 'discord-player' +import { lyricsExtractor } from '@discord-player/extractor' + +export default { + 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: ChatInputCommandInteraction) { + await interaction.deferReply() + + let query = interaction.options.getString('recherche', false) + if (!query) { + 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 !' }) + + if (track.raw.source === 'spotify') query = `${track.author} ${track.title}` + else query = track.title + } + + let lyricsFinder = lyricsExtractor() + + let lyrics = await lyricsFinder.search(query).catch(() => null) + if (!lyrics) return interaction.followUp({ content: 'Pas de paroles trouvées !' }) + + let trimmedLyrics = lyrics.lyrics.substring(0, 1997) + + let embed = new EmbedBuilder() + .setColor('#ffc370') + .setTitle(lyrics.title) + .setURL(lyrics.url) + .setThumbnail(lyrics.thumbnail) + .setAuthor({ + name: lyrics.artist.name, + iconURL: lyrics.artist.image, + url: lyrics.artist.url + }) + .setDescription(trimmedLyrics.length === 1997 ? `${trimmedLyrics}...` : trimmedLyrics) + + return interaction.followUp({ embeds: [embed] }) + } } \ No newline at end of file diff --git a/src/commands/player/pause.ts b/src/commands/player/pause.ts index ca869dc..dc9a42a 100755 --- a/src/commands/player/pause.ts +++ b/src/commands/player/pause.ts @@ -1,15 +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 !') - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 !') + } } \ No newline at end of file diff --git a/src/commands/player/play.ts b/src/commands/player/play.ts index 4f7c9ae..2cebc14 100755 --- a/src/commands/player/play.ts +++ b/src/commands/player/play.ts @@ -1,10 +1,11 @@ import { SlashCommandBuilder, ChatInputCommandInteraction, AutocompleteInteraction, GuildMember } from 'discord.js' import { useMainPlayer, useQueue, QueryType } from 'discord-player' -import writeEnv from '../../utils/writeEnv' + +import dbGuild from '../../schemas/guild' export interface TrackSearchResult { name: string, value: string } -module.exports = { +export default { data: new SlashCommandBuilder() .setName('play') .setDescription('Jouer une musique.') @@ -64,18 +65,23 @@ module.exports = { else return } try { if (!queue.connection) await queue.connect(voiceChannel) } - catch (error: any) { console.error(error); return interaction.followUp(`Y'a eu un problème, <@223831938346123275> ! (${error.message})`) } + catch (error: any) { console.error(error) } + + + let guildProfile = await dbGuild.findOne({ guildId: queue.guild.id }) + if (!guildProfile) return console.log(`Database data for **${queue.guild.name}** does not exist !`) + + let dbData = guildProfile.get('guildPlayer.replay') + dbData['textChannelId'] = interaction.channel?.id + dbData['voiceChannelId'] = voiceChannel.id + + guildProfile.set('guildPlayer.replay', dbData) + await guildProfile.save().catch(console.error) - // 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() @@ -85,7 +91,7 @@ module.exports = { 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: any) { console.error(error); return interaction.followUp(`Y'a eu un problème, <@223831938346123275> ! (${error.message})`) } + } catch (error: any) { console.error(error) } finally { queue.tasksQueue.release() } } } \ No newline at end of file diff --git a/src/commands/player/previous.ts b/src/commands/player/previous.ts index 8ef81d3..2c36bb8 100755 --- a/src/commands/player/previous.ts +++ b/src/commands/player/previous.ts @@ -1,15 +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 !') - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' +import { useHistory } from 'discord-player' + +export default { + 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 !') + } } \ No newline at end of file diff --git a/src/commands/player/resume.ts b/src/commands/player/resume.ts index efe95a0..50d6349 100755 --- a/src/commands/player/resume.ts +++ b/src/commands/player/resume.ts @@ -1,15 +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 !') - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 !') + } } \ No newline at end of file diff --git a/src/commands/player/shuffle.ts b/src/commands/player/shuffle.ts index 18567c5..d91f3ab 100755 --- a/src/commands/player/shuffle.ts +++ b/src/commands/player/shuffle.ts @@ -1,15 +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 !') - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 !') + } } \ No newline at end of file diff --git a/src/commands/player/skip.ts b/src/commands/player/skip.ts index 09387a3..a3fbe55 100755 --- a/src/commands/player/skip.ts +++ b/src/commands/player/skip.ts @@ -1,15 +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 !') - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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 !') + } } \ No newline at end of file diff --git a/src/commands/player/stop.ts b/src/commands/player/stop.ts index ae7577e..af0cc6e 100755 --- a/src/commands/player/stop.ts +++ b/src/commands/player/stop.ts @@ -1,21 +1,15 @@ -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 !') - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + 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() + return await interaction.reply('Musique arrêtée !') + } } \ No newline at end of file diff --git a/src/commands/player/volume.ts b/src/commands/player/volume.ts index d2f4a6d..e9ecd80 100755 --- a/src/commands/player/volume.ts +++ b/src/commands/player/volume.ts @@ -1,21 +1,21 @@ -import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' -import { useQueue } from 'discord-player' - -module.exports = { - data: new SlashCommandBuilder() - .setName('volume') - .setDescription('Modifie le volume de la musique.') - .addIntegerOption(option => option.setName('volume') - .setDescription('Le volume à mettre (%)') - .setRequired(true) - .setMinValue(1) - .setMaxValue(100)), - async execute(interaction: ChatInputCommandInteraction) { - let volume = interaction.options.getInteger('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}% !`) - } +import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js' +import { useQueue } from 'discord-player' + +export default { + data: new SlashCommandBuilder() + .setName('volume') + .setDescription('Modifie le volume de la musique.') + .addIntegerOption(option => option.setName('volume') + .setDescription('Le volume à mettre (%)') + .setRequired(true) + .setMinValue(1) + .setMaxValue(100)), + async execute(interaction: ChatInputCommandInteraction) { + let volume = interaction.options.getInteger('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}% !`) + } } \ No newline at end of file diff --git a/src/events/error.ts b/src/events/client/error.ts similarity index 84% rename from src/events/error.ts rename to src/events/client/error.ts index 1d855fd..a09e2ca 100755 --- a/src/events/error.ts +++ b/src/events/client/error.ts @@ -1,6 +1,6 @@ import { Events } from 'discord.js' -module.exports = { +export default { name: Events.Error, execute(error: any) { console.error(error) diff --git a/src/events/client/guildCreate.ts b/src/events/client/guildCreate.ts new file mode 100755 index 0000000..e29a4d5 --- /dev/null +++ b/src/events/client/guildCreate.ts @@ -0,0 +1,14 @@ +import { Events, Guild } from 'discord.js' +import dbGuildInit from '../../utils/dbGuildInit' + +export default { + name: Events.GuildCreate, + async execute(guild: Guild) { + console.log(`Joined ${guild.name} with ${guild.memberCount} members`) + + let guildProfile = await dbGuildInit(guild) + if (!guildProfile) return console.log(`An error occured while initializing database data for **${guild.name}** !`) + + console.log(`Database data for new guild **${guildProfile.guildName}** successfully initialized !`) + } +} \ No newline at end of file diff --git a/src/events/guildMemberAdd.ts b/src/events/client/guildMemberAdd.ts similarity index 94% rename from src/events/guildMemberAdd.ts rename to src/events/client/guildMemberAdd.ts index 568344d..79abb52 100755 --- a/src/events/guildMemberAdd.ts +++ b/src/events/client/guildMemberAdd.ts @@ -1,19 +1,19 @@ -import { Events, GuildMember } from 'discord.js' - -module.exports = { - name: Events.GuildMemberAdd, - 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...') - channel.setName(`${i} Gens Posés`) - }).catch(console.error) - } +import { Events, GuildMember } from 'discord.js' + +export default { + name: Events.GuildMemberAdd, + 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...') + channel.setName(`${i} Gens Posés`) + }).catch(console.error) + } } \ No newline at end of file diff --git a/src/events/guildMemberRemove.ts b/src/events/client/guildMemberRemove.ts similarity index 94% rename from src/events/guildMemberRemove.ts rename to src/events/client/guildMemberRemove.ts index 3a77c33..50b9d4e 100755 --- a/src/events/guildMemberRemove.ts +++ b/src/events/client/guildMemberRemove.ts @@ -1,19 +1,19 @@ -import { Events, GuildMember } from 'discord.js' - -module.exports = { - name: Events.GuildMemberRemove, - 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...') - channel.setName(`${i} Gens Posés`) - }).catch(console.error) - } +import { Events, GuildMember } from 'discord.js' + +export default { + name: Events.GuildMemberRemove, + 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...') + channel.setName(`${i} Gens Posés`) + }).catch(console.error) + } } \ No newline at end of file diff --git a/src/events/client/guildUpdate.ts b/src/events/client/guildUpdate.ts new file mode 100755 index 0000000..9dd1a53 --- /dev/null +++ b/src/events/client/guildUpdate.ts @@ -0,0 +1,19 @@ +import { Events, Guild } from 'discord.js' +import dbGuildInit from '../../utils/dbGuildInit' +import dbGuild from '../../schemas/guild' + +export default { + name: Events.GuildUpdate, + async execute(oldGuild: Guild, newGuild: Guild) { + console.log(`Guild ${oldGuild.name} updated`) + + let guildProfile = await dbGuild.findOne({ guildId: newGuild.id }) + if (!guildProfile) { + guildProfile = await dbGuildInit(newGuild) + } else { + guildProfile.guildName = newGuild.name + guildProfile.guildIcon = newGuild.iconURL() ?? 'None' + await guildProfile.save().catch(console.error) + } + } +} \ No newline at end of file diff --git a/src/events/interactionCreate.ts b/src/events/client/interactionCreate.ts similarity index 92% rename from src/events/interactionCreate.ts rename to src/events/client/interactionCreate.ts index 89a008c..f925f47 100755 --- a/src/events/interactionCreate.ts +++ b/src/events/client/interactionCreate.ts @@ -1,43 +1,46 @@ -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: Interaction) { - //if (!interaction.isAutocomplete() && !interaction.isChatInputCommand() && !interaction.isButton()) return console.error(`Interaction ${interaction.commandName} is not a command.`) - - if (interaction.isChatInputCommand()) { - 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(`Command '${interaction.commandName}' launched by ${interaction.user.tag}`) - - 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(`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(`Button '${interaction.customId}' clicked by ${interaction.user.tag}`) - - if (playerButtons.includes(interaction.customId)) { await editPlayer(interaction) } - - try { await button.execute(interaction) } - catch (error) { console.error(`Error clicking ${interaction.customId}:`, error) } - } - } +import { Events, Interaction, ChatInputCommandInteraction, AutocompleteInteraction, ButtonInteraction } from 'discord.js' +import playerButtons from '../../utilsPlayer/buttons' +import editPlayer from '../../utilsPlayer/edit' + +export default { + name: Events.InteractionCreate, + async execute(interaction: Interaction) { + //if (!interaction.isAutocomplete() && !interaction.isChatInputCommand() && !interaction.isButton()) return console.error(`Interaction ${interaction.commandName} is not a command.`) + + if (interaction.isChatInputCommand()) { + 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(`Command '${interaction.commandName}' launched by ${interaction.user.tag}`) + + 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(`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(`Button '${interaction.customId}' clicked by ${interaction.user.tag}`) + + if (playerButtons.includes(interaction.customId)) { await editPlayer(interaction) } + + try { await button.execute(interaction) } + catch (error) { console.error(`Error clicking ${interaction.customId}:`, error) } + } + } } \ No newline at end of file diff --git a/src/events/client/ready.ts b/src/events/client/ready.ts new file mode 100755 index 0000000..22742b8 --- /dev/null +++ b/src/events/client/ready.ts @@ -0,0 +1,55 @@ +import { Events, Client, ActivityType } from 'discord.js' +import { useMainPlayer } from 'discord-player' +import { connect } from 'mongoose' +import chalk from 'chalk' +import 'dotenv/config' + +import dbGuildInit from '../../utils/dbGuildInit' +import dbGuild from '../../schemas/guild' +import replay from '../../utilsPlayer/replay' +import disco from '../../utilsPlayer/disco' +import rss from '../../utils/rss' + + +export default { + name: Events.ClientReady, + once: true, + async execute(client: Client) { + console.log(chalk.blue(`[DiscordJS] Connected to Discord ! 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(chalk.blue('[Discord-Player] YouTube and Spotify extractors loaded.'))).catch(console.error) + + let mongo_url = `mongodb://${process.env.MONGOOSE_USER}:${process.env.MONGOOSE_PASSWORD}@${process.env.MONGOOSE_HOST}/${process.env.MONGOOSE_DATABASE}` + await connect(mongo_url).catch(console.error) + + + let guilds = client.guilds.cache + guilds.forEach(async guild => { + let guildProfile = await dbGuild.findOne({ guildId: guild.id }) + + if (!guildProfile) guildProfile = await dbGuildInit(guild) + if (guildProfile.guildPlayer?.replay?.enabled && guildProfile.guildPlayer?.replay?.textChannelId) await replay(client, guildProfile) + + client.disco = { interval: {} as NodeJS.Timeout } + client.disco.interval = setInterval(async () => { + let guildProfile = await dbGuild.findOne({ guildId: guild.id }) + + if (guildProfile?.guildPlayer?.disco?.enabled) { + let state = await disco(client, guildProfile) + if (state === 'clear') clearInterval(client.disco.interval) + } + }, 3000) + + client.rss = { interval: {} as NodeJS.Timeout } + client.rss.interval = setInterval(async () => { + let guildProfile = await dbGuild.findOne({ guildId: guild.id }) + + if (guildProfile?.guildRss?.enabled) { + let state = await rss(client, guildProfile) + if (state === 'clear') clearInterval(client.rss.interval) + } + }, 30000) + }) + } +} \ No newline at end of file diff --git a/src/events/voiceStateUpdate.ts b/src/events/client/voiceStateUpdate.ts similarity index 97% rename from src/events/voiceStateUpdate.ts rename to src/events/client/voiceStateUpdate.ts index 4925ac5..1fef245 100755 --- a/src/events/voiceStateUpdate.ts +++ b/src/events/client/voiceStateUpdate.ts @@ -1,59 +1,59 @@ -import { Events, VoiceState } from 'discord.js' - -module.exports = { - name: Events.VoiceStateUpdate, - async execute(oldState: VoiceState, newState: VoiceState) { - /* - let oldMute = oldState.serverMute - let newMute = newState.serverMute - let oldDeaf = oldState.serverDeaf - let newDeaf = newState.serverDeaf - let oldChannel = oldState.channelId - let newChannel = newState.channelId - console.log(oldChannel) - console.log(newChannel) - let guild = newState.guild - let member = newState.member - let channel = guild.channels.cache.get('1076215868863819848') - let angels = guild.members.cache.get('223831938346123275') - if (oldChannel !== newChannel) { - let executor = await logMoveOrKick('channel_id') - //if (!executor) channel.send(`Impossible de savoir qui a déplacé <@${member.id}> !`) - //else if (member.id === executor.id) channel.send(`<@${member.id}> s'est déplacé lui-même le con...`) - //else { - // channel.send(`<@${member.id}> a été mis en sourdine par <@${executor.id}> !`) - //} - } else if (!oldMute && newMute) { - let executor = await logMuteOrDeaf('mute') - if (!executor) channel.send(`Impossible de savoir qui a muté <@${member.id}> !`) - else if (member.id === executor.id) channel.send(`<@${member.id}> s'est muté lui-même le con...`) - else { - channel.send(`<@${member.id}> a été muté par <@${executor.id}> !`) - } - } else if (!oldDeaf && newDeaf) { - let executor = await logMuteOrDeaf('deaf') - if (!executor) channel.send(`Impossible de savoir qui a mis en sourdine <@${member.id}> !`) - else if (member.id === executor.id) channel.send(`<@${member.id}> s'est mis en sourdine lui-même le con...`) - else { - channel.send(`<@${member.id}> a été mis en sourdine par <@${executor.id}> !`) - } - } - async function logMoveOrKick() { - let auditLogs = await guild.fetchAuditLogs({ limit: 1, type: AuditLogEvent.MemberMove }) - console.log(auditLogs.entries.find(entry => { return entry })) - let log = await auditLogs.entries.find(entry => { return entry.extra.channel.id === newChannel }) - console.log(log) - if (!log) return undefined - let executor = await guild.members.cache.get(log.executor.id) - return executor - } - async function logMuteOrDeaf(type) { - let auditLogs = await guild.fetchAuditLogs({ limit: 1, type: AuditLogEvent.MemberUpdate }) - let log = await auditLogs.entries.find(entry => { return entry.target.id === member.id && entry.changes[0].key === type && entry.changes[0].new === true }) - if (!log) return undefined - let executor = await guild.members.cache.get(log.executor.id) - return executor - } - */ - } +import { Events, VoiceState } from 'discord.js' + +export default { + name: Events.VoiceStateUpdate, + async execute(oldState: VoiceState, newState: VoiceState) { + /* + let oldMute = oldState.serverMute + let newMute = newState.serverMute + let oldDeaf = oldState.serverDeaf + let newDeaf = newState.serverDeaf + let oldChannel = oldState.channelId + let newChannel = newState.channelId + console.log(oldChannel) + console.log(newChannel) + let guild = newState.guild + let member = newState.member + let channel = guild.channels.cache.get('1076215868863819848') + let angels = guild.members.cache.get('223831938346123275') + if (oldChannel !== newChannel) { + let executor = await logMoveOrKick('channel_id') + //if (!executor) channel.send(`Impossible de savoir qui a déplacé <@${member.id}> !`) + //else if (member.id === executor.id) channel.send(`<@${member.id}> s'est déplacé lui-même le con...`) + //else { + // channel.send(`<@${member.id}> a été mis en sourdine par <@${executor.id}> !`) + //} + } else if (!oldMute && newMute) { + let executor = await logMuteOrDeaf('mute') + if (!executor) channel.send(`Impossible de savoir qui a muté <@${member.id}> !`) + else if (member.id === executor.id) channel.send(`<@${member.id}> s'est muté lui-même le con...`) + else { + channel.send(`<@${member.id}> a été muté par <@${executor.id}> !`) + } + } else if (!oldDeaf && newDeaf) { + let executor = await logMuteOrDeaf('deaf') + if (!executor) channel.send(`Impossible de savoir qui a mis en sourdine <@${member.id}> !`) + else if (member.id === executor.id) channel.send(`<@${member.id}> s'est mis en sourdine lui-même le con...`) + else { + channel.send(`<@${member.id}> a été mis en sourdine par <@${executor.id}> !`) + } + } + async function logMoveOrKick() { + let auditLogs = await guild.fetchAuditLogs({ limit: 1, type: AuditLogEvent.MemberMove }) + console.log(auditLogs.entries.find(entry => { return entry })) + let log = await auditLogs.entries.find(entry => { return entry.extra.channel.id === newChannel }) + console.log(log) + if (!log) return undefined + let executor = await guild.members.cache.get(log.executor.id) + return executor + } + async function logMuteOrDeaf(type) { + let auditLogs = await guild.fetchAuditLogs({ limit: 1, type: AuditLogEvent.MemberUpdate }) + let log = await auditLogs.entries.find(entry => { return entry.target.id === member.id && entry.changes[0].key === type && entry.changes[0].new === true }) + if (!log) return undefined + let executor = await guild.members.cache.get(log.executor.id) + return executor + } + */ + } } \ No newline at end of file diff --git a/src/events/mongo/connected.ts b/src/events/mongo/connected.ts new file mode 100644 index 0000000..7e089a2 --- /dev/null +++ b/src/events/mongo/connected.ts @@ -0,0 +1,8 @@ +import chalk from 'chalk' + +export default { + name: 'connected', + async execute() { + console.log(chalk.green('[Mongoose] Connected to MongoDB !')) + } +} \ No newline at end of file diff --git a/src/events/mongo/connecting.ts b/src/events/mongo/connecting.ts new file mode 100644 index 0000000..94f0359 --- /dev/null +++ b/src/events/mongo/connecting.ts @@ -0,0 +1,8 @@ +import chalk from 'chalk' + +export default { + name: 'connecting', + async execute() { + console.log(chalk.green('[Mongoose] Connecting to MongoDB...')) + } +} \ No newline at end of file diff --git a/src/events/mongo/disconnected.ts b/src/events/mongo/disconnected.ts new file mode 100644 index 0000000..688ecbc --- /dev/null +++ b/src/events/mongo/disconnected.ts @@ -0,0 +1,8 @@ +import chalk from 'chalk' + +export default { + name: 'disconnected', + async execute() { + console.log(chalk.green('[Mongoose] Disconnected from MongoDB !')) + } +} \ No newline at end of file diff --git a/src/events/mongo/error.ts b/src/events/mongo/error.ts new file mode 100644 index 0000000..379f253 --- /dev/null +++ b/src/events/mongo/error.ts @@ -0,0 +1,8 @@ +import chalk from 'chalk' + +export default { + name: 'error', + async execute(error: Error) { + console.log(chalk.red('[Mongoose] An error occured with the database conenction :\n' + error)) + } +} \ No newline at end of file diff --git a/src/eventsPlayer/audioTrackAdd.ts b/src/events/player/audioTrackAdd.ts similarity index 82% rename from src/eventsPlayer/audioTrackAdd.ts rename to src/events/player/audioTrackAdd.ts index 4c81db9..27e9667 100755 --- a/src/eventsPlayer/audioTrackAdd.ts +++ b/src/events/player/audioTrackAdd.ts @@ -1,10 +1,10 @@ -import { GuildQueue, Track } from 'discord-player' -import { PlayerMetadata } from '../utilsPlayer/metadata' - -export default { - name: 'audioTrackAdd', - async execute(queue: GuildQueue, 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 !`) - } +import { GuildQueue, Track } from 'discord-player' +import { PlayerMetadata } from '../../utilsPlayer/metadata' + +export default { + name: 'audioTrackAdd', + async execute(queue: GuildQueue, 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 !`) + } } \ No newline at end of file diff --git a/src/eventsPlayer/audioTracksAdd.ts b/src/events/player/audioTracksAdd.ts similarity index 82% rename from src/eventsPlayer/audioTracksAdd.ts rename to src/events/player/audioTracksAdd.ts index df416ba..c4f537a 100755 --- a/src/eventsPlayer/audioTracksAdd.ts +++ b/src/events/player/audioTracksAdd.ts @@ -1,10 +1,10 @@ -import { GuildQueue, Track } from 'discord-player' -import { PlayerMetadata } from '../utilsPlayer/metadata' - -export default { - name: 'audioTracksAdd', - async execute(queue: GuildQueue, track: Array) { - // Emitted when the player adds multiple songs to its queue - queue.metadata.channel.send(`Ajout de ${track.length} musiques à la file d'attente !`) - } +import { GuildQueue, Track } from 'discord-player' +import { PlayerMetadata } from '../../utilsPlayer/metadata' + +export default { + name: 'audioTracksAdd', + async execute(queue: GuildQueue, track: Array) { + // Emitted when the player adds multiple songs to its queue + queue.metadata.channel.send(`Ajout de ${track.length} musiques à la file d'attente !`) + } } \ No newline at end of file diff --git a/src/eventsPlayer/debug.ts b/src/events/player/debug.ts similarity index 96% rename from src/eventsPlayer/debug.ts rename to src/events/player/debug.ts index 0dff677..e56e316 100755 --- a/src/eventsPlayer/debug.ts +++ b/src/events/player/debug.ts @@ -1,10 +1,10 @@ -import { GuildQueue } from 'discord-player' - -export default { - name: 'debug', - 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}`) - } +import { GuildQueue } from 'discord-player' + +export default { + name: 'debug', + 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}`) + } } \ No newline at end of file diff --git a/src/events/player/disconnect.ts b/src/events/player/disconnect.ts new file mode 100755 index 0000000..ebfde38 --- /dev/null +++ b/src/events/player/disconnect.ts @@ -0,0 +1,24 @@ +import { GuildQueue, Track } from 'discord-player' +import { PlayerMetadata } from '../../utilsPlayer/metadata' +import dbGuild from '../../schemas/guild' + +export default { + name: 'disconnect', + async execute(queue: GuildQueue, track: Track) { + // Emitted when the bot leaves the voice channel + queue.metadata.channel.send("J'ai quitté le vocal !") + + let guildProfile = await dbGuild.findOne({ guildId: queue.guild.id }) + if (!guildProfile) return console.log(`Database data for **${queue.guild.name}** does not exist !`) + + let dbData = guildProfile.get('guildPlayer.replay') + dbData['textChannelId'] = '' + dbData['voiceChannelId'] = '' + dbData['trackUrl'] = '' + dbData['progress'] = '' + + guildProfile.set('guildPlayer.replay', dbData) + guildProfile.markModified('guildPlayer.replay') + return await guildProfile.save().catch(console.error) + } +} \ No newline at end of file diff --git a/src/eventsPlayer/emptyChannel.ts b/src/events/player/emptyChannel.ts similarity index 84% rename from src/eventsPlayer/emptyChannel.ts rename to src/events/player/emptyChannel.ts index 7b8be1e..48fc0e8 100755 --- a/src/eventsPlayer/emptyChannel.ts +++ b/src/events/player/emptyChannel.ts @@ -1,11 +1,11 @@ -import { GuildQueue, Track } from 'discord-player' -import { PlayerMetadata } from '../utilsPlayer/metadata' - -export default { - name: 'emptyChannel', - async execute(queue: GuildQueue, 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.`) - } +import { GuildQueue, Track } from 'discord-player' +import { PlayerMetadata } from '../../utilsPlayer/metadata' + +export default { + name: 'emptyChannel', + async execute(queue: GuildQueue, 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.`) + } } \ No newline at end of file diff --git a/src/eventsPlayer/emptyQueue.ts b/src/events/player/emptyQueue.ts similarity index 77% rename from src/eventsPlayer/emptyQueue.ts rename to src/events/player/emptyQueue.ts index ef2bdd0..a3b87ed 100755 --- a/src/eventsPlayer/emptyQueue.ts +++ b/src/events/player/emptyQueue.ts @@ -1,10 +1,10 @@ -import { GuildQueue, Track } from 'discord-player' -import { PlayerMetadata } from '../utilsPlayer/metadata' - -export default { - name: 'emptyQueue', - async execute(queue: GuildQueue) { - // Emitted when the player queue has finished - queue.metadata.channel.send("File d'attente vide !") - } +import { GuildQueue, Track } from 'discord-player' +import { PlayerMetadata } from '../../utilsPlayer/metadata' + +export default { + name: 'emptyQueue', + async execute(queue: GuildQueue) { + // Emitted when the player queue has finished + queue.metadata.channel.send("File d'attente vide !") + } } \ No newline at end of file diff --git a/src/eventsPlayer/error.ts b/src/events/player/error.ts similarity index 96% rename from src/eventsPlayer/error.ts rename to src/events/player/error.ts index b53a818..efd59f2 100755 --- a/src/eventsPlayer/error.ts +++ b/src/events/player/error.ts @@ -1,10 +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) - } +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) + } } \ No newline at end of file diff --git a/src/eventsPlayer/playerError.ts b/src/events/player/playerError.ts similarity index 96% rename from src/eventsPlayer/playerError.ts rename to src/events/player/playerError.ts index 289a9fc..f084529 100755 --- a/src/eventsPlayer/playerError.ts +++ b/src/events/player/playerError.ts @@ -1,10 +1,10 @@ -import { GuildQueue } from 'discord-player' - -export default { - name: 'playerError', - 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) - } +import { GuildQueue } from 'discord-player' + +export default { + name: 'playerError', + 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) + } } \ No newline at end of file diff --git a/src/eventsPlayer/playerSkip.ts b/src/events/player/playerSkip.ts similarity index 82% rename from src/eventsPlayer/playerSkip.ts rename to src/events/player/playerSkip.ts index 941ca55..5e55047 100755 --- a/src/eventsPlayer/playerSkip.ts +++ b/src/events/player/playerSkip.ts @@ -1,10 +1,10 @@ -import { GuildQueue, Track } from 'discord-player' -import { PlayerMetadata } from '../utilsPlayer/metadata' - -export default { - name: 'playerSkip', - async execute(queue: GuildQueue, 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 !`) - } +import { GuildQueue, Track } from 'discord-player' +import { PlayerMetadata } from '../../utilsPlayer/metadata' + +export default { + name: 'playerSkip', + async execute(queue: GuildQueue, 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 !`) + } } \ No newline at end of file diff --git a/src/events/player/playerStart.ts b/src/events/player/playerStart.ts new file mode 100755 index 0000000..ec09c6e --- /dev/null +++ b/src/events/player/playerStart.ts @@ -0,0 +1,22 @@ +import { GuildQueue, Track } from 'discord-player' +import { PlayerMetadata } from '../../utilsPlayer/metadata' +import dbGuild from '../../schemas/guild' + +export default { + name: 'playerStart', + async execute(queue: GuildQueue, track: Track) { + // Emitted when the player starts to play a song + queue.metadata.channel.send(`Lecture de **${track.title}** de **${track.author}** !`) + + let guildProfile = await dbGuild.findOne({ guildId: queue.guild.id }) + if (!guildProfile) return console.log(`Database data for **${queue.guild.name}** does not exist !`) + + let dbData = guildProfile.get('guildPlayer.replay') + dbData['trackUrl'] = track.url + dbData['progress'] = '0' + + guildProfile.set('guildPlayer.replay', dbData) + guildProfile.markModified('guildPlayer.replay') + return await guildProfile.save().catch(console.error) + } +} \ No newline at end of file diff --git a/src/events/ready.ts b/src/events/ready.ts deleted file mode 100755 index 4124e7c..0000000 --- a/src/events/ready.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Events, Client, ActivityType } from 'discord.js' -import { useMainPlayer } from 'discord-player' -import replay from '../utilsPlayer/replay' -import disco from '../utilsPlayer/disco' -import rss from '../utils/rss' -import 'dotenv/config' - -declare module "discord.js" { - export interface Client { - disco: { interval: NodeJS.Timeout }, - rss: { 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) - - client.rss = { interval: {} as NodeJS.Timeout } - client.rss.interval = setInterval(async () => { - let state = await rss(client) - if (state === 'clear') clearInterval(client.rss.interval) - }, 30000) - rss(client) - } -} \ No newline at end of file diff --git a/src/eventsPlayer/disconnect.ts b/src/eventsPlayer/disconnect.ts deleted file mode 100755 index b1c7dd5..0000000 --- a/src/eventsPlayer/disconnect.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { GuildQueue, Track } from 'discord-player' -import { PlayerMetadata } from '../utilsPlayer/metadata' -import writeEnv from '../utils/writeEnv' - -export default { - name: 'disconnect', - async execute(queue: GuildQueue, track: Track) { - // Emitted when the bot leaves the voice channel - queue.metadata.channel.send("J'ai quitté le vocal !") - - writeEnv('DISCORD_MUSIC_TEXTCHANNEL_ID', '') - writeEnv('DISCORD_MUSIC_VOICECHANNEL_ID', '') - writeEnv('DISCORD_MUSIC_CURRENT_TRACK', '') - writeEnv('DISCORD_MUSIC_CURRENT_PROGRESS', '') - } -} \ No newline at end of file diff --git a/src/eventsPlayer/playerStart.ts b/src/eventsPlayer/playerStart.ts deleted file mode 100755 index b08129a..0000000 --- a/src/eventsPlayer/playerStart.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { GuildQueue, Track } from 'discord-player' -import { PlayerMetadata } from '../utilsPlayer/metadata' -import writeEnv from '../utils/writeEnv' - -export default { - name: 'playerStart', - async execute(queue: GuildQueue, 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) - } -} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 6354224..09c562b 100755 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,22 @@ // PACKAGES import { Client, Collection, GatewayIntentBits, REST, Routes, ChatInputCommandInteraction, AutocompleteInteraction, ButtonInteraction } from 'discord.js' import { Player } from 'discord-player' +import { connection } from 'mongoose' import path from 'path' import fs from 'fs' import 'dotenv/config' export interface Command { - name: string, - description: string, - data: any, - autocompleteRun: (interaction: AutocompleteInteraction) => any, + name: string + description: string + data: any + autocompleteRun: (interaction: AutocompleteInteraction) => any execute: (interaction: ChatInputCommandInteraction) => any } export interface Button { - name: string, - description: string, - id: string, + name: string + description: string + id: string execute: (interaction: ButtonInteraction) => any } @@ -23,6 +24,8 @@ declare module 'discord.js' { export interface Client { commands: Collection buttons: Collection + disco: { interval: NodeJS.Timeout } + rss: { interval: NodeJS.Timeout } } } @@ -30,59 +33,78 @@ declare module 'discord.js' { // 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 commands = [] as Command[] -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); commands.push(commandData) } - } 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: 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) + +// COMMANDS HANDLING +let commands = [] as Command[] +let commandsParsed = 0 +let commandsTotal = 0 + +let 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')) + commandsTotal += commandFiles.length + + commandFiles.forEach(async file => { + let command = await import(path.join(folderPath, file)) + command = command.default + if ('data' in command && 'execute' in command) { + let commandData = command.data.toJSON() + if (commandData) { client.commands.set(commandData.name, command); commands.push(commandData) } + } else console.log(`[WARNING] The command at ${`${folderPath}/${file}`} is missing a required "data" or "execute" property.`) + commandsParsed++ + + if (commandsParsed === commandsTotal) { + // COMMANDS REGISTRATION + 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: commands }) } + catch (error) { console.error(error) } + })() + } + }) +}) + +// BUTTONS HANDLING +let buttonFiles = fs.readdirSync(path.join(__dirname, './buttons')).filter(file => file.endsWith('.ts')) +buttonFiles.forEach(async file => { + let button = await import(path.join(__dirname, './buttons', file)) + button = button.default + 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.`) +}) + +// EVENTS HANDLING +let eventClientFiles = fs.readdirSync(path.join(__dirname, './events/client')).filter(file => file.endsWith('.ts')) +eventClientFiles.forEach(async file => { + let event = await import(path.join(__dirname, './events/client', file)) + event = event.default + if (event.once) client.once(event.name, (...args) => { event.execute(...args) }) + else client.on(event.name, (...args) => { event.execute(...args) }) +}) + // 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)) +let eventsPlayer = fs.readdirSync(path.join(__dirname, './events/player')).filter(file => file.endsWith('.ts')) +eventsPlayer.forEach(async file => { + let event = await import(path.join(__dirname, './events/player', file)) + event = event.default + if (event.name === 'debug') return + player.events.on(event.name, (...args: any[]) => event.execute(...args)) +}) + +// MONGO EVENTS HANDLING +let eventsMongo = fs.readdirSync(path.join(__dirname, './events/mongo')).filter(file => file.endsWith('.ts')) +eventsMongo.forEach(async file => { + let event = await import(path.join(__dirname, './events/mongo', file)) + event = event.default + if (event.once) connection.once(event.name, (...args) => { event.execute(...args, client) }) + else connection.on(event.name, (...args) => { event.execute(...args, client) }) }) diff --git a/src/schemas/guild.ts b/src/schemas/guild.ts new file mode 100644 index 0000000..1906ec4 --- /dev/null +++ b/src/schemas/guild.ts @@ -0,0 +1,39 @@ +import { Schema, Types, model } from 'mongoose' + +const guildSchema = new Schema({ + _id: Types.ObjectId, + guildId: { type: String, required: true }, + guildName: { type: String, required: true }, + guildIcon: { type: String, required: true }, + guildPlayer: { + replay: { + enabled: { type: Boolean, required: true }, + textChannelId: { type: String, required: false }, + voiceChannelId: { type: String, required: false }, + trackUrl: { type: String, required: false }, + progress: { type: Number, required: false } + }, + disco: { + enabled: { type: Boolean, required: true }, + channelId: { type: String, required: false } + } + }, + guildRss: { + enabled: { type: Boolean, required: true }, + channelId: { type: String, required: false }, + feeds: [{ + name: { type: String, required: false }, + url: { type: String, required: false }, + token: { type: String, required: false } + }] + }, + guildAmp: { + enabled: { type: Boolean, required: true }, + host: { type: String, required: false }, + username: { type: String, required: false }, + sessionID: { type: String, required: false }, + rememberMeToken: { type: String, required: false } + } +}) + +export default model('Guild', guildSchema, 'guilds') \ No newline at end of file diff --git a/src/utils/amp.ts b/src/utils/amp.ts index 7f8a93d..eeee204 100644 --- a/src/utils/amp.ts +++ b/src/utils/amp.ts @@ -1,12 +1,11 @@ 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`, { + async GetInstances(host: string, SESSIONID: string) { + return await axios.post(host + '/API/ADSModule/GetInstances', { SESSIONID }).then(response => { - if (!response.data.result) return { status: 'fail', data: response.data } + if (!Array.isArray(response.data)) return { status: 'fail', data: response.data } return { status: 'success', data: response.data } }).catch(error => { console.error(error) @@ -14,13 +13,11 @@ export const ADSModule = { }) }, - async ManageInstance(SESSIONID: string, InstanceId: string) { - return await axios.post(`${process.env.AMP_HOST}/API/ADSModule/ManageInstance`, { + async ManageInstance(host: string, SESSIONID: string, InstanceId: string) { + return await axios.post(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 => { @@ -29,13 +26,11 @@ export const ADSModule = { }) }, - async RestartInstance(SESSIONID: string, InstanceName: string) { - return await axios.post(`${process.env.AMP_HOST}/API/ADSModule/RestartInstance`, { + async RestartInstance(host: string, SESSIONID: string, InstanceName: string) { + return await axios.post(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 => { @@ -44,16 +39,13 @@ export const ADSModule = { }) }, - async Servers(SESSIONID: string, InstanceId: string) { - return await axios.get(`${process.env.AMP_HOST}/API/ADSModule/Servers`, { + async Servers(host: string, SESSIONID: string, InstanceId: string) { + return await axios.get(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 => { @@ -64,16 +56,11 @@ export const ADSModule = { } export const Core = { - async Login(details: any) { - return await axios.post(`${process.env.AMP_HOST}/API/Core/Login`, + async Login(host: string, details: any) { + return await axios.post(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) @@ -82,11 +69,11 @@ export const Core = { } } -export async function CheckSession(SESSIONID: string) { - return await axios.post(`${process.env.AMP_HOST}/API/ADSModule/GetInstances`, { +export async function CheckSession(host: string, SESSIONID: string) { + return await axios.post(host + '/API/ADSModule/GetInstances', { SESSIONID }).then(response => { - if (!response.data.result) return { status: 'fail', data: response.data } + if (!Array.isArray(response.data)) return { status: 'fail', data: response.data } return { status: 'success', data: response.data } }).catch(error => { console.error(error) diff --git a/src/utils/dbGuildInit.ts b/src/utils/dbGuildInit.ts new file mode 100644 index 0000000..b7154df --- /dev/null +++ b/src/utils/dbGuildInit.ts @@ -0,0 +1,20 @@ +import { Guild } from 'discord.js' +import { Types } from 'mongoose' +import dbGuild from '../schemas/guild' + +export default async (guild: Guild) => { + let guildProfile = new dbGuild({ + _id: new Types.ObjectId(), + guildId: guild.id, + guildName: guild.name, + guildIcon: guild.iconURL() ?? 'None', + guildPlayer: { + replay: { enabled: false }, + disco: { enabled: false } + }, + guildRss: { enabled: false, feeds: [] }, + guildAmp: { enabled: false } + }) + await guildProfile.save().catch(console.error) + return guildProfile +} \ No newline at end of file diff --git a/src/utils/rss.ts b/src/utils/rss.ts index 12f882d..5fb66ea 100644 --- a/src/utils/rss.ts +++ b/src/utils/rss.ts @@ -1,21 +1,31 @@ import { Client, TextChannel } from 'discord.js' +import { Document } from 'mongoose' import Parser from 'rss-parser' import 'dotenv/config' -export default async (client: Client) => { +export interface Feed { + name: string + url: string + token?: string +} + +export default async (client: Client, guildProfile: Document) => { try { - let guild = client.guilds.cache.get(process.env.DISCORD_GUILD_ID as string) + let guild = client.guilds.cache.get(guildProfile.get('guildId')) if (!guild) { clearInterval(client.disco.interval) - console.log(`Aucun serveur trouvé avec l'id \`${process.env.DISCORD_GUILD_ID}\`, veuillez utiliser la commande \`/setchannel\` !`) + console.log(`Aucun serveur trouvé avec l'id \`${guildProfile.get('guildId')}\`, veuillez utiliser la commande \`/setchannel\` !`) return 'clear' } - let channel = client.channels.cache.get(process.env.DISCORD_RSSCHANNEL_ID as string) as TextChannel + + let dbData = guildProfile.get('guildRss') + let channel = client.channels.cache.get(dbData.channelId) as TextChannel if (!channel) { clearInterval(client.disco.interval) - console.log(`Aucun channel trouvé avec l'id \`${process.env.DISCORD_RSSCHANNEL_ID}\`, veuillez utiliser la commande \`/setchannel\` !`) + console.log(`Aucun channel trouvé avec l'id \`${dbData.channelId}\`, veuillez utiliser la commande \`/setchannel\` !`) return 'clear' } + let feeds = [ { name: 'Nautiljon - Actualités', @@ -27,79 +37,87 @@ export default async (client: Client) => { }, { name: 'YGG - Application', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2144&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2144&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - Audio', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2139&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2139&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - eBook', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2140&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2140&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - Emulation', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2141&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2141&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - Flim/Vidéo', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2145&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2145&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - GPS', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2143&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2143&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - Imprimante 3D', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2200&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2200&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - Jeu Vidéo', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2142&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2142&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - Nulled', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2300&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2300&passkey=', + token: process.env.YGG_PASSKEY }, { name: 'YGG - XXX', - url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2188&passkey=' + url: 'https://www3.yggtorrent.qa/rss?action=generate&type=cat&id=2188&passkey=', + token: process.env.YGG_PASSKEY } ] - feeds.forEach((feed, i) => { setTimeout(async () => { + if (!dbData.feeds) dbData.feeds = feeds + dbData.feeds.forEach((feed: Feed, i: Number) => { setTimeout(async () => { let parser = new Parser() - let url = feed.url - if (feed.name.includes('YGG')) url += process.env.YGG_PASSKEY - let feedData = await parser.parseURL(url) + if (feed.token) feed.url += feed.token + let feedData = await parser.parseURL(feed.url) - let thread = await channel.threads.cache.find(thread => thread.name === feed.name) + let thread = channel.threads.cache.find(thread => thread.name === feed.name) if (!thread) { thread = await channel.threads.create({ name: feed.name, autoArchiveDuration: 60, reason: 'Création du fil RSS' }) - await thread.send({ content: 'Fil RSS créé !'}) - await thread.send({ content: `Visionnage de **${feedData.title}** sur ${feedData.link}...` }) + await thread.send({ content: `Fil RSS créé !\nVisionnage de **${feedData.title}** sur ${feedData.link}...` }) - if (feed.name.includes('YGG')) { - let lastItem = feedData.items[0] - await thread.send({ content: `**${lastItem.title}**\n${lastItem.link}` }) - } - else feedData.items.forEach(async (item, i) => { setTimeout(async () => { - await thread?.send({ content: `**${item.title}**\n${item.link}` }) - }, i * 1000) }) + feedData.items.reverse().forEach(async (item, i) => { + setTimeout(async () => await thread?.send({ content: `**${item.title}**\n${item.link}` }), i * 1000) + }) } let lastItem = feedData.items[0] + if (!lastItem) return console.log('No last item found for ' + feed.name) + let messages = await thread.messages.fetch({ limit: 1 }) + if (!messages) return console.log('No messages found for ' + feed.name) let lastMessage = messages.first() if (!lastMessage) return console.log('No last message found for ' + feed.name) if (lastMessage.content !== `**${lastItem.title}**\n${lastItem.link}`) await thread.send({ content: `**${lastItem.title}**\n${lastItem.link}` }) //else console.log('No new item found for ' + feed.name) - }, i * 1000) }) + }, Number(i) * 1000) }) } catch (error: any) { console.error(error); return 'clear' } } \ No newline at end of file diff --git a/src/utils/writeEnv.ts b/src/utils/writeEnv.ts deleted file mode 100755 index da84872..0000000 --- a/src/utils/writeEnv.ts +++ /dev/null @@ -1,7 +0,0 @@ -import fs from 'fs' - -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) -}) \ No newline at end of file diff --git a/src/utilsPlayer/bots.ts b/src/utilsPlayer/bots.ts new file mode 100644 index 0000000..c11bc42 --- /dev/null +++ b/src/utilsPlayer/bots.ts @@ -0,0 +1 @@ +export default ['1065047326860783636', '1119343522059927684', '1119344050412204032', '1210714000321548329'] \ No newline at end of file diff --git a/src/utilsPlayer/disco.ts b/src/utilsPlayer/disco.ts index 9f33db7..ca4d4a7 100755 --- a/src/utilsPlayer/disco.ts +++ b/src/utilsPlayer/disco.ts @@ -1,26 +1,32 @@ import { Client, TextChannel } from 'discord.js' import { useQueue } from 'discord-player' +import { Document } from 'mongoose' import getUptime from '../utils/getUptime' -import writeEnv from '../utils/writeEnv' import generate from './generate' +import bots from './bots' -export default async (client: Client) => { +export default async (client: Client, guildProfile: Document) => { try { - let guild = client.guilds.cache.get(process.env.DISCORD_GUILD_ID as string) + let guild = client.guilds.cache.get(guildProfile.get('guildId')) 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 dbData = guildProfile.get('guildPlayer.disco') let queue = useQueue(guild.id) - if (queue) if (queue.isPlaying()) writeEnv('DISCORD_MUSIC_CURRENT_PROGRESS', queue.node.playbackTime.toString()) + if (queue) if (queue.isPlaying()) { + dbData['progress'] = queue.node.playbackTime.toString() - let channel = client.channels.cache.get(process.env.DISCORD_DISCOCHANNEL_ID as string) as TextChannel + guildProfile.set('guildPlayer.disco', dbData) + guildProfile.markModified('guildPlayer.disco') + await guildProfile.save().catch(console.error) + } + + let channel = client.channels.cache.get(dbData.channelId) as TextChannel if (!channel) { + console.log(`Aucun channel trouvé avec l'id \`${dbData.channelId}\`, veuillez utiliser la commande \`/database edit 'value': guildPlayer.disco.channelId\` !`) clearInterval(client.disco.interval) - console.log(`Aucun channel trouvé avec l'id \`${process.env.DISCORD_DISCOCHANNEL_ID}\`, veuillez utiliser la commande \`/setchannel\` !`) return 'clear' } @@ -29,14 +35,21 @@ export default async (client: Client) => { 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() }) + messages.forEach(msg => { if (!bots.includes(msg.author.id)) 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 botMessage.edit({ embeds: [embed] }) + } else return channel.send({ embeds: [embed] }) - } catch (error: any) { console.error(error); return 'clear' } + } catch (error: any) { + console.error(error); + return 'clear' + } } \ No newline at end of file diff --git a/src/utilsPlayer/replay.ts b/src/utilsPlayer/replay.ts index fc8374f..6a94517 100755 --- a/src/utilsPlayer/replay.ts +++ b/src/utilsPlayer/replay.ts @@ -1,11 +1,14 @@ import { Client, TextChannel, VoiceChannel } from 'discord.js' import { useMainPlayer } from 'discord-player' +import { Document } from 'mongoose' -export default async (client: Client) => { - let textChannel = client.channels.cache.get(process.env.DISCORD_MUSIC_TEXTCHANNEL_ID as string) as TextChannel - if (!textChannel) return console.log(`Aucun channel trouvé avec l'id \`${process.env.DISCORD_MUSIC_TEXTCHANNEL_ID}\`, veuillez utiliser la commande \`/setchannel\` !`) - let voiceChannel = client.channels.cache.get(process.env.DISCORD_MUSIC_VOICECHANNEL_ID as string) as VoiceChannel - if (!voiceChannel) return console.log(`Aucun channel trouvé avec l'id \`${process.env.DISCORD_MUSIC_VOICECHANNEL_ID}\`, veuillez utiliser la commande \`/setchannel\` !`) +export default async (client: Client, guildProfile: Document) => { + let dbData = guildProfile.get('guildPlayer.replay') + + let textChannel = client.channels.cache.get(dbData.textChannelId) as TextChannel + if (!textChannel) return console.log(`Aucun channel trouvé avec l'id \`${dbData.textChannelId}\`, veuillez utiliser la commande \`/setchannel\` !`) + let voiceChannel = client.channels.cache.get(dbData.voiceChannelId) as VoiceChannel + if (!voiceChannel) return console.log(`Aucun channel trouvé avec l'id \`${dbData.voiceChannelId}\`, veuillez utiliser la commande \`/setchannel\` !`) let player = useMainPlayer() let queue = player.nodes.create(textChannel.guild, { @@ -21,22 +24,22 @@ export default async (client: Client) => { leaveOnEnd: true, leaveOnEndCooldown: 300000 }) - + try { if (!queue.connection) await queue.connect(voiceChannel) } - catch (error: any) { console.error(error); await textChannel.send(`Y'a eu un problème, <@223831938346123275> ! (${error.message})`) } + catch (error: any) { console.error(error) } - let result = await player.search(process.env.DISCORD_MUSIC_CURRENT_TRACK as string, { requestedBy: client.user || undefined }) - if (!result.hasTracks()) await textChannel.send(`Aucune musique trouvée pour **${process.env.DISCORD_MUSIC_CURRENT_TRACK}** !`) + let result = await player.search(dbData.trackUrl as string, { requestedBy: client.user || undefined }) + if (!result.hasTracks()) await textChannel.send(`Aucune musique trouvée pour **${dbData.trackUrl}** !`) let track = result.tracks[0] let entry = queue.tasksQueue.acquire() await entry.getTask() queue.addTrack(track) - + try { await queue.node.play() - await queue.node.seek(Number(process.env.DISCORD_MUSIC_CURRENT_PROGRESS) / 1000) + await queue.node.seek(Number(dbData.progress) / 1000) await textChannel.send(`Relancement de la musique suite à mon redémarrage...`) - } catch (error: any) { console.error(error); await textChannel.send(`Y'a eu un problème, <@223831938346123275> ! (${error.message})`) } + } catch (error: any) { console.error(error) } finally { queue.tasksQueue.release() } } \ No newline at end of file