Intégration MongoDB + Fix export et amp

This commit is contained in:
Angels-dev
2024-02-29 00:24:21 +01:00
parent 397a45e371
commit 94c7fc1c98
63 changed files with 1608 additions and 1161 deletions

191
package-lock.json generated
View File

@@ -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"
},

View File

@@ -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",

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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))
}
}
}
}

View File

@@ -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] })
}
}

73
src/commands/global/database.ts Executable file
View File

@@ -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}` })
}
}
}

View File

@@ -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 !' })
}
}

View File

@@ -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()
}
})
}
}

View File

@@ -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`)
}
}

View File

@@ -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()
}
}

View File

@@ -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)
}
}

View File

@@ -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'}.`)
}
}

View File

@@ -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] })
}
}

View File

@@ -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 !')
}
}

View File

@@ -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() }
}
}

View File

@@ -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 !')
}
}

View File

@@ -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 !')
}
}

View File

@@ -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 !')
}
}

View File

@@ -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 !')
}
}

View File

@@ -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 !')
}
}

View File

@@ -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}% !`)
}
}

View File

@@ -1,6 +1,6 @@
import { Events } from 'discord.js'
module.exports = {
export default {
name: Events.Error,
execute(error: any) {
console.error(error)

View File

@@ -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 !`)
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}
}

View File

@@ -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) }
}
}
}

55
src/events/client/ready.ts Executable file
View File

@@ -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)
})
}
}

View File

@@ -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
}
*/
}
}

View File

@@ -0,0 +1,8 @@
import chalk from 'chalk'
export default {
name: 'connected',
async execute() {
console.log(chalk.green('[Mongoose] Connected to MongoDB !'))
}
}

View File

@@ -0,0 +1,8 @@
import chalk from 'chalk'
export default {
name: 'connecting',
async execute() {
console.log(chalk.green('[Mongoose] Connecting to MongoDB...'))
}
}

View File

@@ -0,0 +1,8 @@
import chalk from 'chalk'
export default {
name: 'disconnected',
async execute() {
console.log(chalk.green('[Mongoose] Disconnected from MongoDB !'))
}
}

View File

@@ -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))
}
}

View File

@@ -1,10 +1,10 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'audioTrackAdd',
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the player adds a single song to its queue
queue.metadata.channel.send(`Musique **${track.title}** de **${track.author}** ajoutée à la file d'attente !`)
}
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../../utilsPlayer/metadata'
export default {
name: 'audioTrackAdd',
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the player adds a single song to its queue
queue.metadata.channel.send(`Musique **${track.title}** de **${track.author}** ajoutée à la file d'attente !`)
}
}

View File

@@ -1,10 +1,10 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'audioTracksAdd',
async execute(queue: GuildQueue<PlayerMetadata>, track: Array<Track>) {
// Emitted when the player adds multiple songs to its queue
queue.metadata.channel.send(`Ajout de ${track.length} musiques à la file d'attente !`)
}
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../../utilsPlayer/metadata'
export default {
name: 'audioTracksAdd',
async execute(queue: GuildQueue<PlayerMetadata>, track: Array<Track>) {
// Emitted when the player adds multiple songs to its queue
queue.metadata.channel.send(`Ajout de ${track.length} musiques à la file d'attente !`)
}
}

View File

@@ -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}`)
}
}

24
src/events/player/disconnect.ts Executable file
View File

@@ -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<PlayerMetadata>, 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)
}
}

View File

@@ -1,11 +1,11 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'emptyChannel',
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the voice channel has been empty for the set threshold
// Bot will automatically leave the voice channel with this event
queue.metadata.channel.send(`Je quitte le vocal car il est vide depuis trop longtemps.`)
}
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../../utilsPlayer/metadata'
export default {
name: 'emptyChannel',
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the voice channel has been empty for the set threshold
// Bot will automatically leave the voice channel with this event
queue.metadata.channel.send(`Je quitte le vocal car il est vide depuis trop longtemps.`)
}
}

View File

@@ -1,10 +1,10 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'emptyQueue',
async execute(queue: GuildQueue<PlayerMetadata>) {
// Emitted when the player queue has finished
queue.metadata.channel.send("File d'attente vide !")
}
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../../utilsPlayer/metadata'
export default {
name: 'emptyQueue',
async execute(queue: GuildQueue<PlayerMetadata>) {
// Emitted when the player queue has finished
queue.metadata.channel.send("File d'attente vide !")
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -1,10 +1,10 @@
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../utilsPlayer/metadata'
export default {
name: 'playerSkip',
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the audio player fails to load the stream for a song
queue.metadata.channel.send(`Musique **${track.title}** de **${track.author}** passée !`)
}
import { GuildQueue, Track } from 'discord-player'
import { PlayerMetadata } from '../../utilsPlayer/metadata'
export default {
name: 'playerSkip',
async execute(queue: GuildQueue<PlayerMetadata>, track: Track) {
// Emitted when the audio player fails to load the stream for a song
queue.metadata.channel.send(`Musique **${track.title}** de **${track.author}** passée !`)
}
}

View File

@@ -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<PlayerMetadata>, 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)
}
}

View File

@@ -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)
}
}

View File

@@ -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<PlayerMetadata>, 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', '')
}
}

View File

@@ -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<PlayerMetadata>, track: Track) {
// Emitted when the player starts to play a song
queue.metadata.channel.send(`Lecture de **${track.title}** de **${track.author}** !`)
writeEnv(`DISCORD_MUSIC_CURRENT_TRACK`, track.url)
}
}

View File

@@ -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<unknown, Command>
buttons: Collection<unknown, Button>
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) })
})

39
src/schemas/guild.ts Normal file
View File

@@ -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')

View File

@@ -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)

20
src/utils/dbGuildInit.ts Normal file
View File

@@ -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
}

View File

@@ -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' }
}

View File

@@ -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)
})

1
src/utilsPlayer/bots.ts Normal file
View File

@@ -0,0 +1 @@
export default ['1065047326860783636', '1119343522059927684', '1119344050412204032', '1210714000321548329']

View File

@@ -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'
}
}

View File

@@ -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() }
}