Version 0.3.0-alpha1 - Youtube and Spotify support
This commit is contained in:
		
							
								
								
									
										521
									
								
								backend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										521
									
								
								backend/package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1,15 +1,17 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "chopin-backend",
 | 
			
		||||
  "version": "0.2.0",
 | 
			
		||||
  "version": "0.3.0",
 | 
			
		||||
  "lockfileVersion": 3,
 | 
			
		||||
  "requires": true,
 | 
			
		||||
  "packages": {
 | 
			
		||||
    "": {
 | 
			
		||||
      "name": "chopin-backend",
 | 
			
		||||
      "version": "0.2.0",
 | 
			
		||||
      "version": "0.3.0",
 | 
			
		||||
      "license": "ISC",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@discordjs/voice": "^0.18.0",
 | 
			
		||||
        "@distube/ytdl-core": "^4.11.5",
 | 
			
		||||
        "@distube/ytsr": "2.0.4",
 | 
			
		||||
        "cors": "^2.8.5",
 | 
			
		||||
        "discord-player": "^7.1.0",
 | 
			
		||||
        "discord.js": "^14.18.0",
 | 
			
		||||
@@ -22,9 +24,9 @@
 | 
			
		||||
        "nodemon": "^3.1.9",
 | 
			
		||||
        "pm2": "^5.4.3",
 | 
			
		||||
        "socket.io": "^4.8.1",
 | 
			
		||||
        "spotify-web-api-node": "^5.0.2",
 | 
			
		||||
        "uuid": "^11.1.0",
 | 
			
		||||
        "webmetrik": "^0.1.4",
 | 
			
		||||
        "ytdl-core": "^4.11.5"
 | 
			
		||||
        "webmetrik": "^0.1.4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@derhuerst/http-basic": {
 | 
			
		||||
@@ -251,10 +253,55 @@
 | 
			
		||||
        "url": "https://github.com/discordjs/discord.js?sponsor"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@distube/ytdl-core": {
 | 
			
		||||
      "version": "4.16.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.16.4.tgz",
 | 
			
		||||
      "integrity": "sha512-r0ZPMMB5rbUSQSez//dYDWjPSAEOm6eeV+9gyR+1vngGYFUi953Z/CoF4epTBS40X8dR32gyH3ERlh7NbnCaRg==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "http-cookie-agent": "^6.0.8",
 | 
			
		||||
        "https-proxy-agent": "^7.0.6",
 | 
			
		||||
        "m3u8stream": "^0.8.6",
 | 
			
		||||
        "miniget": "^4.2.3",
 | 
			
		||||
        "sax": "^1.4.1",
 | 
			
		||||
        "tough-cookie": "^5.1.0",
 | 
			
		||||
        "undici": "^7.3.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=20.18.1"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/distubejs/ytdl-core?sponsor"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@distube/ytdl-core/node_modules/undici": {
 | 
			
		||||
      "version": "7.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/undici/-/undici-7.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Qy96NND4Dou5jKoSJ2gm8ax8AJM/Ey9o9mz7KN1bb9GP+G0l20Zw8afxTnY2f4b7hmhn/z8aC2kfArVQlAhFBw==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=20.18.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@distube/ytsr": {
 | 
			
		||||
      "version": "2.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@distube/ytsr/-/ytsr-2.0.4.tgz",
 | 
			
		||||
      "integrity": "sha512-OiSWgARQ9LTj+dXt3jmMFzUH4l86VVCD4dVC4hEHNXdqp+DyU4QEzc+W6YY6//kWkvzTaUxOo7JUY7lBzwIF0A==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "undici": "^6.18.2"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=14.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/distubejs/ytsr?sponsor"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/aix-ppc64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "ppc64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -268,9 +315,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/android-arm": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -284,9 +331,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/android-arm64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -300,9 +347,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/android-x64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -316,9 +363,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/darwin-arm64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -332,9 +379,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/darwin-x64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -348,9 +395,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/freebsd-arm64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -364,9 +411,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/freebsd-x64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -380,9 +427,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-arm": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -396,9 +443,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-arm64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -412,9 +459,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-ia32": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "ia32"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -428,9 +475,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-loong64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "loong64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -444,9 +491,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-mips64el": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "mips64el"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -460,9 +507,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-ppc64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "ppc64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -476,9 +523,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-riscv64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "riscv64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -492,9 +539,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-s390x": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "s390x"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -508,9 +555,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/linux-x64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -524,9 +571,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/netbsd-arm64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -540,9 +587,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/netbsd-x64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -556,9 +603,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/openbsd-arm64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -572,9 +619,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/openbsd-x64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -588,9 +635,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/sunos-x64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -604,9 +651,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/win32-arm64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -620,9 +667,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/win32-ia32": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "ia32"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -636,9 +683,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@esbuild/win32-x64": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -1507,6 +1554,12 @@
 | 
			
		||||
      "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/asynckit": {
 | 
			
		||||
      "version": "0.4.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/balanced-match": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
 | 
			
		||||
@@ -1836,12 +1889,33 @@
 | 
			
		||||
      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/combined-stream": {
 | 
			
		||||
      "version": "1.0.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 | 
			
		||||
      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "delayed-stream": "~1.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 0.8"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/commander": {
 | 
			
		||||
      "version": "2.15.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
 | 
			
		||||
      "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/component-emitter": {
 | 
			
		||||
      "version": "1.3.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
 | 
			
		||||
      "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/sponsors/sindresorhus"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/concat-map": {
 | 
			
		||||
      "version": "0.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 | 
			
		||||
@@ -1908,6 +1982,12 @@
 | 
			
		||||
      "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/cookiejar": {
 | 
			
		||||
      "version": "2.1.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
 | 
			
		||||
      "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/cors": {
 | 
			
		||||
      "version": "2.8.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
 | 
			
		||||
@@ -2024,6 +2104,15 @@
 | 
			
		||||
        "node": ">= 14"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/delayed-stream": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=0.4.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/depd": {
 | 
			
		||||
      "version": "2.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
 | 
			
		||||
@@ -2335,10 +2424,25 @@
 | 
			
		||||
        "node": ">= 0.4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/es-set-tostringtag": {
 | 
			
		||||
      "version": "2.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
 | 
			
		||||
      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "es-errors": "^1.3.0",
 | 
			
		||||
        "get-intrinsic": "^1.2.6",
 | 
			
		||||
        "has-tostringtag": "^1.0.2",
 | 
			
		||||
        "hasown": "^2.0.2"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 0.4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/esbuild": {
 | 
			
		||||
      "version": "0.24.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
 | 
			
		||||
      "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
 | 
			
		||||
      "version": "0.25.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
 | 
			
		||||
      "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
 | 
			
		||||
      "hasInstallScript": true,
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "bin": {
 | 
			
		||||
@@ -2348,31 +2452,31 @@
 | 
			
		||||
        "node": ">=18"
 | 
			
		||||
      },
 | 
			
		||||
      "optionalDependencies": {
 | 
			
		||||
        "@esbuild/aix-ppc64": "0.24.2",
 | 
			
		||||
        "@esbuild/android-arm": "0.24.2",
 | 
			
		||||
        "@esbuild/android-arm64": "0.24.2",
 | 
			
		||||
        "@esbuild/android-x64": "0.24.2",
 | 
			
		||||
        "@esbuild/darwin-arm64": "0.24.2",
 | 
			
		||||
        "@esbuild/darwin-x64": "0.24.2",
 | 
			
		||||
        "@esbuild/freebsd-arm64": "0.24.2",
 | 
			
		||||
        "@esbuild/freebsd-x64": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-arm": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-arm64": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-ia32": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-loong64": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-mips64el": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-ppc64": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-riscv64": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-s390x": "0.24.2",
 | 
			
		||||
        "@esbuild/linux-x64": "0.24.2",
 | 
			
		||||
        "@esbuild/netbsd-arm64": "0.24.2",
 | 
			
		||||
        "@esbuild/netbsd-x64": "0.24.2",
 | 
			
		||||
        "@esbuild/openbsd-arm64": "0.24.2",
 | 
			
		||||
        "@esbuild/openbsd-x64": "0.24.2",
 | 
			
		||||
        "@esbuild/sunos-x64": "0.24.2",
 | 
			
		||||
        "@esbuild/win32-arm64": "0.24.2",
 | 
			
		||||
        "@esbuild/win32-ia32": "0.24.2",
 | 
			
		||||
        "@esbuild/win32-x64": "0.24.2"
 | 
			
		||||
        "@esbuild/aix-ppc64": "0.25.0",
 | 
			
		||||
        "@esbuild/android-arm": "0.25.0",
 | 
			
		||||
        "@esbuild/android-arm64": "0.25.0",
 | 
			
		||||
        "@esbuild/android-x64": "0.25.0",
 | 
			
		||||
        "@esbuild/darwin-arm64": "0.25.0",
 | 
			
		||||
        "@esbuild/darwin-x64": "0.25.0",
 | 
			
		||||
        "@esbuild/freebsd-arm64": "0.25.0",
 | 
			
		||||
        "@esbuild/freebsd-x64": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-arm": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-arm64": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-ia32": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-loong64": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-mips64el": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-ppc64": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-riscv64": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-s390x": "0.25.0",
 | 
			
		||||
        "@esbuild/linux-x64": "0.25.0",
 | 
			
		||||
        "@esbuild/netbsd-arm64": "0.25.0",
 | 
			
		||||
        "@esbuild/netbsd-x64": "0.25.0",
 | 
			
		||||
        "@esbuild/openbsd-arm64": "0.25.0",
 | 
			
		||||
        "@esbuild/openbsd-x64": "0.25.0",
 | 
			
		||||
        "@esbuild/sunos-x64": "0.25.0",
 | 
			
		||||
        "@esbuild/win32-arm64": "0.25.0",
 | 
			
		||||
        "@esbuild/win32-ia32": "0.25.0",
 | 
			
		||||
        "@esbuild/win32-x64": "0.25.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/escape-html": {
 | 
			
		||||
@@ -2547,6 +2651,12 @@
 | 
			
		||||
      "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/fast-safe-stringify": {
 | 
			
		||||
      "version": "2.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
 | 
			
		||||
      "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/fclone": {
 | 
			
		||||
      "version": "1.0.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz",
 | 
			
		||||
@@ -2754,6 +2864,21 @@
 | 
			
		||||
        "url": "https://github.com/sponsors/isaacs"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/form-data": {
 | 
			
		||||
      "version": "3.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.3.tgz",
 | 
			
		||||
      "integrity": "sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "asynckit": "^0.4.0",
 | 
			
		||||
        "combined-stream": "^1.0.8",
 | 
			
		||||
        "es-set-tostringtag": "^2.1.0",
 | 
			
		||||
        "mime-types": "^2.1.35"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 6"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/formdata-polyfill": {
 | 
			
		||||
      "version": "4.0.10",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
 | 
			
		||||
@@ -2767,6 +2892,16 @@
 | 
			
		||||
        "node": ">=12.20.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/formidable": {
 | 
			
		||||
      "version": "1.2.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz",
 | 
			
		||||
      "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==",
 | 
			
		||||
      "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://ko-fi.com/tunnckoCore/commissions"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/forwarded": {
 | 
			
		||||
      "version": "0.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
 | 
			
		||||
@@ -2983,6 +3118,21 @@
 | 
			
		||||
        "url": "https://github.com/sponsors/ljharb"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/has-tostringtag": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "has-symbols": "^1.0.3"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 0.4"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/sponsors/ljharb"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/hasown": {
 | 
			
		||||
      "version": "2.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
 | 
			
		||||
@@ -3012,6 +3162,30 @@
 | 
			
		||||
      "license": "ISC",
 | 
			
		||||
      "peer": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/http-cookie-agent": {
 | 
			
		||||
      "version": "6.0.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/http-cookie-agent/-/http-cookie-agent-6.0.8.tgz",
 | 
			
		||||
      "integrity": "sha512-qnYh3yLSr2jBsTYkw11elq+T361uKAJaZ2dR4cfYZChw1dt9uL5t3zSUwehoqqVb4oldk1BpkXKm2oat8zV+oA==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "agent-base": "^7.1.3"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=18.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/sponsors/3846masa"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "tough-cookie": "^4.0.0 || ^5.0.0",
 | 
			
		||||
        "undici": "^5.11.0 || ^6.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "undici": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/http-errors": {
 | 
			
		||||
      "version": "2.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
 | 
			
		||||
@@ -5447,6 +5621,15 @@
 | 
			
		||||
        "node": ">= 12"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/spotify-web-api-node": {
 | 
			
		||||
      "version": "5.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/spotify-web-api-node/-/spotify-web-api-node-5.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-r82dRWU9PMimHvHEzL0DwEJrzFk+SMCVfq249SLt3I7EFez7R+jeoKQd+M1//QcnjqlXPs2am4DFsGk8/GCsrA==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "superagent": "^6.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/sprintf-js": {
 | 
			
		||||
      "version": "1.1.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
 | 
			
		||||
@@ -5616,6 +5799,64 @@
 | 
			
		||||
        "node": ">= 6"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/superagent": {
 | 
			
		||||
      "version": "6.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz",
 | 
			
		||||
      "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==",
 | 
			
		||||
      "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "component-emitter": "^1.3.0",
 | 
			
		||||
        "cookiejar": "^2.1.2",
 | 
			
		||||
        "debug": "^4.1.1",
 | 
			
		||||
        "fast-safe-stringify": "^2.0.7",
 | 
			
		||||
        "form-data": "^3.0.0",
 | 
			
		||||
        "formidable": "^1.2.2",
 | 
			
		||||
        "methods": "^1.1.2",
 | 
			
		||||
        "mime": "^2.4.6",
 | 
			
		||||
        "qs": "^6.9.4",
 | 
			
		||||
        "readable-stream": "^3.6.0",
 | 
			
		||||
        "semver": "^7.3.2"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 7.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/superagent/node_modules/debug": {
 | 
			
		||||
      "version": "4.4.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
 | 
			
		||||
      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ms": "^2.1.3"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=6.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "supports-color": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/superagent/node_modules/mime": {
 | 
			
		||||
      "version": "2.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
 | 
			
		||||
      "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "bin": {
 | 
			
		||||
        "mime": "cli.js"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=4.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/superagent/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==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/supports-color": {
 | 
			
		||||
      "version": "5.5.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
 | 
			
		||||
@@ -5742,6 +5983,24 @@
 | 
			
		||||
        "url": "https://github.com/sponsors/jonschlinkert"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/tldts": {
 | 
			
		||||
      "version": "6.1.79",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.79.tgz",
 | 
			
		||||
      "integrity": "sha512-wjlYwK8lC/WcywLWf3A7qbK07SexezXjTRVwuPWXHvcjD7MnpPS2RXY5rLO3g12a8CNc7Y7jQRQsV7XyuBZjig==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "tldts-core": "^6.1.79"
 | 
			
		||||
      },
 | 
			
		||||
      "bin": {
 | 
			
		||||
        "tldts": "bin/cli.js"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/tldts-core": {
 | 
			
		||||
      "version": "6.1.79",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.79.tgz",
 | 
			
		||||
      "integrity": "sha512-HM+Ud/2oQuHt4I43Nvjc213Zji/z25NSH5OkJskJwHXNtYh9DTRlHMDFhms9dFMP7qyve/yVaXFIxmcJ7TdOjw==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/to-regex-range": {
 | 
			
		||||
      "version": "5.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
 | 
			
		||||
@@ -5790,6 +6049,18 @@
 | 
			
		||||
        "nodetouch": "bin/nodetouch.js"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/tough-cookie": {
 | 
			
		||||
      "version": "5.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.1.tgz",
 | 
			
		||||
      "integrity": "sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA==",
 | 
			
		||||
      "license": "BSD-3-Clause",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "tldts": "^6.1.32"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=16"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/tr46": {
 | 
			
		||||
      "version": "0.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
 | 
			
		||||
@@ -5825,26 +6096,26 @@
 | 
			
		||||
      "license": "0BSD"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/tsup": {
 | 
			
		||||
      "version": "8.3.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.3.6.tgz",
 | 
			
		||||
      "integrity": "sha512-XkVtlDV/58S9Ye0JxUUTcrQk4S+EqlOHKzg6Roa62rdjL1nGWNUstG0xgI4vanHdfIpjP448J8vlN0oK6XOJ5g==",
 | 
			
		||||
      "version": "8.4.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.4.0.tgz",
 | 
			
		||||
      "integrity": "sha512-b+eZbPCjz10fRryaAA7C8xlIHnf8VnsaRqydheLIqwG/Mcpfk8Z5zp3HayX7GaTygkigHl5cBUs+IhcySiIexQ==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "bundle-require": "^5.0.0",
 | 
			
		||||
        "bundle-require": "^5.1.0",
 | 
			
		||||
        "cac": "^6.7.14",
 | 
			
		||||
        "chokidar": "^4.0.1",
 | 
			
		||||
        "consola": "^3.2.3",
 | 
			
		||||
        "debug": "^4.3.7",
 | 
			
		||||
        "esbuild": "^0.24.0",
 | 
			
		||||
        "chokidar": "^4.0.3",
 | 
			
		||||
        "consola": "^3.4.0",
 | 
			
		||||
        "debug": "^4.4.0",
 | 
			
		||||
        "esbuild": "^0.25.0",
 | 
			
		||||
        "joycon": "^3.1.1",
 | 
			
		||||
        "picocolors": "^1.1.1",
 | 
			
		||||
        "postcss-load-config": "^6.0.1",
 | 
			
		||||
        "resolve-from": "^5.0.0",
 | 
			
		||||
        "rollup": "^4.24.0",
 | 
			
		||||
        "rollup": "^4.34.8",
 | 
			
		||||
        "source-map": "0.8.0-beta.0",
 | 
			
		||||
        "sucrase": "^3.35.0",
 | 
			
		||||
        "tinyexec": "^0.3.1",
 | 
			
		||||
        "tinyglobby": "^0.2.9",
 | 
			
		||||
        "tinyexec": "^0.3.2",
 | 
			
		||||
        "tinyglobby": "^0.2.11",
 | 
			
		||||
        "tree-kill": "^1.2.2"
 | 
			
		||||
      },
 | 
			
		||||
      "bin": {
 | 
			
		||||
@@ -6288,20 +6559,6 @@
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
 | 
			
		||||
      "license": "ISC"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/ytdl-core": {
 | 
			
		||||
      "version": "4.11.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.11.5.tgz",
 | 
			
		||||
      "integrity": "sha512-27LwsW4n4nyNviRCO1hmr8Wr5J1wLLMawHCQvH8Fk0hiRqrxuIu028WzbJetiYH28K8XDbeinYW4/wcHQD1EXA==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "m3u8stream": "^0.8.6",
 | 
			
		||||
        "miniget": "^4.2.2",
 | 
			
		||||
        "sax": "^1.1.3"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=12"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "chopin-backend",
 | 
			
		||||
  "version": "0.2.0",
 | 
			
		||||
  "version": "0.3.0",
 | 
			
		||||
  "description": "Discord Bot for music - Fetching everywhere !",
 | 
			
		||||
  "main": "src/main.js",
 | 
			
		||||
  "nodemonConfig": {
 | 
			
		||||
@@ -19,6 +19,8 @@
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@discordjs/voice": "^0.18.0",
 | 
			
		||||
    "@distube/ytdl-core": "^4.11.5",
 | 
			
		||||
    "@distube/ytsr": "2.0.4",
 | 
			
		||||
    "cors": "^2.8.5",
 | 
			
		||||
    "discord-player": "^7.1.0",
 | 
			
		||||
    "discord.js": "^14.18.0",
 | 
			
		||||
@@ -31,8 +33,8 @@
 | 
			
		||||
    "nodemon": "^3.1.9",
 | 
			
		||||
    "pm2": "^5.4.3",
 | 
			
		||||
    "socket.io": "^4.8.1",
 | 
			
		||||
    "spotify-web-api-node": "^5.0.2",
 | 
			
		||||
    "uuid": "^11.1.0",
 | 
			
		||||
    "webmetrik": "^0.1.4",
 | 
			
		||||
    "ytdl-core": "^4.11.5"
 | 
			
		||||
    "webmetrik": "^0.1.4"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,10 +13,7 @@ function setMusicActivity(songName, artistName, imageUrl) {
 | 
			
		||||
    const client = bot.getClient()
 | 
			
		||||
    client.user.setActivity(`${songName} - ${artistName}`,{
 | 
			
		||||
            type: ActivityType.Listening,
 | 
			
		||||
            assets: {
 | 
			
		||||
                largeImage: imageUrl,
 | 
			
		||||
                largeText: songName
 | 
			
		||||
            }
 | 
			
		||||
            url: imageUrl
 | 
			
		||||
    });
 | 
			
		||||
    dlog.log(`Activité mise à jour : ${songName} - ${artistName}`)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -68,6 +68,9 @@ function init() {
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // TODO: Implement the disconnect event for the bot
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    client.login(config.getToken())
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ const command = new Command("about", "Affiche des informations sur le bot", (cli
 | 
			
		||||
    const seconds = Math.floor(uptime % 60);
 | 
			
		||||
 | 
			
		||||
    const embed = new Embed()
 | 
			
		||||
    embed.setColor(0xb0f542)
 | 
			
		||||
    embed.setColor(237, 12, 91)
 | 
			
		||||
    embed.setThumbnail("https://cdn.discordapp.com/avatars/" + client.user.id + "/" + client.user.avatar + ".png")
 | 
			
		||||
    embed.setTitle('Subsonics - Chopin')
 | 
			
		||||
    embed.addField('Informations',"")
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,72 @@
 | 
			
		||||
const { Command } = require("../Command");
 | 
			
		||||
const { Embed, EmbedError } = require("../Embed");
 | 
			
		||||
const { Player } = require("../../player/Player");
 | 
			
		||||
const Finder = require("../../player/Finder");
 | 
			
		||||
const { Playlist } = require("../../player/Playlist");
 | 
			
		||||
 | 
			
		||||
const command = new Command("play", "Jouer une musique à partir d'un lien dans un salon vocal", (client, interaction) => {
 | 
			
		||||
const command = new Command("play", "Jouer une musique à partir d'un lien dans un salon vocal", async (client, interaction) => {
 | 
			
		||||
 | 
			
		||||
    if(!interaction.member.voice.channel) return new EmbedError("Vous devez rejoindre un salon vocal pour jouer une musique !").send(interaction)
 | 
			
		||||
 | 
			
		||||
    const url = interaction.options.get("url")
 | 
			
		||||
    const channel = interaction.member.voice.channel
 | 
			
		||||
    const now = interaction.options.getBoolean("now") || false
 | 
			
		||||
    await Finder.search(url.value).then((song) => {
 | 
			
		||||
        if(!song) return new EmbedError("Impossible de trouver la musique à partir du lien donné ou des mots clés donnés").send(interaction)
 | 
			
		||||
    
 | 
			
		||||
}, [{type: "STRING", name: "url", description: "Lien audio (Youtube / Soundclound / Spotify)", required: true}]
 | 
			
		||||
        const player = new Player(channel.guildId)
 | 
			
		||||
        player.join(channel)
 | 
			
		||||
    
 | 
			
		||||
        const embed = new Embed()
 | 
			
		||||
        embed.setColor(0x15e6ed)
 | 
			
		||||
        
 | 
			
		||||
        // Check if song is playlist 
 | 
			
		||||
        if(song instanceof Playlist) {
 | 
			
		||||
 | 
			
		||||
            if(now) {
 | 
			
		||||
                player.readPlaylist(song, true)
 | 
			
		||||
                embed.setTitle('**Lecture immédiate**')
 | 
			
		||||
            } else {
 | 
			
		||||
                player.readPlaylist(song)
 | 
			
		||||
                embed.setTitle('**Ajout à la liste de lecture**')
 | 
			
		||||
            }
 | 
			
		||||
            embed.setDescription('**Playlist : **' + song.songs.length + ' musiques')
 | 
			
		||||
            embed.addField('**Titre : **' + song.title, "")  
 | 
			
		||||
            embed.addField('**Demandé par : **', interaction.member.user.username,)
 | 
			
		||||
            embed.addField('**Auteur : **', song.author)  
 | 
			
		||||
            embed.addField('**Durée : **', song.readduration)
 | 
			
		||||
 | 
			
		||||
            embed.setThumbnail(song.thumbnail)
 | 
			
		||||
            
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
            if(now) { 
 | 
			
		||||
            
 | 
			
		||||
                player.play(song)
 | 
			
		||||
                embed.setTitle('**Lecture immédiate**')
 | 
			
		||||
          
 | 
			
		||||
            } else {
 | 
			
		||||
                player.add(song)
 | 
			
		||||
                embed.setTitle('**Ajout à liste de lecture**')
 | 
			
		||||
                
 | 
			
		||||
            }
 | 
			
		||||
                
 | 
			
		||||
            embed.setDescription('**Titre : **' + song.title)
 | 
			
		||||
            embed.addField('**Durée : **', song.readduration)
 | 
			
		||||
            embed.addField("**Artiste : **",song.author)
 | 
			
		||||
            embed.addField('**Demandé par **' + interaction.member.user.username, "")
 | 
			
		||||
            embed.setThumbnail(song.thumbnail)
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
       
 | 
			
		||||
        
 | 
			
		||||
        embed.send(interaction)
 | 
			
		||||
    })
 | 
			
		||||
    
 | 
			
		||||
}, [{type: "STRING", name: "url", description: "Recherche / Lien audio (Youtube / Soundclound / Spotify)", required: true},
 | 
			
		||||
    {type:"BOOLEAN", name: "now", description: "Lire le média maintenant", required: false}]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
module.exports = {command}
 | 
			
		||||
@@ -23,7 +23,10 @@ const command = new Command("liste", "Affiche la file d'attente", (client, inter
 | 
			
		||||
            embed.setColor(0x15e6ed)
 | 
			
		||||
            embed.setThumbnail("https://www.iconsdb.com/icons/download/white/list-2-64.png")
 | 
			
		||||
            embed.setTitle('**File d\'attente :**')
 | 
			
		||||
            embed.setDescription('**' + queue.length + ' musiques**')
 | 
			
		||||
            queue.forEach((song, index) => {
 | 
			
		||||
                // max 24 fields
 | 
			
		||||
                if(index > 10) return
 | 
			
		||||
                embed.addField(`**${index+1} - ${song.title}**`, `**Durée : **${song.readduration}\n**Artiste : **${song.author}`)
 | 
			
		||||
            })
 | 
			
		||||
            
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ metric.publishMetrics("8001", "raphraph")
 | 
			
		||||
 | 
			
		||||
setup();
 | 
			
		||||
 | 
			
		||||
function setup() {
 | 
			
		||||
async function setup() {
 | 
			
		||||
    const DiscordBot = require("./discord/Bot")
 | 
			
		||||
    DiscordBot.init()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										0
									
								
								backend/src/media/SoundcloudInformation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								backend/src/media/SoundcloudInformation.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										112
									
								
								backend/src/media/SpotifyInformation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								backend/src/media/SpotifyInformation.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
const {LogType} = require('loguix');  
 | 
			
		||||
const clog = new LogType("SpotifyInformation");
 | 
			
		||||
const config = require('../utils/Database/Configuration');
 | 
			
		||||
const SPOTIFY_CLIENT_ID = config.getSpotifyClientId()
 | 
			
		||||
const SPOTIFY_CLIENT_SECRET = config.getSpotifyClientSecret()
 | 
			
		||||
const SpotifyWebApi = require('spotify-web-api-node');
 | 
			
		||||
const {Playlist} = require('../player/Playlist');
 | 
			
		||||
const {Song} = require('../player/Song');
 | 
			
		||||
const youtube = require("../media/YoutubeInformation");
 | 
			
		||||
const {getReadableDuration} = require('../utils/TimeConverter');
 | 
			
		||||
 | 
			
		||||
const spotifyApi = new SpotifyWebApi({
 | 
			
		||||
    clientId: SPOTIFY_CLIENT_ID,
 | 
			
		||||
    clientSecret: SPOTIFY_CLIENT_SECRET,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
async function getSong(url) {
 | 
			
		||||
    try {
 | 
			
		||||
        const data = await spotifyApi.clientCredentialsGrant();
 | 
			
		||||
        spotifyApi.setAccessToken(data.body['access_token']);
 | 
			
		||||
 | 
			
		||||
        const parts = url.split('/');
 | 
			
		||||
        const trackId = parts[parts.length - 1];
 | 
			
		||||
 | 
			
		||||
        if(!trackId) {
 | 
			
		||||
            clog.error("Impossible de récupérer l'identifiant de la piste Spotify à partir de l'URL");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        const trackInfo = await spotifyApi.getTrack(trackId);
 | 
			
		||||
        const trackName = trackInfo.body.name;
 | 
			
		||||
        const artistName = trackInfo.body.artists[0].name;
 | 
			
		||||
 | 
			
		||||
        return `${trackName} - ${artistName}`;
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        console.error('Erreur lors de la récupération des données :', error);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getAlbum(albumId) {
 | 
			
		||||
   
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getPlaylist(url) {
 | 
			
		||||
    // Get the playlist and return a Playlist Object
 | 
			
		||||
    const data = await spotifyApi.clientCredentialsGrant();
 | 
			
		||||
    spotifyApi.setAccessToken(data.body['access_token']);
 | 
			
		||||
 | 
			
		||||
    const parts = url.split('/');
 | 
			
		||||
    const playlistId = parts[parts.indexOf('playlist') + 1].split('?')[0];
 | 
			
		||||
 | 
			
		||||
    spotifyApi.getPlaylist(playlistId)
 | 
			
		||||
    .then(function(data) {
 | 
			
		||||
        const info = data.body;
 | 
			
		||||
 | 
			
		||||
        const playlist = new Playlist() 
 | 
			
		||||
        playlist.title = info.name;
 | 
			
		||||
        playlist.author = info.owner.display_name;
 | 
			
		||||
        playlist.authorId = info.owner.id;
 | 
			
		||||
        playlist.thumbnail = info.images[0].url;
 | 
			
		||||
        playlist.url = info.external_urls.spotify;
 | 
			
		||||
        playlist.id = playlistId;
 | 
			
		||||
        playlist.type = "spotify";
 | 
			
		||||
        
 | 
			
		||||
        const tracks = info.tracks.items;
 | 
			
		||||
        tracks.forEach(async function(track) {
 | 
			
		||||
        
 | 
			
		||||
            var trackName = track.track.name;
 | 
			
		||||
            var artistName = track.track.artists[0].name;
 | 
			
		||||
            var queryForYoutube =  `${trackName} - ${artistName}`;
 | 
			
		||||
 | 
			
		||||
            var urlYoutubeFounded = await youtube.getQuery(queryForYoutube).then(function(songFind) {
 | 
			
		||||
                if(!songFind) return null;
 | 
			
		||||
                return songFind.url;
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
            clog.log("URL de la vidéo YouTube trouvée : " + urlYoutubeFounded);
 | 
			
		||||
 | 
			
		||||
            if(!urlYoutubeFounded) {
 | 
			
		||||
                clog.error("Impossible de récupérer l'URL de la vidéo YouTube à partir de la requête  " + queryForYoutube);
 | 
			
		||||
               
 | 
			
		||||
            } else {
 | 
			
		||||
                const song = new Song();
 | 
			
		||||
                song.title = track.track.name;
 | 
			
		||||
                song.author = track.track.artists[0].name;
 | 
			
		||||
                song.url = urlYoutubeFounded;
 | 
			
		||||
                song.thumbnail = track.track.album.images[0].url;
 | 
			
		||||
                song.id = track.track.id;
 | 
			
		||||
                song.duration = track.track.duration_ms / 1000;
 | 
			
		||||
                song.readduration = getReadableDuration(track.track.duration_ms);
 | 
			
		||||
    
 | 
			
		||||
                playlist.duration += track.track.duration_ms;
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
                playlist.songs.push(song);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        playlist.readduration = getReadableDuration(playlist.duration);
 | 
			
		||||
        return playlist;
 | 
			
		||||
   
 | 
			
		||||
    }, function(err) {
 | 
			
		||||
        clog.error('Une erreur s\'est produite lors de la récupération de la playlist');
 | 
			
		||||
        clog.error(err);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = {getSong, getAlbum, getPlaylist}
 | 
			
		||||
							
								
								
									
										43
									
								
								backend/src/player/Finder.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								backend/src/player/Finder.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
const Resolver = require('../utils/Resolver');
 | 
			
		||||
const { QueryType } = require('../utils/QueryType');
 | 
			
		||||
const { Links } = require('../utils/Links');
 | 
			
		||||
const youtube = require("../media/YoutubeInformation")
 | 
			
		||||
const spotify = require("../media/SpotifyInformation")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async function search(query) {
 | 
			
		||||
    const type = Resolver.getQueryType(query)
 | 
			
		||||
    if(type == QueryType.YOUTUBE_SEARCH) {
 | 
			
		||||
 | 
			
		||||
        return await youtube.getQuery(query)
 | 
			
		||||
      
 | 
			
		||||
    }
 | 
			
		||||
    if(type == QueryType.YOUTUBE_VIDEO) {
 | 
			
		||||
    
 | 
			
		||||
        return await youtube.getVideo(query)
 | 
			
		||||
    }
 | 
			
		||||
    if(type == QueryType.YOUTUBE_PLAYLIST) {
 | 
			
		||||
    
 | 
			
		||||
        return await youtube.getPlaylist(query)
 | 
			
		||||
    }
 | 
			
		||||
    if(type == QueryType.SPOTIFY_SONG) {
 | 
			
		||||
        return await youtube.getQuery(await spotify.getSong(query))
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
    if(type == QueryType.SPOTIFY_ALBUM) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    if(type == QueryType.SPOTIFY_PLAYLIST) {
 | 
			
		||||
        return await spotify.getPlaylist(query)
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    if(type == QueryType.SOUNDCLOUD_TRACK) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    if(type == QueryType.SOUNDCLOUD_PLAYLIST) {
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
    // TODO: Add more providers
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {search}
 | 
			
		||||
@@ -177,6 +177,16 @@ class List {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addNextPlaylist(playlist, firstAlreadyPlayed) {
 | 
			
		||||
        if(firstAlreadyPlayed) {
 | 
			
		||||
            playlist.songs.shift()
 | 
			
		||||
        }
 | 
			
		||||
     
 | 
			
		||||
        for(const song of playlist.songs) {
 | 
			
		||||
            this.addNextSong(song)
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,21 @@
 | 
			
		||||
const {createAudioResource, VoiceConnectionStatus, createAudioPlayer} = require('@discordjs/voice');
 | 
			
		||||
const {createAudioResource, VoiceConnectionStatus, createAudioPlayer, StreamType} = require('@discordjs/voice');
 | 
			
		||||
const {LogType} = require('loguix')
 | 
			
		||||
const clog = new LogType("Media")
 | 
			
		||||
const plog = require("loguix").getInstance("Player")
 | 
			
		||||
 | 
			
		||||
async function play(instance, song) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
       try {
 | 
			
		||||
          
 | 
			
		||||
            instance.player = createAudioPlayer()
 | 
			
		||||
            instance.generatePlayerEvents()
 | 
			
		||||
            const player = instance.player
 | 
			
		||||
            const resource = await song.getResource() // Remplace par ton fichier audio
 | 
			
		||||
            song.resource = await createAudioResource(song.url, {
 | 
			
		||||
                    inputType: StreamType.Arbitrary
 | 
			
		||||
               }) // Remplace par ton fichier audio
 | 
			
		||||
 | 
			
		||||
            player.play(resource);
 | 
			
		||||
            player.play(song.resource);
 | 
			
		||||
            instance.connection.subscribe(player);
 | 
			
		||||
            clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Media): ${song.title} - Filename : ${song.filename}`) 
 | 
			
		||||
            clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Media): ${song.title} - id : ${song.id}`) 
 | 
			
		||||
 | 
			
		||||
       } catch(e) {
 | 
			
		||||
            clog.error("Erreur lors de la lecture de la musique : " + song.title)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								backend/src/player/Method/Youtube.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								backend/src/player/Method/Youtube.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
const {createAudioResource, VoiceConnectionStatus, createAudioPlayer, StreamType} = require('@discordjs/voice');
 | 
			
		||||
const {LogType} = require('loguix')
 | 
			
		||||
const clog = new LogType("Youtube")
 | 
			
		||||
const plog = require("loguix").getInstance("Player")
 | 
			
		||||
const ytdl = require('@distube/ytdl-core')
 | 
			
		||||
 | 
			
		||||
async function play(instance, song) {
 | 
			
		||||
       try {
 | 
			
		||||
              
 | 
			
		||||
          instance.player = createAudioPlayer()
 | 
			
		||||
          instance.generatePlayerEvents()
 | 
			
		||||
          const player = instance.player
 | 
			
		||||
          const stream = ytdl(song.url, { 
 | 
			
		||||
               quality: 'highestaudio',
 | 
			
		||||
               highWaterMark: 1 << 30,
 | 
			
		||||
               liveBuffer: 20000,
 | 
			
		||||
               dlChunkSize: 0,
 | 
			
		||||
               bitrate: 128,
 | 
			
		||||
          
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
                    // Add compressor to the audio resource
 | 
			
		||||
          song.resource = createAudioResource(stream);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
          player.play(song.resource);
 | 
			
		||||
          instance.connection.subscribe(player);
 | 
			
		||||
          clog.log(`GUILD : ${instance.guildId} - Lecture de la musique (Media): ${song.title} - id : ${song.id}`) 
 | 
			
		||||
    
 | 
			
		||||
           } catch(e) {
 | 
			
		||||
                clog.error("Erreur lors de la lecture de la musique : " + song.title)
 | 
			
		||||
                clog.error(e)
 | 
			
		||||
           }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {play}
 | 
			
		||||
@@ -6,6 +6,7 @@ const plog = new LogType("Player")
 | 
			
		||||
const clog = new LogType("Signal")
 | 
			
		||||
 | 
			
		||||
const media = require('./Method/Media');
 | 
			
		||||
const youtube = require('./Method/Youtube');
 | 
			
		||||
const Activity = require('../discord/Activity');
 | 
			
		||||
 | 
			
		||||
const AllPlayers = new Map()
 | 
			
		||||
@@ -75,6 +76,7 @@ class Player {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.player.on(AudioPlayerStatus.Playing, () => {
 | 
			
		||||
        
 | 
			
		||||
            plog.log(`GUILD : ${this.guildId} - Le player est en train de jouer le contenu suivant : ${this.queue.current.title}`);
 | 
			
		||||
            Activity.setMusicActivity(this.queue.current.title, this.queue.current.author, this.queue.current.thumbnail)
 | 
			
		||||
            
 | 
			
		||||
@@ -98,11 +100,18 @@ class Player {
 | 
			
		||||
        if(this.queue.current != null) {
 | 
			
		||||
            this.player.stop()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.queue.setCurrent(song)
 | 
			
		||||
 | 
			
		||||
       if(song.type = "attachment") {
 | 
			
		||||
       if(song.type == "attachment") {
 | 
			
		||||
            media.play(this, song)
 | 
			
		||||
       }
 | 
			
		||||
       if(song.type == 'youtube') {
 | 
			
		||||
            youtube.play(this, song)
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
       // TODO: Créer une méthode pour les autres types de médias
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async add(song) {
 | 
			
		||||
@@ -115,6 +124,19 @@ class Player {
 | 
			
		||||
        plog.log(`GUILD : ${this.guildId} - La musique a été ajoutée à la liste de lecture : ${song.title}`)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async readPlaylist(playlist, now) {
 | 
			
		||||
        if(this.player.state.status == AudioPlayerStatus.Idle && this.queue.current === null && this.queue.next.length === 0) {
 | 
			
		||||
            this.play(playlist.songs[0])
 | 
			
		||||
        } 
 | 
			
		||||
        if(now) {
 | 
			
		||||
            this.play(playlist.songs[0])
 | 
			
		||||
            this.queue.addNextPlaylist(playlist, true)
 | 
			
		||||
        } else {
 | 
			
		||||
            this.queue.addNextPlaylist(playlist)
 | 
			
		||||
        }
 | 
			
		||||
        plog.log(`GUILD : ${this.guildId} - La playlist a été ajoutée à la liste de lecture : ${playlist.title}`)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async pause() {
 | 
			
		||||
        if(this.checkConnection()) return "no_music"
 | 
			
		||||
        if(this.player.state.status == AudioPlayerStatus.Paused) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								backend/src/player/Playlist.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								backend/src/player/Playlist.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
class Playlist {
 | 
			
		||||
    title = "Aucun titre";
 | 
			
		||||
    id;
 | 
			
		||||
    url;
 | 
			
		||||
    author = "Auteur inconnu";
 | 
			
		||||
    authorId;
 | 
			
		||||
    songs = [];
 | 
			
		||||
    thumbnail = "https://radomisol.fr/wp-content/uploads/2016/08/cropped-note-radomisol-musique.png" ;
 | 
			
		||||
    duration = 0;
 | 
			
		||||
    readduration;
 | 
			
		||||
    description;
 | 
			
		||||
    type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {Playlist};
 | 
			
		||||
 | 
			
		||||
@@ -1,39 +1,44 @@
 | 
			
		||||
const {LogType} = require('loguix')
 | 
			
		||||
const { createAudioResource, StreamType } = require('@discordjs/voice');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const clog = new LogType("Song")
 | 
			
		||||
const MediaInformation = require('../media/MediaInformation')
 | 
			
		||||
const YoutubeDuration = require('../utils/YoutubeDuration');
 | 
			
		||||
const { getReadableDuration } = require('../utils/TimeConverter');
 | 
			
		||||
 | 
			
		||||
class Song {
 | 
			
		||||
    title = "Aucun titre";
 | 
			
		||||
    filename = "Aucun fichier";
 | 
			
		||||
    id = "Aucun fichier";
 | 
			
		||||
    author = "Auteur inconnu"
 | 
			
		||||
    authorId;
 | 
			
		||||
    url;
 | 
			
		||||
    thumbnail = "https://radomisol.fr/wp-content/uploads/2016/08/cropped-note-radomisol-musique.png" ;
 | 
			
		||||
    duration;
 | 
			
		||||
    readduration;
 | 
			
		||||
    type;
 | 
			
		||||
    resource;
 | 
			
		||||
 | 
			
		||||
    constructor(properties) {
 | 
			
		||||
        if(properties) {
 | 
			
		||||
            this.type = properties.type ?? this.type
 | 
			
		||||
            this.title = properties.title ?? this.title
 | 
			
		||||
            this.filename = properties.filename ?? this.filename
 | 
			
		||||
            this.id = properties.id ?? this.id
 | 
			
		||||
            this.author = properties.author ?? this.author
 | 
			
		||||
            this.url = properties.url ?? this.url
 | 
			
		||||
            this.thumbnail = properties.thumbnail ?? this.thumbnail
 | 
			
		||||
            this.duration = properties.duration ?? this.duration
 | 
			
		||||
            this.readduration = properties.readduration ?? this.readduration
 | 
			
		||||
            this.type = properties.type ?? this.type
 | 
			
		||||
            this.authorId = properties.authorId ?? this.authorId
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async processMedia(media, provider) {
 | 
			
		||||
        if(provider) this.author = provider
 | 
			
		||||
        if(provider) this.author = provider;
 | 
			
		||||
        if(provider) this.authorId = provider;
 | 
			
		||||
        // Check if media is a file or a link
 | 
			
		||||
        if(media.attachment) {
 | 
			
		||||
            this.url = media.attachment.url
 | 
			
		||||
            this.filename = media.attachment.name
 | 
			
		||||
            this.id = media.attachment.name
 | 
			
		||||
            this.type = "attachment"
 | 
			
		||||
        
 | 
			
		||||
            // In face, duration is null, get the metadata of the file to get the duration
 | 
			
		||||
@@ -45,19 +50,21 @@ class Song {
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async getResource() {
 | 
			
		||||
        
 | 
			
		||||
        const resource = createAudioResource(this.url, {
 | 
			
		||||
            inputType: StreamType.Arbitrary
 | 
			
		||||
        })
 | 
			
		||||
        return resource
 | 
			
		||||
    async processYoutubeVideo(video) {
 | 
			
		||||
        this.title = video.snippet.title
 | 
			
		||||
        this.author = video.snippet.channelTitle
 | 
			
		||||
        this.authorId = video.snippet.channelId
 | 
			
		||||
        this.thumbnail = video.snippet.thumbnails.standard.url
 | 
			
		||||
        this.url = `https://www.youtube.com/watch?v=${video.id}`
 | 
			
		||||
        this.type = "youtube"
 | 
			
		||||
        this.id = video.id
 | 
			
		||||
 | 
			
		||||
        this.duration = await YoutubeDuration.getDurationVideo(video.id)
 | 
			
		||||
        this.readduration = getReadableDuration(this.duration)
 | 
			
		||||
 | 
			
		||||
        return this
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {Song}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,13 @@ const config = new Database("config", __glob.DATA  + path.sep + "config.json", {
 | 
			
		||||
    report: {
 | 
			
		||||
        channel : "",
 | 
			
		||||
        contact : ""
 | 
			
		||||
    },
 | 
			
		||||
    api: {
 | 
			
		||||
        youtube: "",
 | 
			
		||||
        spotify: {
 | 
			
		||||
            clientId: "",
 | 
			
		||||
            clientSecret: ""
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@@ -25,9 +32,22 @@ function getReportContact() {
 | 
			
		||||
    return config.data.report.contact
 | 
			
		||||
}   
 | 
			
		||||
 | 
			
		||||
function getYoutubeApiKey() {
 | 
			
		||||
    return config.data.api.youtube
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getSpotifyClientId() {
 | 
			
		||||
    return config.data.api.spotify.clientId
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getSpotifyClientSecret() {
 | 
			
		||||
 | 
			
		||||
    return config.data.api.spotify.clientSecret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if(getToken() == "") {
 | 
			
		||||
    clog.error("Impossible de démarrer sans token valide")
 | 
			
		||||
    process.exit(1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {getToken, getReportChannel, getReportContact}
 | 
			
		||||
module.exports = {getToken, getReportChannel, getReportContact, getYoutubeApiKey, getSpotifyClientId, getSpotifyClientSecret}
 | 
			
		||||
							
								
								
									
										79
									
								
								backend/src/utils/Links.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								backend/src/utils/Links.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
const YoutubeLinks = [
 | 
			
		||||
    "youtube.com",
 | 
			
		||||
    "youtu.be",
 | 
			
		||||
    "music.youtube.com",
 | 
			
		||||
    "gaming.youtube.com",
 | 
			
		||||
    "www.youtube.com",
 | 
			
		||||
    "m.youtube.com"
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var youtubePlaylistRegex = new RegExp(/^https?:\/\/(www.)?youtube.com\/playlist\?list=((PL|FL|UU|LL|RD|OL)[a-zA-Z0-9-_]{16,41})$/)
 | 
			
		||||
var youtubeVideoURLRegex = new RegExp(/^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:watch\?v=))([\w-]{11})(\S+)?$/)
 | 
			
		||||
var youtubeVideoIdRegex = new RegExp(/^[a-zA-Z0-9-_]{11}$/)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const SpotifyLinks = [
 | 
			
		||||
    "open.spotify.com", 
 | 
			
		||||
    "embed.spotify.com"
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
var spotifySongRegex = new RegExp(/^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:track\/|\?uri=spotify:track:)((\w|-){22})(\?si=.+)?$/)
 | 
			
		||||
var spotifyPlaylistRegex = new RegExp(/^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})(\?si=.+)?$/)
 | 
			
		||||
var spotifyAlbumRegex = new RegExp(/^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:album\/|\?uri=spotify:album:)((\w|-){22})(\?si=.+)?$/)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const SoundcloudLinks = [
 | 
			
		||||
    "soundcloud.com"
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var soundcloudTrackRegex = new RegExp(/^https?:\/\/(m.|www.)?soundcloud.com\/(\w|-)+\/(\w|-)+(.+)?$/)
 | 
			
		||||
var soundcloudPlaylistRegex = new RegExp(/^https?:\/\/(m.|www.)?soundcloud.com\/(\w|-)+\/sets\/(\w|-)+(.+)?$/)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @typedef {Object} Links
 | 
			
		||||
 * @property {Object} regex
 | 
			
		||||
 * @property {Object} regex.youtube
 | 
			
		||||
 * @property {RegExp} regex.youtube.playlist
 | 
			
		||||
 * @property {RegExp} regex.youtube.videoURL
 | 
			
		||||
 * @property {RegExp} regex.youtube.videoId
 | 
			
		||||
 * @property {Object} regex.spotify
 | 
			
		||||
 * @property {RegExp} regex.spotify.song
 | 
			
		||||
 * @property {RegExp} regex.spotify.playlist
 | 
			
		||||
 * @property {RegExp} regex.spotify.album
 | 
			
		||||
 * @property {Object} regex.soundcloud
 | 
			
		||||
 * @property {RegExp} regex.soundcloud.track
 | 
			
		||||
 * @property {RegExp} regex.soundcloud.playlist
 | 
			
		||||
 * @property {Object} types
 | 
			
		||||
 * @property {Array<String>} types.youtube
 | 
			
		||||
 * @property {Array<String>} types.spotify
 | 
			
		||||
 * @property {Array<String>} types.soundcloud
 | 
			
		||||
 */
 | 
			
		||||
const Links = {
 | 
			
		||||
    regex: {
 | 
			
		||||
        youtube: {
 | 
			
		||||
            playlist: youtubePlaylistRegex,
 | 
			
		||||
            videoURL: youtubeVideoURLRegex,
 | 
			
		||||
            videoId: youtubeVideoIdRegex
 | 
			
		||||
        },
 | 
			
		||||
        spotify: {
 | 
			
		||||
            song: spotifySongRegex,
 | 
			
		||||
            playlist: spotifyPlaylistRegex,
 | 
			
		||||
            album: spotifyAlbumRegex
 | 
			
		||||
        },
 | 
			
		||||
        soundcloud: {
 | 
			
		||||
            track: soundcloudTrackRegex,
 | 
			
		||||
            playlist: soundcloudPlaylistRegex
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    types: {
 | 
			
		||||
        youtube: YoutubeLinks,
 | 
			
		||||
        spotify: SpotifyLinks,
 | 
			
		||||
        soundcloud: SoundcloudLinks
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {Links}
 | 
			
		||||
							
								
								
									
										16
									
								
								backend/src/utils/QueryType.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								backend/src/utils/QueryType.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Enum for query types
 | 
			
		||||
 * @readonly
 | 
			
		||||
 */
 | 
			
		||||
const QueryType = {
 | 
			
		||||
    SPOTIFY_PLAYLIST: 'spotify_playlist',
 | 
			
		||||
    SPOTIFY_ALBUM: 'spotify_album',
 | 
			
		||||
    SPOTIFY_SONG: 'spotify_song',
 | 
			
		||||
    YOUTUBE_PLAYLIST: 'youtube_playlist',
 | 
			
		||||
    YOUTUBE_VIDEO: 'youtube_video',
 | 
			
		||||
    SOUNDCLOUD_TRACK: 'soundcloud_track',
 | 
			
		||||
    SOUNDCLOUD_PLAYLIST: 'soundcloud_playlist',
 | 
			
		||||
    YOUTUBE_SEARCH: 'youtube_search',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = { QueryType };
 | 
			
		||||
							
								
								
									
										32
									
								
								backend/src/utils/Resolver.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								backend/src/utils/Resolver.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
const {Links} = require('./Links')
 | 
			
		||||
const {QueryType} = require('./QueryType')
 | 
			
		||||
 | 
			
		||||
function getQueryType(url) {
 | 
			
		||||
    // Check if it's string
 | 
			
		||||
 
 | 
			
		||||
    if(typeof url !== "string") return "NOT_STRING"
 | 
			
		||||
    // Check if it's a Youtube link
 | 
			
		||||
  
 | 
			
		||||
    if(Links.regex.youtube.playlist.test(url)) return QueryType.YOUTUBE_PLAYLIST
 | 
			
		||||
    if(Links.regex.youtube.videoURL.test(url)) return QueryType.YOUTUBE_VIDEO
 | 
			
		||||
    
 | 
			
		||||
    // Check if it's a Spotify link
 | 
			
		||||
 | 
			
		||||
    if(Links.regex.spotify.playlist.test(url)) return QueryType.SPOTIFY_PLAYLIST
 | 
			
		||||
    if(Links.regex.spotify.album.test(url)) return QueryType.SPOTIFY_ALBUM
 | 
			
		||||
    if(Links.regex.spotify.song.test(url)) return QueryType.SPOTIFY_SONG
 | 
			
		||||
    
 | 
			
		||||
    // Check if it's a Soundcloud link
 | 
			
		||||
 
 | 
			
		||||
    if(Links.regex.soundcloud.track.test(url)) return QueryType.SOUNDCLOUD_TRACK
 | 
			
		||||
    if(Links.regex.soundcloud.playlist.test(url)) return QueryType.SOUNDCLOUD_PLAYLIST
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    return QueryType.YOUTUBE_SEARCH
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
module.exports = {getQueryType}
 | 
			
		||||
							
								
								
									
										45
									
								
								backend/src/utils/YoutubeDuration.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								backend/src/utils/YoutubeDuration.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
const config = require('../utils/Database/Configuration');
 | 
			
		||||
const YOUTUBE_API_KEY = config.getYoutubeApiKey()
 | 
			
		||||
 | 
			
		||||
async function getDurationVideo(videoId) {
 | 
			
		||||
    const clog = require("loguix").getInstance("YoutubeInformation");
 | 
			
		||||
    // Check videoId if valid 
 | 
			
		||||
    if(videoId === null && typeof videoId !== 'string') {
 | 
			
		||||
        clog.error("Impossible de récupérer la durée de la vidéo YouTube, car l'identifiant est nul ou n'est pas une chaîne de caractères");
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fetch video information
 | 
			
		||||
    try {
 | 
			
		||||
        const response = await fetch(`https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=${videoId}&key=${YOUTUBE_API_KEY}`);
 | 
			
		||||
        const data = await response.json();
 | 
			
		||||
        const video = data.items[0];
 | 
			
		||||
        if(video) {
 | 
			
		||||
     
 | 
			
		||||
            if(video.contentDetails.duration == "P0D") return "LIVE";
 | 
			
		||||
            const duration = video.contentDetails.duration;
 | 
			
		||||
            //Convert ISO 8601 duration to seconds
 | 
			
		||||
            return parseDuration(duration);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            clog.error("Impossible de récupérer la durée de la vidéo YouTube à partir de l'identifiant");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        clog.error('Erreur lors de la recherche de la durée de la vidéo YouTube:', error);
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function parseDuration(duration) {
 | 
			
		||||
    const match = duration.match(/PT(\d+H)?(\d+M)?(\d+S)?/);
 | 
			
		||||
    const hours = parseInt(match[1]) || 0;
 | 
			
		||||
    const minutes = parseInt(match[2]) || 0;
 | 
			
		||||
    const seconds = parseInt(match[3]) || 0;
 | 
			
		||||
    return hours * 3600 + minutes * 60 + seconds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {getDurationVideo}
 | 
			
		||||
		Reference in New Issue
	
	Block a user