diff --git a/.gitignore b/.gitignore index 7870a7c..98ff7cc 100644 --- a/.gitignore +++ b/.gitignore @@ -132,6 +132,6 @@ dist .pnp.* data/config.json - +data diff --git a/DONTREADME.md b/DONTREADME.md new file mode 100644 index 0000000..cd802b1 --- /dev/null +++ b/DONTREADME.md @@ -0,0 +1,17 @@ +# **Easter Egg Subsonics** + +> Un savant fou fait des recherches sur les gens du CLP et a caché son système et ses recherches sur le site du bot + +**Etapes** + +* Page caché +* Confirmation avec le bot +* Erreur assembler le programme +* Accès aux donnés + + +# Idéés + +- Faille dans le bot (à) la recherche +- C'est moi le grand méchant et il doivent arrêter mon plan macchiavélique +- Etape : Me parler pour me soutirer des infos : Genre une histoire \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md index e6ad101..60688a1 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,12 @@ -#
Subsonics Web
+ -
+#
Subsonics WEB
-* En cas de bug, n'hésitez pas à faire un **report** sur votre profil. -* Vous pouvez utiliser la commande **/restart** sur Discord pour redémarrer l'intégralité du Bot ! -* Pour toute suggestion, vous pouvez envoyez un rapport avec la catégorie Suggestion ! +
Bienvenue sur le site de Subsonics ! Recherche, lance et écoute !
+Si tu veux utiliser le bot, pas de soucis mais vérifie que quelqu'un ne l'utilise pas !
- -
- -
- -
- - -
Développé par Raphix
-
Avec l'aide de Gabouille et de IcePlayer
-
Pour le CLP 💖
-
- -
- - -# Changelog - -## Subsonics - Web - 2.0.0 - - **Adds :** *Rework Style, Soundboard Editor, OOBE* - ### Details -**Rework Style** -> - Style principal, (Cf StylePlans) -> - Création d'éléments modèles (Classe commune) -> - Permettre l'ajout de playlist youtube en favoris - -**Soundboard Editor** -> - Faire l'HTML & CSS -> - Faire le lien entre l'API Discord et Subsonics -> - Demander les permissions à IcePlayer - -**OOBE** -> - Faire l'HTML & CSS -> - Faire la vérification de la lecture de l'OOBE +
+
Fait avec ❤️ par Raphix +
Pour le CLP :) +
Avec l'aide de Gabouille et de IcePlayer
+
\ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 819aaf6..77fc148 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "erela.js": "^2.4.0", "express": "^4.18.2", "express-favicon": "^2.0.4", + "genius-lyrics": "^4.4.6", "loguix": "^1.4.2", "markdown-it": "^13.0.1", "nodemon": "^2.0.22", @@ -107,6 +108,14 @@ "node": ">=16.9.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", + "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", + "engines": { + "node": ">=14" + } + }, "node_modules/@opencensus/core": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.9.tgz", @@ -810,6 +819,11 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -835,17 +849,6 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1098,6 +1101,32 @@ "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/culvert": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", @@ -1202,6 +1231,68 @@ "node": ">=16.9.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1681,6 +1772,15 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/genius-lyrics": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/genius-lyrics/-/genius-lyrics-4.4.6.tgz", + "integrity": "sha512-TeSF4qXwLm+Nl8wUX+WUTJlEhPBanMw9EWpIHE2a/Qs4y2NBK99AHYfZJc73H1HVkZj4zPfscuGWlkQbbh0pDA==", + "dependencies": { + "node-html-parser": "^6.1.9", + "undici": "^5.24.0" + } + }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", @@ -1845,6 +1945,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2341,6 +2449,15 @@ "node": ">= 0.4.0" } }, + "node_modules/node-html-parser": { + "version": "6.1.12", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.12.tgz", + "integrity": "sha512-/bT/Ncmv+fbMGX96XG9g05vFt43m/+SYKIs9oAemQVYyVcZmDAI2Xq/SbNcpOA35eF0Zk2av3Ksf+Xk8Vt8abA==", + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, "node_modules/nodemon": { "version": "2.0.22", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", @@ -2420,6 +2537,17 @@ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -3470,14 +3598,6 @@ "node": ">= 0.8" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3674,11 +3794,11 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" }, "node_modules/undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", + "version": "5.28.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.2.tgz", + "integrity": "sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==", "dependencies": { - "busboy": "^1.6.0" + "@fastify/busboy": "^2.0.0" }, "engines": { "node": ">=14.0" @@ -3893,6 +4013,11 @@ "ws": "^8.13.0" } }, + "@fastify/busboy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", + "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==" + }, "@opencensus/core": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.9.tgz", @@ -4431,6 +4556,11 @@ "unpipe": "1.0.0" } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4453,14 +4583,6 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "requires": { - "streamsearch": "^1.1.0" - } - }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -4654,6 +4776,23 @@ "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, "culvert": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", @@ -4736,6 +4875,46 @@ "ws": "^8.13.0" } }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "dependencies": { + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + } + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -5076,6 +5255,15 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "genius-lyrics": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/genius-lyrics/-/genius-lyrics-4.4.6.tgz", + "integrity": "sha512-TeSF4qXwLm+Nl8wUX+WUTJlEhPBanMw9EWpIHE2a/Qs4y2NBK99AHYfZJc73H1HVkZj4zPfscuGWlkQbbh0pDA==", + "requires": { + "node-html-parser": "^6.1.9", + "undici": "^5.24.0" + } + }, "get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", @@ -5194,6 +5382,11 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -5574,6 +5767,15 @@ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" }, + "node-html-parser": { + "version": "6.1.12", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.12.tgz", + "integrity": "sha512-/bT/Ncmv+fbMGX96XG9g05vFt43m/+SYKIs9oAemQVYyVcZmDAI2Xq/SbNcpOA35eF0Zk2av3Ksf+Xk8Vt8abA==", + "requires": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, "nodemon": { "version": "2.0.22", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", @@ -5635,6 +5837,14 @@ } } }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -6406,11 +6616,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -6543,11 +6748,11 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" }, "undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", + "version": "5.28.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.2.tgz", + "integrity": "sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==", "requires": { - "busboy": "^1.6.0" + "@fastify/busboy": "^2.0.0" } }, "universalify": { diff --git a/package.json b/package.json index e348073..3b3e698 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "subsonics-web", "author": "Raphix", - "version": "1.1.0", + "version": "2.0.0", "nodemonConfig": { "ext": "js, html", "ignore": [ @@ -19,6 +19,7 @@ "erela.js": "^2.4.0", "express": "^4.18.2", "express-favicon": "^2.0.4", + "genius-lyrics": "^4.4.6", "loguix": "^1.4.2", "markdown-it": "^13.0.1", "nodemon": "^2.0.22", diff --git a/src/commands/restart.js b/src/commands/restart.js index 3b58e9a..86b08ea 100644 --- a/src/commands/restart.js +++ b/src/commands/restart.js @@ -16,8 +16,9 @@ module.exports = { await interaction.reply({embeds: [membed]}) - pm2.restart('SubSonics - Bot Discord') + pm2.restart("Subsonics") } -} \ No newline at end of file +} + diff --git a/src/modules/discord-bot.js b/src/modules/discord-bot.js index 65e85cd..0e46024 100644 --- a/src/modules/discord-bot.js +++ b/src/modules/discord-bot.js @@ -6,8 +6,6 @@ const { __glob } = require("./global-variables") const { LogType } = require("loguix") const { List } = require("./sub-list") const nodeFinder = require("./nodes-finder") -const subplayer = require("./sub-player") -const nodemon = require("nodemon") const metric = require("webmetrik") const client = new Client({ @@ -153,25 +151,6 @@ function init(dlog, config) { function startErelaManager(dlog, config) { const elog = new LogType("Lavalink-Manager") - - client.on("voiceStateUpdate", (oldMember, newMember) => { - - membersVoices.set(newMember.id, newMember.channelId) - - let player = client.manager.players.get(oldMember.guild.id) - - if(player) { - - client.channels.fetch(player.options.voiceChannel).then(channel => { - - if(channel.members.size <= 1) { - - player.destroy() - } - }) - } - }) - const nodes = nodeFinder.getNodes() client.manager = new Manager({ @@ -191,19 +170,22 @@ function startErelaManager(dlog, config) { membersVoices.set(newMember.id, newMember.channelId) + /* SECURITY DISABLED let player = client.manager.players.get(oldMember.guild.id) + + if(player) { + + client.channels.fetch(player.options.voiceChannel).then(channel => { - if(player) { + if(channel.members.size <= 1) { - client.channels.fetch(player.options.voiceChannel).then(channel => { - - if(channel.members.size <= 1) { - - player.destroy() - plog.log("[Automatic Task] Player supprimé dans : " + channel.name) - } - }) - } + player.destroy() + plog.log("[Automatic Task] Player supprimé dans : " + channel.name) + } + }) + + }*/ + }) @@ -261,9 +243,8 @@ function startErelaManager(dlog, config) { if(await list.haveSongs()) { await player.play(list.next()) - + console.log("Lecture de la musique suivante") } - } @@ -295,17 +276,4 @@ function startErelaManager(dlog, config) { client.on("raw", d => client.manager.updateVoiceState(d)); } -async function closeClient() { - console.log("Fermeture du client Discord") - if(client) { - let player = await client.manager.players.get("137291455336022018") - if(player) { - await player.destroy() - } - client.destroy() - } - -} - - diff --git a/src/modules/global-variables.js b/src/modules/global-variables.js index 2f1198f..9923f68 100644 --- a/src/modules/global-variables.js +++ b/src/modules/global-variables.js @@ -17,10 +17,10 @@ const __glob = { NODES: root + path.sep + "data" + path.sep + "nodes.json", README: root + path.sep + "README.md", PLAYLIST: root + path.sep + "data" + path.sep + "playlist.json", - RADIO: root + path.sep + "data" + path.sep + "radios.json", LOGS: root + path.sep + "src" + path.sep + "modules" + path.sep + "logs", METRIC_FILE: root + path.sep + "data" + path.sep + "metrics.json", PICTURE_DIR: root + path.sep + "data" + path.sep + "pictures", + PREVIOUS_FILE: root + path.sep + "data" + path.sep + "previous.json", }; const webroot = __glob.WEB_DIR + path.sep diff --git a/src/modules/nodes-finder.js b/src/modules/nodes-finder.js index ba0e0f0..3d8b81a 100644 --- a/src/modules/nodes-finder.js +++ b/src/modules/nodes-finder.js @@ -91,6 +91,7 @@ module.exports.addNodes = function (data) { nlog.step.init("add_nodes", "Ajout d'un nouveau noeud dans la base de donnée de nodes : " + data.host) try { var nodes_data = readNodesFile() + data.retryAmount = 1 nodes_data.push(data) saveNodesFile(nodes_data) nlog.step.end("add_nodes") diff --git a/src/modules/sub-auth.js b/src/modules/sub-auth.js index 9a19f4e..b979c69 100644 --- a/src/modules/sub-auth.js +++ b/src/modules/sub-auth.js @@ -1,6 +1,7 @@ const { __glob, __web } = require("./global-variables"); const { LogType } = require('loguix'); const fs = require("fs"); +const { log } = require("console"); const alog = new LogType("Authentification") @@ -60,13 +61,14 @@ module.exports.getDiscordUser = function (code, session) { reject("NOT_IN_CLP") } else if(typeof userInfo.user == "undefined") { reject("MIGRATE_ACCOUNT_ONLY") - } else { + } else { // Replace existing user from the DB file if exist const userDB = readUsersFile(__glob.USERS) - for (const user of userDB) { - if(user.user.id == userInfo.user.id) { - userInfo.token = user.token + for (const userFromDB of userDB) { + if(userFromDB.user.id == userInfo.user.id) { + userInfo.token = userFromDB.token + user.banned = userFromDB.banned } } @@ -74,10 +76,20 @@ module.exports.getDiscordUser = function (code, session) { if(userInfo.user.id == "486943594893017119") { user.admin = true; + user.banned = false; } + + Object.assign(user, userInfo); - resolve(user); + + if(user.banned) { + reject("ACCOUNT_BANNED") + alog.log("Tentative de connexion d'un utilisateur banni : " + user.user.username) + } else { + resolve(user); + } + } }).catch(error => reject(error)) @@ -122,11 +134,16 @@ module.exports.removeSession = function (session) { module.exports.checkUser = function (token) { + var users = this.getUsers() for(var user of users) { - if(user[1].token.includes(token)) { - - return true + if(user.token.includes(token)) { + + if(user.banned) { + return false + } else { + return true + } } } @@ -136,11 +153,17 @@ module.exports.checkUser = function (token) { module.exports.getUser = function (token) { + var users = this.getUsers() for(var user of users) { - if(user[1].token.includes(token)) { - - return user[1] + if(user.token.includes(token)) { + if(user.banned) { + return null + } else { + return user + } + + } } @@ -148,7 +171,7 @@ module.exports.getUser = function (token) { } -module.exports.getUsers = function () { +module.exports.getUsers = function() { const userDB = readUsersFile(__glob.USERS) return userDB @@ -156,7 +179,7 @@ module.exports.getUsers = function () { } -module.exports.getSimpleUsers = function () { +module.exports.getSimpleUsers = function() { var userList = new Array() const userDB = readUsersFile(__glob.USERS) @@ -172,7 +195,7 @@ module.exports.getSimpleUsers = function () { } -module.exports.getSimpleUser = function (token) { +module.exports.getSimpleUser = function(token) { const user = this.getUser(token) @@ -184,8 +207,46 @@ module.exports.getSimpleUser = function (token) { return ({"username": user.user.username, "global_name":user.user.global_name, "avatar": user.user.avatar, "id": user.user.id, "admin": user.admin, "picture": user.picture}) } +module.exports.getOOBE = function(userId) { + + const userDB = readUsersFile(__glob.USERS) + for (const user of userDB) { + if(user.user.id == userId) { + if(!user.oobe) { + return true + } + } + } + return false +} -module.exports.addUser = function (user) { +module.exports.setOOBE = function(userId) { + + const userDB = readUsersFile(__glob.USERS) + var selectedUser = null + + + for(var user of userDB) { + + if(userId == user.user.id) { + + selectedUser = user + } + + } + + if(!selectedUser) { + return + } + userDB[userDB.indexOf(selectedUser)].oobe = true + + saveUsersFile(userDB) +} + + + + +module.exports.addUser = async function(user) { const userDB = readUsersFile(__glob.USERS) @@ -203,46 +264,56 @@ module.exports.addUser = function (user) { - if(selectedUser != null) { + if(selectedUser) { userDB[selectedUser].token = user.token + if(user.user.id == "486943594893017119") { + userDB[selectedUser].banned = false + } } else { userDB.push(user) } + + saveUsersFile( userDB) var OPdest = __glob.PICTURE_DIR + "/" + user.user.id + ".png" if (fs.existsSync(OPdest)) { fs.rmSync(OPdest); } - checkAllPictures() + await checkAllPictures() updateUsers() alog.log("Ajout de " + user.user.username + " en tant qu'utilisateur avec le token : " + user.token) } -module.exports.removeUser = function (token) { +module.exports.removeUser = function(id) { const userDB = readUsersFile(__glob.USERS) var selectedUser = null - for (const user of userDB) { - if(user.token == token) { - selectedUser = user + + for(var user of userDB) { + + if(id == user.user.id) { + + selectedUser = userDB.indexOf(user) } - } - const index = userDB.indexOf(selectedUser) - alog.log("Supression de " + selectedUser.user.username + " en tant qu'utilisateur avec le token : " + selectedUser.token) - userDB.splice(index, 1) + } + + + alog.log("Supression de " + userDB[selectedUser].user.username + " en tant qu'utilisateur avec le token : " + userDB[selectedUser].token) + + userDB.splice(selectedUser, 1) saveUsersFile(userDB) updateUsers() } -module.exports.removeToken = function (token) { +module.exports.removeToken = function(token) { const userDB = readUsersFile(__glob.USERS) var selectedUser = null @@ -253,7 +324,7 @@ module.exports.removeToken = function (token) { selectedUser = user } } - const index = userDB.indexOf(selectedUser) + alog.log("Supression du token de " + selectedUser.user.username + " en tant qu'utilisateur avec le token : " + selectedUser.token) const tokens = selectedUser.token @@ -265,17 +336,17 @@ module.exports.removeToken = function (token) { } -module.exports.setAdmin = function (user) { +module.exports.setAdmin = function(id) { const userDB = readUsersFile(__glob.USERS) var selectedUser = null - for(var userI of userDB) { + for(var user of userDB) { - if(user.user.id == userI.user.id) { + if(id == user.user.id) { - selectedUser = userDB.indexOf(userI) + selectedUser = userDB.indexOf(user) } } @@ -295,10 +366,45 @@ module.exports.setAdmin = function (user) { saveUsersFile(userDB) updateUsers() - alog.log("Ajout de " + user.user.username + " en tant qu'administrateur avec le token : " + user.token) + alog.log("Ajout de " + userDB[selectedUser].user.username + " en tant qu'administrateur !") } +module.exports.setBan = function(id) { + + const userDB = readUsersFile(__glob.USERS) + + var selectedUser = null + + for(var user of userDB) { + + if(id == user.user.id) { + + selectedUser = userDB.indexOf(user) + } + + } + + if(!userDB[selectedUser].banned) { + + userDB[selectedUser].banned = true + console.log("[Personnal Quote] - New Ban") + + } else { + + userDB[selectedUser].banned = false + console.log("[Personnal Quote] - Remove Ban") + + } + + saveUsersFile(userDB) + + updateUsers() + alog.log("Ajout de " + userDB[selectedUser].user.username + " en tant que banni !") + +} + + function updateUsers() { diff --git a/src/modules/sub-list.js b/src/modules/sub-list.js index 87ac4b5..988b2eb 100644 --- a/src/modules/sub-list.js +++ b/src/modules/sub-list.js @@ -2,29 +2,76 @@ const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); const { __glob } = require("../modules/global-variables"); const { LogType } = require('loguix'); const discord = require("./discord-bot") +const fs = require('fs') const dlog = new LogType("Queue-List") var next = new Array() -var previous = new Array() var current = null; var shuffle = false +if(!fs.existsSync(__glob.PREVIOUS_FILE)) { + fs.writeFileSync(__glob.PREVIOUS_FILE, JSON.stringify(new Array(), null, 2)) +} + module.exports.List = class { getList() { - return next } + getPreviousList() { + return getPreviousFile() + } + + getCurrent() { + return current + } + + removeAll() { + next = new Array() + process.emit("MUSIC_UPDATE_STATE") + } + destroy() { next = new Array() - previous = new Array() current = null shuffle = false } + playQueue(data) { + // Play the song with the index in the queue and delete it from the queue + + var index = data[0] + var list = data[1] + + if(list == "next") { + + const song = next[index] + next.splice(index, 1) + + return song + } else if(list == "previous") { + + const song = getPreviousFile()[index] + + return song + + } + + } + + changeQueue(index) { + //PREVIOUS TO NEXT + + const song = getPreviousFile()[index] + next.push(song) + + process.emit("MUSIC_UPDATE_STATE") + + } + setShuffle(state) { shuffle = state @@ -55,10 +102,15 @@ module.exports.List = class { } + + previous() { - const song = previous[0] - previous.splice(0, 1) + const song = getPreviousFile()[0] + var previousList = getPreviousFile() + previousList.splice(0, 1) + savePreviousFile(previousList) + return song } @@ -70,8 +122,12 @@ module.exports.List = class { } addCurrentToPrevious() { - - previous.unshift(current) + if(current) { + var previousList = getPreviousFile() + previousList.unshift(current) + savePreviousFile(previousList) + } + } @@ -88,7 +144,8 @@ module.exports.List = class { havePreviousSongs() { - if(previous.length == 0) { + var previousList = getPreviousFile() + if(previousList.length == 0) { return false } else{ @@ -97,6 +154,8 @@ module.exports.List = class { } + + getNextSong() { const song = next[0] @@ -106,6 +165,11 @@ module.exports.List = class { async add(song, interaction) { + + if(!song) { + process.emit("MUSIC_UPDATE_STATE") + return + } dlog.log("Ajout d'un titre dans la liste de lecture : '" + song.title + "' de '" + song.author + "'") next.push(song) @@ -155,21 +219,29 @@ module.exports.List = class { } __previous_add(song) { - - previous.unshift(song) + if(song) { + var previousList = getPreviousFile() + previousList.unshift(song) + savePreviousFile(previousList) + } + } __previous_remove(song) { - - const index = next.indexOf(song) - previous.splice(index, 1) + if(song) { + var previousList = getPreviousFile() + previousList.splice(previousList.indexOf(song), 1) + savePreviousFile(previousList) + } + } __next_add(song) { - - next.unshift(song) - + if(song) { + next.unshift(song) + } + } async replaceList(data) { @@ -188,7 +260,7 @@ module.exports.List = class { } - async playlistAdd(playlist, interaction, userId, ) { + async playlistAdd(playlist, interaction, userId, quick ) { var client = discord.getClient() let player = client.manager.players.get("137291455336022018") @@ -221,13 +293,24 @@ module.exports.List = class { } + var numberExecuted = 0 for(var song of playlist.videos) { if(song.uri) { song.url = song.uri } const song_finded = await client.manager.search(song.url) + // Avoid if song not found + if(!song_finded.tracks[0]) { + numberExecuted += 1 + continue + } next.push(song_finded.tracks[0]) - process.emit("MUSIC_UPDATE_STATE") + numberExecuted++ + if(numberExecuted == playlist.videos.length) { + + process.emit("MUSIC_UPDATE_STATE") + } + } if(!player) { @@ -256,6 +339,11 @@ module.exports.List = class { player.play(next[0]) this.remove(next[0]) + } else { + if(quick) { + player.play(next[0]) + this.remove(next[0]) + } } @@ -266,3 +354,24 @@ module.exports.List = class { } + +/** + * + * @returns {Array} + */ +function getPreviousFile() { + return JSON.parse(fs.readFileSync(__glob.PREVIOUS_FILE, 'utf8')) +} + + +function savePreviousFile(db) { + + // Add a security to avoid a too big file + if(db.length > 25) { + db.splice(25, db.length - 25) + } + + + fs.writeFileSync(__glob.PREVIOUS_FILE, (JSON.stringify(db, null, 2))) + +} \ No newline at end of file diff --git a/src/modules/sub-player.js b/src/modules/sub-player.js index a237c70..aae0e63 100644 --- a/src/modules/sub-player.js +++ b/src/modules/sub-player.js @@ -9,6 +9,12 @@ const { Metric } = require("webmetrik"); const list = new List() +module.exports.getSong = async function (url) { + var client = discord.getClient() + const songs = await client.manager.search(url) + return songs.tracks[0] +} + module.exports.play = async function (client, interaction) { if(interaction) { @@ -187,12 +193,12 @@ module.exports.getState = function(client, interaction) { } -module.exports.playPlaylist = function (id, data) { +module.exports.playPlaylist = function (id, data, quick) { const playlist = {} playlist.videos = data - list.playlistAdd(playlist, null, id) + list.playlistAdd(playlist, null, id, quick) } @@ -241,6 +247,10 @@ module.exports.addSong = async function (data, userId, quick, playlist) { player.play(songs.tracks[0]) + if(list.getCurrent()) { + + list.__previous_add(list.getCurrent()) + } } else { if(!player.playing && player.paused == false) { @@ -260,15 +270,20 @@ module.exports.addSong = async function (data, userId, quick, playlist) { } -module.exports.addSongsFromPlaylist = async function (data, userId) { +module.exports.addSongsFromPlaylist = async function (data, userId, quick) { var playlist = await checkPlaylist(data) if(playlist) { - - list.playlistAdd(playlist, null, userId) + if(quick) { + list.removeAll() + list.playlistAdd(playlist, null, userId, true) + } else { + list.playlistAdd(playlist, null, userId) + } + } @@ -329,6 +344,7 @@ module.exports.skip = function (client, interaction) { if(player) { player.stop() + } @@ -668,11 +684,13 @@ module.exports.updateMusicState = function (client, action) { } data["queue"] = list.getList(); + data["isOnline"] = true } - + data["previous"] = list.getPreviousList(); + if(action == "end") { data["current"] = null; @@ -738,6 +756,26 @@ module.exports.leave = function (client, interaction) { } +module.exports.moveOut = function(userId) { + var memberVoices = discord.getMemberVoices() + var channelId = memberVoices.get(userId) + + console.log(channelId) + + if(channelId) { + + var client = discord.getClient() + var player = client.manager.players.get("137291455336022018") + if(player) { + + player.voiceChannel = channelId + player.connect() + + } + } + +} + // FINI async function checkPlaylist (song_name) { @@ -754,6 +792,8 @@ async function checkPlaylist (song_name) { } + + function playStats(username) { var userMusicPlayed = new Metric("userMusicPlayed_" + username, "Nombre de musiques jouées par l'utilisateur : " + username) userMusicPlayed.setValue(userMusicPlayed.getValue() + 1) diff --git a/src/modules/sub-playlist.js b/src/modules/sub-playlist.js index 9f48f31..9e7b9c3 100644 --- a/src/modules/sub-playlist.js +++ b/src/modules/sub-playlist.js @@ -3,49 +3,113 @@ const { __glob } = require("../modules/global-variables"); const { LogType } = require("loguix"); const subplayer = require("./sub-player") const fs = require("fs"); +const { randomUUID } = require("crypto"); +const { url } = require("inspector"); var playlists = {} const plog = new LogType("Playlist-Manager") check() -module.exports.getUser = function (id) { + +module.exports.getUser = function (userId) { check() - if(!playlists[id]) { - plog.log("Ajout de l'utilisateur \"" + id + "\" dans la base de donnée Playlist !") - playlists[id] = {} + var allPlaylist = new Object() + // Inject "shared" playlist object in allPlaylist + + if(playlists[userId]) { + // Copy the keys of the user playlist to the allPlaylist object + for(var key in playlists[userId]) { + allPlaylist[key] = playlists[userId][key] + } + // Copy the keys of the shared playlist to the allPlaylist object + for(var key in playlists["shared"]) { + allPlaylist[key] = playlists["shared"][key] + } + } + + + + if(!playlists[userId]) { + plog.log("Ajout de l'utilisateur \"" + userId + "\" dans la base de donnée Playlist !") + playlists[userId] = {} fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) - return playlists[id] + + return allPlaylist } else { - plog.log("L'utilisateur \"" + id + "\" existe déjà dans la base de donnée Playlist !") - return playlists[id] + plog.log("L'utilisateur \"" + userId + "\" existe déjà dans la base de donnée Playlist !") + + return allPlaylist } + + } -module.exports.addPlaylist = function (id, name) { +module.exports.addPlaylist = function (userId, data) { check() - if(!playlists[id][name]) { - plog.log("Ajout de la playlist à l'utilisateur \"" + id + "\" dans la base de donnée Playlist !") - playlists[id][name] = [] + var name = data.name + var source = data.source + var content = [] + + if(source == "shared") { + userId = "shared" + + } + + var alreadyExist = false + + for(var pIndex in playlists[userId]) { + if(playlists[userId][pIndex].title == name) { + alreadyExist = true + } + } + + if(!alreadyExist) { + plog.log("Ajout de la playlist '" + name + "' à l'utilisateur \"" + userId + "\" dans la base de donnée Playlist !") + var id = randomUUID().toString() + + if(source == "youtube") { + content = data.url + } + + playlists[userId][id] = { + "title": name, + "source": data.source, + "content": content + } fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) } else { - plog.log("L'utilisateur \"" + id + "\" à déjà une playlist avec le nom "+ name + " dans la base de donnée Playlist !") + plog.log("L'utilisateur \"" + userId + "\" à déjà une playlist avec le nom " + name + " dans la base de donnée Playlist !") } + process.emit("PLAYLIST_REFRESH") + } -module.exports.copyPlaylist = function (id, from, dest) { - this.getUser(dest) +module.exports.copyPlaylist = function (userId, from, dest) { check() - let playlistDest = playlists[dest][from] - if(!playlistDest) { - plog.log("Ajout de la playlist à l'utilisateur \"" + id + "\" dans la base de donnée Playlist !") - playlists[dest][from] = playlists[id][from] + this.getUser(dest) + + userId = checkSharedMusic(from, userId) + + var alreadyExist = false + + for(var pIndex in playlists[dest]) { + if(playlists[dest][pIndex].title == playlists[userId][from].title) { + alreadyExist = true + } + } + + var id = randomUUID().toString() + + if(!alreadyExist) { + plog.log("Ajout de la playlist à l'utilisateur \"" + userId + "\" dans la base de donnée Playlist !") + playlists[dest][id] = playlists[userId][from] fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) } else { @@ -54,68 +118,134 @@ module.exports.copyPlaylist = function (id, from, dest) { } + process.emit("PLAYLIST_REFRESH") + + } -module.exports.removePlaylist = function (id, name) { +module.exports.removePlaylist = function (userId, id) { check() - if(playlists[id][name]) { - plog.log("Supression de la playlist à l'utilisateur \"" + id + "\" dans la base de donnée Playlist !") - delete playlists[id][name] + + userId = checkSharedMusic(id, userId) + + if(playlists[userId][id]) { + plog.log("Supression de la playlist à l'utilisateur \"" + userId + "\" dans la base de donnée Playlist !") + + delete playlists[userId][id] fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) } else { - plog.log("L'utilisateur \"" + id + "\" n'a pas une playlist avec le nom "+ name + " dans la base de donnée Playlist !") + plog.log("L'utilisateur \"" + userId + "\" n'a pas une playlist avec l'identifiant "+ id + " dans la base de donnée Playlist !") } -} + process.emit("PLAYLIST_REFRESH") -module.exports.addSong = function (id, name, song) { - check() - if(playlists[id][name]) { - - plog.log("Ajout d'une chanson dans la playlist '" + name + "' à l'utilisateur \"" + id + "\" dans la base de donnée Playlist !") - - playlists[id][name].push(song) - - fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) - } else { - - plog.log("L'utilisateur \"" + id + "\" n'a pas une playlist avec le nom "+ name + " dans la base de donnée Playlist !") - - } } - -module.exports.removeSong = function (id, name, song ) { +module.exports.renamePlaylist = function (userId, id, newName) { check() - if(playlists[id][name]) { - plog.log("Supression d'une chanson dans la playlist '" + name + "' à l'utilisateur \"" + id + "\" dans la base de donnée Playlist !") - playlists[id][name].splice(playlists[id][name].indexOf(song), 1) + + userId = checkSharedMusic(id, userId) + + if(playlists[userId][id]) { + plog.log("Renommage de la playlist à l'utilisateur \"" + userId + "\" dans la base de donnée Playlist !") + playlists[userId][id].title = newName fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) } else { - plog.log("L'utilisateur \"" + id + "\" n'a pas une playlist avec le nom "+ name + " dans la base de donnée Playlist !") + plog.log("L'utilisateur \"" + userId + "\" n'a pas une playlist avec l'identifiant "+ id + " dans la base de donnée Playlist !") + + } + + process.emit("PLAYLIST_REFRESH") + + +} + + +module.exports.addSong = async function (userId, id, urlSong) { + check() + + userId = checkSharedMusic(id, userId) + + if(playlists[userId][id]) { + + // Check if it's not a youtube playlist + + if(playlists[userId][id].source != "youtube") { + + plog.log("Ajout d'une chanson dans la playlist '" + id + "' à l'utilisateur \"" + userId + "\" dans la base de donnée Playlist !") + + var song = await subplayer.getSong(urlSong) + + playlists[userId][id].content.push(song) + + fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) + + } else { + + plog.log("La playlist '" + id + "' à l'utilisateur \"" + userId + "\" est une playlist youtube, vous ne pouvez pas ajouter de chanson à une playlist youtube !") + } + } else { + + plog.log("L'utilisateur \"" + userId + "\" n'a pas une playlist avec le nom "+ id + " dans la base de donnée Playlist !") } + process.emit("PLAYLIST_REFRESH") + + } -module.exports.playPlaylist = function (id, name) { + +module.exports.removeSong = function (userId, id, identifier ) { check() - if(playlists[id][name]) { - plog.log("Ajout de la playlist à l'utilisateur \"" + id + "\" dans la liste de lecture !") + + userId = checkSharedMusic(id, userId) + + if(playlists[userId][id]) { + plog.log("Supression d'une chanson dans la playlist '" + id + "' à l'utilisateur \"" + userId + "\" dans la base de donnée Playlist !") - subplayer.playPlaylist(id, playlists[id][name]) + // Check with the identifier the song to remove + + for(var song of playlists[userId][id].content) { + if(song.identifier == identifier) { + playlists[userId][id].content.splice(playlists[userId][id].content.indexOf(song), 1) + } + } + + fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) } else { - plog.log("L'utilisateur \"" + id + "\" n'a pas une playlist avec le nom "+ name + " dans la base de donnée Playlist !") + plog.log("L'utilisateur \"" + userId + "\" n'a pas une playlist avec le nom "+ id + " dans la base de donnée Playlist !") } + process.emit("PLAYLIST_REFRESH") + + +} + +module.exports.playPlaylist = function (userId, id, quick) { + check() + + userId = checkSharedMusic(id, userId) + + if(playlists[userId][id]) { + plog.log("Ajout de la playlist à l'utilisateur \"" + userId + "\" dans la liste de lecture !") + + subplayer.playPlaylist(id, playlists[userId][id].content, quick) + } else { + + plog.log("L'utilisateur \"" + userId + "\" n'a pas une playlist avec le nom "+ id + " dans la base de donnée Playlist !") + + } + + } @@ -127,6 +257,20 @@ function check() { playlists = JSON.parse(fs.readFileSync(__glob.PLAYLIST)) } else { - fs.writeFileSync(__glob.PLAYLIST, JSON.stringify(playlists, null, 2)) + fs.writeFileSync(__glob.PLAYLIST, JSON.stringify({ + "shared": { + + } + }, null, 2)) } +} + +function checkSharedMusic(id, originalUserId) { + for(var playlist in playlists["shared"]) { + if(playlist == id) { + return "shared" + } + } + + return originalUserId } \ No newline at end of file diff --git a/src/modules/sub-radio.js b/src/modules/sub-radio.js deleted file mode 100644 index 46cd78e..0000000 --- a/src/modules/sub-radio.js +++ /dev/null @@ -1,79 +0,0 @@ -const { __glob } = require("../modules/global-variables"); -const { LogType } = require("loguix"); -var { List } = require("./sub-list") -const discord = require("./discord-bot") -const subplayer = require("./sub-player") -const fs = require("fs"); -const { type } = require("os"); -var radios = [] -const plog = new LogType("Radio-Manager") - -checkRadioFile() - - -module.exports.get = function () { - - checkRadioFile() - return radios - -} - -module.exports.add = function (data) { - - var radios_data = readRadioFile() - - radios_data.push(data) - fs.writeFileSync(__glob.RADIO, JSON.stringify(radios_data, null, 2)) - - return radios - -} - -module.exports.remove = function(data) { - - var radios_data = readRadioFile() - - var radIndex = -1 - - for(var radio of radios_data) { - - if(data.uri == radio.uri) { - - radIndex = radios_data.indexOf(radio) - - } - - } - - - radios_data.splice(radIndex, 1) - - saveRadioFile(radios_data) - -} - - -function saveRadioFile(data) { - - fs.writeFileSync(__glob.RADIO, JSON.stringify(data, null, 2)) -} - -function readRadioFile() { - - if(fs.existsSync(__glob.RADIO)) { - - return JSON.parse(fs.readFileSync(__glob.RADIO)) - } -} - - -function checkRadioFile() { - - if(fs.existsSync(__glob.RADIO)) { - - radios = JSON.parse(fs.readFileSync(__glob.RADIO)) - } else { - - fs.writeFileSync(__glob.RADIO, JSON.stringify(radios, null, 2)) - } -} \ No newline at end of file diff --git a/src/modules/sub-web.js b/src/modules/sub-web.js index 6f96393..6c02407 100644 --- a/src/modules/sub-web.js +++ b/src/modules/sub-web.js @@ -5,7 +5,7 @@ const auth = require("./sub-auth"); const cook = require("cookie") const wlog = new LogType("Web") const subplayer = require('./sub-player'); -const subradio = require("./sub-radio.js") + const { List } = require("./sub-list") const subplaylist = require("./sub-playlist") const nodesfinder = require("./nodes-finder") @@ -13,6 +13,14 @@ const { Server } = require("socket.io") var fs = require("fs") var path = require("path") const { Metric } = require("webmetrik"); +const markdownit = require("markdown-it")({ + html: true, + linkify: true, + typographer: true +}) + +const Genius = require("genius-lyrics"); +const GClient = new Genius.Client("OHOV9c0B4uuyfWTK2w2YRliC9iyPjjF2Kk6ijCtZ2RtqfkZ2JpntnO2fwraF1A5h"); module.exports.WebServer = class { @@ -170,20 +178,18 @@ function IOConnection(io) { }) - process.on("UPDATE_RADIO", () => { - + process.on("PLAYLIST_REFRESH", () => { if(io) { - - const radioList = subradio.get() - AlwaysRequest("ALL_RADIO", radioList) - } - + AlwaysRequest("PLAYLIST_REFRESH", "OK") + } }) + process.on("MUSIC_UPDATE_STATE", () => { if(io) { const data = subplayer.updateMusicState() AlwaysRequest("MUSIC_STATE", data) + } }) @@ -201,7 +207,12 @@ function IOConnection(io) { const online_users_data = auth.getSimpleUser(token) if(online_users_data) { - usersOnline.push(online_users_data) + // Check if user is already connected and if not push it + if(!usersOnline.find(item => item.username == online_users_data.username)) { + usersOnline.push(online_users_data) + + } + alog.log(online_users_data.username + " - Connexion du serveur avec le socket : " + socket.id + " - " + socket.handshake.address + " - " + socket.handshake.headers["user-agent"]) } @@ -271,15 +282,7 @@ function IOConnection(io) { GetRequest("DISCONNECT", () => { subplayer.leave() GetAnswer("DISCONNECT", "OK") - sendUserNotification("à déconnecté le Bot de son salon vocal !") - }) - - GetRequest("RESTART", () => { - const pm2 = require('pm2'); - pm2.restart('SubSonics - Bot Discord') - sendUserNotification("à redémarré le Bot !") - GetAnswer("RESTART", "OK") - + }) GetRequest("NODES", () => { @@ -292,11 +295,26 @@ function IOConnection(io) { AlwaysRequest("ALL_CONNECTED_USER", usersOnline) }) - GetRequest("ALL_RADIO", async () => { - GetAnswer("ALL_RADIO", "OK") - AlwaysRequest("ALL_RADIO", await subradio.get()) + GetRequest("README", () => { + var content = markdownit.render(fs.readFileSync(__glob.README).toString()) + GetAnswer("README", content) + }) + GetRequest("OOBE_CHECK", () => { + GetAnswer("OOBE_CHECK", auth.getOOBE(user.user.id)) + }) + + GetRequest("OOBE_VALID", () => { + auth.setOOBE(user.user.id) + GetAnswer("OOBE_VALID", "OK") + }) + + + GetRequest("MOVEOUT", () => { + subplayer.moveOut(user.user.id) + GetAnswer("MOVEOUT", "OK") + }) PostRequest("SEEK", (data) => { subplayer.seek(data) @@ -308,12 +326,34 @@ function IOConnection(io) { PostAnswer("VOLUME", "OK") }) + PostRequest("PLAY_QUEUE", (data) => { + var sublist = new List() + subplayer.addSong(sublist.playQueue(data), user.user.id, true) + PostAnswer("PLAY_QUEUE", "OK") + + }) + + PostRequest("CHANGE_QUEUE", (data) => { + var sublist = new List() + sublist.changeQueue(data) + PostAnswer("CHANGE_QUEUE", "OK") + + }) + PostRequest("DELETE_QUEUE", (data) => { var sublist = new List() sublist.removeByIndex(data) PostAnswer("DELETE_QUEUE", "OK") - sendUserNotification("à supprimé un titre de la file d'attente !") + + }) + + PostRequest("DELETE_ALL_QUEUE", () => { + var sublist = new List() + sublist.removeAll() + + PostAnswer("DELETE_QUEUE", "OK") + }) PostRequest("MOVE_QUEUE", (data) => { @@ -321,7 +361,7 @@ function IOConnection(io) { sublist.moveUp(data) PostAnswer("MOVE_QUEUE", "OK") - sendUserNotification("à déplacé un titre de la file d'attente !") + }) PostRequest("MOVE_QUEUE_BY_ENTIRE", (data) => { @@ -329,7 +369,7 @@ function IOConnection(io) { sublist.replaceList(data) PostAnswer("MOVE_QUEUE_BY_ENTIRE", "OK") - sendUserNotification("à déplacé un titre tout au début de la file d'attente : " + data.title + " !") + }) PostRequest("REPORT", (data) => { @@ -337,7 +377,7 @@ function IOConnection(io) { data.username = user subplayer.report(null, null, data) PostAnswer("REPORT", "OK") - sendUserNotification("à signalé un bug et a été envoyé !") + }) PostRequest("SEARCH", async (data) => { @@ -348,38 +388,46 @@ function IOConnection(io) { PostRequest("ADD_SONG", async (data) => { subplayer.addSong(data, user.user.id) PostAnswer("ADD_SONG", "OK") - sendUserNotification("à ajouté un titre à la file d'attente : " + data.title + " !") + playStats(user.user.username) }) PostRequest("ADD_SONG_NOW", async (data) => { subplayer.addSong(data, user.user.id, true) PostAnswer("ADD_SONG_NOW", "OK") - sendUserNotification("à lancé un titre : " + data.title + " !") + playStats(user.user.username) }) PostRequest("FP_ADD_SONG", async (data) => { subplayer.addSong(data, user.user.id, false, true) PostAnswer("FP_ADD_SONG", "OK") - sendUserNotification("à ajouté un titre à la file d'attente : " + data.title + " !") + playStats(user.user.username) }) PostRequest("FP_ADD_SONG_NOW", async (data) => { subplayer.addSong(data, user.user.id, true, true) PostAnswer("FP_ADD_SONG_NOW", "OK") - sendUserNotification("à lancé une titre : " + data.title + " !") + playStats(user.user.username) }) PostRequest("PLAY_PLAYLIST", async (data) => { subplaylist.playPlaylist(user.user.id, data) PostAnswer("PLAY_PLAYLIST", "OK") - sendUserNotification("à ajouté une playlist à la file d'attente !") + playStats(user.user.username) }) + PostRequest("PLAY_PLAYLIST_NOW", async (data) => { + subplaylist.playPlaylist(user.user.id, data, true) + PostAnswer("PLAY_PLAYLIST_NOW", "OK") + + playStats(user.user.username) + }) + + PostRequest("CREATE_PLAYLIST", async (data) => { subplaylist.addPlaylist(user.user.id, data) socket.emit("DO_UPDATE_PLAYLIST") @@ -393,31 +441,70 @@ function IOConnection(io) { PostAnswer("DELETE_PLAYLIST", "OK") }) - PostRequest("FP_PLAY_PLAYLIST", async (data) => { - subplayer.addSongsFromPlaylist(data, user.user.id) - PostAnswer("FP_PLAY_PLAYLIST", "OK") - sendUserNotification("à ajouté une playlist à la file d'attente !") - }) - PostRequest("SEND_PLAYLIST", async (data) => { subplaylist.copyPlaylist(user.user.id, data.key, data.dest) socket.emit("DO_UPDATE_PLAYLIST") PostAnswer("SEND_PLAYLIST", "OK") }) + PostRequest("RENAME_PLAYLIST", async (data) => { + subplaylist.renamePlaylist(user.user.id, data.id, data.name) + socket.emit("DO_UPDATE_PLAYLIST") + PostAnswer("RENAME_PLAYLIST", "OK") + }) + PostRequest("ADD_SONG_TO_PLAYLIST", async (data) => { - subplaylist.addSong(user.user.id, data.data, data.song) + subplaylist.addSong(user.user.id, data.id, data.url) socket.emit("DO_UPDATE_PLAYLIST") PostAnswer("ADD_SONG_TO_PLAYLIST", "OK") }) PostRequest("DELETE_SONG_TO_PLAYLIST", async (data) => { - subplaylist.removeSong(user.user.id, data.data, data.song) + subplaylist.removeSong(user.user.id, data.id, data.identifier) socket.emit("DO_UPDATE_PLAYLIST") PostAnswer("DELETE_SONG_TO_PLAYLIST", "OK") }) + PostRequest("FP_PLAY_PLAYLIST", async (data) => { + subplayer.addSongsFromPlaylist(data, user.user.id) + PostAnswer("FP_PLAY_PLAYLIST", "OK") + + }) + + PostRequest("FP_PLAY_PLAYLIST_NOW", async (data) => { + subplayer.addSongsFromPlaylist(data, user.user.id, true) + PostAnswer("FP_PLAY_PLAYLIST", "OK") + + }) + + PostRequest("LYRICS", async (data) => { + const searches = await GClient.songs.search(data); + + if(!searches) { + PostAnswer("LYRICS", null) + return + } + const firstSong = searches[0]; + if(!firstSong) { + PostAnswer("LYRICS", null) + return + + } + + const lyrics = await firstSong.lyrics(); + if(!lyrics) { + PostAnswer("LYRICS", null) + return + } + + PostAnswer("LYRICS", lyrics) + }) + + + + + if(user.admin == true) { GetRequest("LOGS", () => { const logs_data = new Array() @@ -455,37 +542,6 @@ function IOConnection(io) { }) - PostRequest("RADIO/ADD", async (data) => { - const music_data = await (await subplayer.search(data)).results.tracks[0] - - var radioContains = null - - for(var title of subradio.get()) { - - if(title.uri == music_data.uri) { - - radioContains = true - } - } - - - if(!radioContains) { - - subradio.add(music_data) - console.log("[Radio] - ADD : " + data) - - } else { - - subradio.remove(music_data) - console.log("[Radio] - REMOVE : " + data) - - } - - PostAnswer("RADIO/ADD", "OK") - process.emit("UPDATE_RADIO") - - }) - PostRequest("USERS/ADMIN", (data) => { auth.setAdmin(data) PostAnswer("USERS/ADMIN", "OK") @@ -493,13 +549,29 @@ function IOConnection(io) { AdminRequest("USERS", users_data) }) + PostRequest("USERS/BAN", (data) => { + auth.setBan(data) + PostAnswer("USERS/BAN", "OK") + const users_data = auth.getUsers() + AdminRequest("USERS", users_data) + }) + PostRequest("USERS/DELETE", (data) => { - auth.removeUser(data.token) + auth.removeUser(data) PostAnswer("USERS/DELETE", "OK") const users_data = auth.getUsers() AdminRequest("USERS", users_data) }) + GetRequest("RESTART", () => { + const pm2 = require('pm2'); + pm2.restart('Subsonics') + + GetAnswer("RESTART", "OK") + + }) + + @@ -538,10 +610,7 @@ function IOConnection(io) { } - function sendUserNotification(text) { - - io.sockets.emit("NOTIFICATION", {"image_src": "https://cdn.discordapp.com/avatars/" + user.user.id + "/" + user.user.avatar, "text": user.user.global_name + " (" + user.user.username + ") " + text}) - } + }) @@ -562,10 +631,7 @@ function IOConnection(io) { } - function sendNotification(image_src, text) { - io.sockets.emit("NOTIFICATION", {"image_src": image_src, "text": text}) - } - + function playStats(username) { var userMusicPlayed = new Metric("userMusicPlayed_" + username, "Nombre de musiques jouées par l'utilisateur : " + username) diff --git a/src/web/public/images/black-image.svg b/src/web/public/images/black-image.svg deleted file mode 100644 index fad9438..0000000 --- a/src/web/public/images/black-image.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/web/public/images/default.jpg b/src/web/public/images/default.jpg new file mode 100644 index 0000000..4a93ad1 Binary files /dev/null and b/src/web/public/images/default.jpg differ diff --git a/src/web/public/images/logo-old.ico b/src/web/public/images/logo-old.ico deleted file mode 100644 index 439327f..0000000 Binary files a/src/web/public/images/logo-old.ico and /dev/null differ diff --git a/src/web/public/images/logo-test.ico b/src/web/public/images/logo-test.ico deleted file mode 100644 index d90e833..0000000 Binary files a/src/web/public/images/logo-test.ico and /dev/null differ diff --git a/src/web/public/images/logo-white.svg b/src/web/public/images/logo-white.svg new file mode 100644 index 0000000..10ece83 --- /dev/null +++ b/src/web/public/images/logo-white.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/web/public/images/logo.png b/src/web/public/images/logo.png deleted file mode 100644 index e5f7567..0000000 Binary files a/src/web/public/images/logo.png and /dev/null differ diff --git a/src/web/public/images/playlist-tile.svg b/src/web/public/images/playlist-tile.svg deleted file mode 100644 index f002fa6..0000000 --- a/src/web/public/images/playlist-tile.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/web/public/images/signout.svg b/src/web/public/images/signout.svg new file mode 100644 index 0000000..e0d705f --- /dev/null +++ b/src/web/public/images/signout.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/web/public/images/title.png b/src/web/public/images/title.png deleted file mode 100644 index 7097877..0000000 Binary files a/src/web/public/images/title.png and /dev/null differ diff --git a/src/web/public/javascript/IO.js b/src/web/public/javascript/IO.js index e459c49..34ed8e0 100644 --- a/src/web/public/javascript/IO.js +++ b/src/web/public/javascript/IO.js @@ -34,11 +34,11 @@ function get(request) { } -function post(request, data, secondata, thirddata) { +function post(request, data) { return new Promise((resolve, reject) => { - socket.emit("POST/" + request, data, secondata, thirddata) + socket.emit("POST/" + request, data) console.log("Envoi de la requête POST : " + request) socket.once("ANSWER/POST/" + request, (answer) => { diff --git a/src/web/public/javascript/basics.js b/src/web/public/javascript/basics.js index a990651..4593bec 100644 --- a/src/web/public/javascript/basics.js +++ b/src/web/public/javascript/basics.js @@ -1,16 +1,41 @@ -/** - * @param {string} id - * @returns element - */ function getID(id) { return document.getElementById(id); } -// Get The position of the mouse +function getTimeCode(duration) { + var max = "" + + + const maxhours = Math.floor(duration / 3600000); + + var maxmin = Math.trunc(duration / 60000) - (Math.floor(duration / 60000 / 60) * 60); + var maxsec = Math.floor(duration / 1000) - (Math.floor(duration / 1000 / 60) * 60); + + + if (maxsec < 10) { + maxsec = `0${maxsec}`; + } + + + if(maxhours != 0) { + + if (maxmin < 10) { + maxmin = `0${maxmin}`; + } + + + max = maxhours + ":" + maxmin + ":" + maxsec + } else { + max = maxmin + ":" + maxsec + + } + return max +} var xMousePos = 0; var yMousePos = 0; + document.onmousemove = function(e) { xMousePos = e.clientX + window.scrollX; @@ -18,170 +43,378 @@ document.onmousemove = function(e) } -function disableDrag() { - // Ajoutez un gestionnaire d'événement pour l'événement dragover - document.addEventListener('dragover', function (e) { - e.preventDefault(); // Empêche le comportement par défaut du navigateur - }); - // Ajoutez un gestionnaire d'événement pour l'événement drop - document.addEventListener('drop', function (e) { - e.preventDefault(); // Empêche le comportement par défaut du navigateur - }); -} - - - -// Pour réactiver le drag-and-drop, vous pouvez supprimer les gestionnaires d'événements -function enableDrag() { - // Supprimez le gestionnaire d'événement pour l'événement dragover - document.removeEventListener('dragover', function (e) { - e.preventDefault(); // Empêche le comportement par défaut du navigateur - }); - - // Supprimez le gestionnaire d'événement pour l'événement drop - document.removeEventListener('drop', function (e) { - e.preventDefault(); // Empêche le comportement par défaut du navigateur - }); -} - - -function startInterval() { - interval = setInterval(() => { - - - if(isPlaying == true) { - setTime() - - } - - }, 1000) - -} - -function stopInterval() { - clearInterval(interval); -} - - - -function setTime() { - - - durationBar.max = durationAll - durationProgress += 1000 - durationBar.value = durationProgress - - - const maxhours = Math.floor(durationAll / 3600000); - const nowhours = Math.floor(durationProgress / 3600000); - - - - var maxmin = Math.trunc(durationAll / 60000) - (Math.floor(durationAll / 60000 / 60) * 60); - var maxsec = Math.floor(durationAll / 1000) - (Math.floor(durationAll / 1000 / 60) * 60); - var nowmin = Math.trunc(durationProgress / 60000) - (Math.floor(durationProgress / 60000 / 60) * 60); - var nowsec = Math.floor(durationProgress / 1000) - (Math.floor(durationProgress / 1000 / 60) * 60); - - console.log(durationAll) - console.log(durationProgress) - console.log("---------------------") - - var now = "" - var max = "" - - - if (maxmin < 10) { - maxmin = `0${maxmin}`; - } - - if (nowmin < 10) { - nowmin = `0${nowmin}`; - } - - if (maxsec < 10) { - maxsec = `0${maxsec}`; - } - - if (nowsec < 10) { - nowsec = `0${nowsec}`; - } - - if(maxhours != 0) { - - max = maxhours + ":" + maxmin + ":" + maxsec - } else { - max = maxmin + ":" + maxsec - - } - - if(nowhours != 0) { - - now = nowhours + ":" + nowmin + ":" + nowsec - } else { - now = nowmin + ":" + nowsec - - } - - - - durationTextAct.innerHTML = now - durationTextTotal.innerHTML = max -} - -function getTimeCode(pdurationAll) { - var pmax = "" - - - const pmaxhours = Math.floor(pdurationAll / 3600000); - - var pmaxmin = Math.trunc(pdurationAll / 60000) - (Math.floor(pdurationAll / 60000 / 60) * 60); - var pmaxsec = Math.floor(pdurationAll / 1000) - (Math.floor(pdurationAll / 1000 / 60) * 60); - - - if (pmaxsec < 10) { - pmaxsec = `0${pmaxsec}`; - } - - - if(pmaxhours != 0) { - - if (pmaxmin < 10) { - pmaxmin = `0${pmaxmin}`; - } - - - pmax = pmaxhours + ":" + pmaxmin + ":" + pmaxsec - } else { - pmax = pmaxmin + ":" + pmaxsec +class User { + constructor(properties) { + this.userImg = properties.picture + this.userName = properties.name + this.userId = properties.id } - return pmax + + generateHTML() { + return `
+ +
+

${this.userName}

+

${this.userId}

+
+
` + } + + } -function loadHome() { +var ActualDroppableMenu = null - userLocation = "home" - - mainView.innerHTML = WelcomeContent - - get("ALL_CONNECTED_USER") - get("ALL_RADIO") +class DroppableMenu { + options = new Array() + id = null + DMSpanInteger = null + constructor() { + this.id = Math.random().toString(36).substring(7) + + } + + add(action, string) { + + this.options.push("
" + string + "
") + + } + + show() { + console.log("DROPPABLE MENU - " + this.id) + + if(ActualDroppableMenu) { + ActualDroppableMenu.hide() + } + + + ActualDroppableMenu = this + + if(xMousePos && yMousePos) { + + this.DMSpanInteger = document.createElement("span") + this.DMSpanInteger.id = "dm-" + this.id + this.DMSpanInteger.className = "dm-span" + + document.body.appendChild(this.DMSpanInteger); + + this.DMSpanInteger.innerHTML = this.options.join('') + const menu = getID(`dm-${this.id}`) + + menu.style.position = "absolute" + menu.style.left = (xMousePos - 100) + "px" + menu.style.top = (yMousePos - 40) + "px" + + menu.addEventListener("mouseleave", () => { + + this.hide() + + }) + + menu.addEventListener("click", () => { + this.hide() + }) + } + + } + + get(action) { + + return getID(this.id + "_" + action) + } + + hide() { + + const menu = getID(`dm-${this.id}`) + if(menu) { + menu.outerHTML = "" + console.log("HIDED") + } + + } +} + +class ModalComponent { + Element; + constructor(properties) { + this.title = properties.title + this.content = properties.content + this.closable = true + if(properties.closable != null) { + this.closable = properties.closable + } + if(properties.width) { + this.width = properties.width + } else { + this.width = "50%" + } + } + + show() { + var closableDiv = "×" + if(this.closable == false) { + closableDiv = "" + } + + this.Element = document.createElement("div") + this.Element.className = "modal" + this.Element.id = this.id + this.Element.innerHTML = `` + document.body.appendChild(this.Element) + this.Element.style.display = "flex" + + // Edit the width of modal content + const modalContent = getID("modal-content") + modalContent.style.width = this.width + + if(this.closable) { + + const close = getID("modal-close") + close.addEventListener("click", () => { + this.hide() + }) + + } + + } + + hide() { + this.Element.outerHTML = "" + + } + + setContent(content) { + this.content = content + + } + + + +} + +class VideoComponent { + constructor(data, playlist) { + + if(playlist) { + this.onPlaylist = true + this.title = data.title + this.author = data.author.name + this.thumbnail = data.thumbnail_url + this.url = data.url + this.duration = data.milis_length + this.identifier = data.id + this.type = data.type + this.self = data + } else { + this.onPlaylist = false + this.title = data.title + this.author = data.author + this.thumbnail = data.thumbnail + this.url = data.uri + this.duration = data.duration + this.identifier = data.identifier + this.type = data.type + this.self = data + } + } + + generateHTML(playlist, onYoutube) { + + var actions = `` + var timecode = null + + if(this.duration == 9223372036854776000) { + + timecode = " LIVE" + + } else { + timecode = getTimeCode(this.duration) + } + + if(playlist) { + actions = ` + + + ${!onYoutube ? `` : ""} + + ` + } else { + actions = ` + + ` + + } + + + return ` ` + } + + loadScript(fromPlaylist, onYoutube) { + const image = getID(`${this.identifier}_search_image`) + image.style.backgroundImage = `url(${this.thumbnail})` + + const play = getID(`${this.identifier}_search_play`) + const add = getID(`${this.identifier}_search_add`) + const padd = getID(`${this.identifier}_search_padd`) + + add.addEventListener("click", () => { + const action = this.onPlaylist ? "FP_ADD_SONG" : "ADD_SONG"; + post(action, this.onPlaylist ? this.url : this.self); + }); + + play.addEventListener("click", () => { + const action = this.onPlaylist ? "FP_ADD_SONG_NOW" : "ADD_SONG_NOW"; + post(action, this.onPlaylist ? this.url : this.self); + }); + + if(!fromPlaylist) { + padd.addEventListener("click", () => { + saveToPlaylist(this.url) + }) + } else { + if(onYoutube) { + + padd.addEventListener("click", () => { + post("DELETE_SONG_TO_PLAYLIST", {"id": playlistId, "identifier": this.identifier}) + }) + } + + } + + + + + + + } + + + + loadPlaylist() { + const image = getID(`${this.identifier}_search_image`) + image.style.backgroundImage = `url(${this.thumbnail})` + + + } +} + +var playlistId = null + + +const viewEdit = getID("view-edit") + +function loadView(content) { + viewEdit.innerHTML = content +} + +const tileList = new Array() + +function setTileActive(tile) { + playlistId = null + + // add only the 'invert' class to the selected tile by the id + + tileList.forEach((element) => { + if(element) { + element.classList.remove("invert") + } + }) + + if(tile) { + getID(tile).classList.add("invert") + } +} + + +function loading(returnable) { + + if(returnable) { + return `

Chargement en cours ...

` + + } else { + loadView(` +

Chargement en cours ...

+ `) + } } -const buttons = document.querySelectorAll(".sside_line"); +function saveToPlaylist(url) { + get("PLAYLIST").then((res) => { + + var allPlaylistOptions = new Array() + for(var playlist in res) { + var indicator = "[Privée] " - buttons.forEach(button => { - button.addEventListener("click", function () { - buttons.forEach(btn => { - if (btn === button) { - btn.style.color = "white"; - } else { - btn.style.color = ""; - } - }); - }); - }); \ No newline at end of file + if(res[playlist].source == "shared") { + indicator = "[Partagée] " + } + + if(res[playlist].source != "youtube") { + allPlaylistOptions.push(``) + } + + + + } + + if(allPlaylistOptions.length == 0) { + //Make a modal named "Error" with close button and a message + const modalError = new ModalComponent({"title": " Erreur", width: "20%"}) + + modalError.setContent(``) + modalError.show() + + + + + } else { + + const modal = new ModalComponent({"title": " Ajouter à la playlist", width: "20%"}) + + modal.setContent(` + + `) + modal.show() + + const confirm = getID("playlist-add-confirm") + const playlistId = getID("playlist-id") + + confirm.addEventListener("click", () => { + post("ADD_SONG_TO_PLAYLIST", {"id": playlistId.value, "url": url}) + modal.hide() + }) + + } + }) +} \ No newline at end of file diff --git a/src/web/public/javascript/index.js b/src/web/public/javascript/index.js new file mode 100644 index 0000000..6aa6200 --- /dev/null +++ b/src/web/public/javascript/index.js @@ -0,0 +1,43 @@ +const userImg = getID("user-img") +const userName = getID("user-name") +const userId = getID("user-id") +const website_list = document.getElementById("ousers-list") +const website_list_number = document.getElementById("ousers-number") + +AlwaysRequest("UPDATE_SELF", () => { + initUser() +}) + +initUser() + +function initUser() { + const userInfo = get("USER_INFO") + + userInfo.then(user => { + userImg.src = user.picture + userId.innerHTML = user.user.username + userName.innerHTML = user.user.global_name + + }) +} + +AlwaysRequest("ALL_CONNECTED_USER", (data) => { + + + const userToPush = new Array() + + for(var user of data) { + + const userC = new User({ + picture: user.picture, + name: user.global_name, + id: user.username + }) + userToPush.push(userC.generateHTML()) + + } + + website_list.innerHTML = userToPush.join("") + website_list_number.innerHTML = userToPush.length + +}) diff --git a/src/web/public/javascript/indexscript.js b/src/web/public/javascript/indexscript.js deleted file mode 100644 index 1fa1629..0000000 --- a/src/web/public/javascript/indexscript.js +++ /dev/null @@ -1,137 +0,0 @@ - -updateUsersPictures() - -AlwaysRequest("UPDATE_SELF", () => { - updateUsersPictures() -}) - -function updateUsersPictures() { - - const userInfo = get("USER_INFO") - - userInfo.then(user => { - - settingsBtn.style.display = "none" - - if(user.admin == true) { - - settingsBtn.style.display = "flex" - userAdmin = true - } - - userInfoDiv.innerHTML = "

" + user.user.global_name + "

" + user.user.username + "

" + "
" - - - }) -} - - - - -userInfoDiv.addEventListener("click", () => { - - if(userInfoPopup.classList.contains("invisible")) { - - userInfoPopup.classList.remove("invisible") - userInfoPopup.style.left = (xMousePos - 110) + "px" - userInfoPopup.style.top = yMousePos + "px" - - } - -}) - -userInfoPopup.classList.add("invisible") - -userInfoPopup.addEventListener("mouseleave", () => { - - userInfoPopup.classList.add("invisible") -}) - -// Load users connected - -AlwaysRequest("ALL_CONNECTED_USER", (data) => { - if(userLocation == "home") { - - const website_list = document.getElementById("website_list") - const userToPush = new Array() - - userToPush.push("

Utilisateurs connecté(es)

") - - for(var user of data) { - - userToPush.push(`

${user.global_name}

${user.username}

`) - - } - - website_list.innerHTML = userToPush.join("") - - } - -}) - - - -var timeoutId = null - -socket.on("NOTIFICATION", (data) => { - - if(timeoutId) { - - clearTimeout(timeoutId) - } - - const notifDiv = document.getElementById("notif") - const notif_image = document.getElementById("notif_image") - const notif_text = document.getElementById("notif_text") - - notif_image.src = data.image_src - notif_text.innerHTML = data.text - - - - notifDiv.classList.add("notif_div_on") - - timeoutId = setTimeout(() => { - - notifDiv.classList.remove("notif_div_on") - }, 4000) - - notifDiv.addEventListener("click", () => { - - - if(timeoutId) { - - clearTimeout(timeoutId) - } - - - notifDiv.classList.remove("notif_div_on") - - }) -}) - - -// Window Selector - - - -homeBtn.style.color = "white" - -homeBtn.addEventListener("click", () => { - - loadHome() - -}) - -// Restart - - -restartBtn.addEventListener("click", () => { - - get("RESTART") -}) - - -// Start Operation - -loadHome() \ No newline at end of file diff --git a/src/web/public/javascript/login-script.js b/src/web/public/javascript/login.js similarity index 100% rename from src/web/public/javascript/login-script.js rename to src/web/public/javascript/login.js diff --git a/src/web/public/javascript/middle.js b/src/web/public/javascript/middle.js deleted file mode 100644 index def9f07..0000000 --- a/src/web/public/javascript/middle.js +++ /dev/null @@ -1,68 +0,0 @@ -const userInfoDiv = getID("userInfo") -const userInfoPopup = getID("userPopup") -const userInfoglobal = getID("userInfoglobal") - -const musicTitle = getID("music_title") -const musicURL = getID("music_img") - -const durationBar = getID("duration") -const durationTextAct = getID("durationTextAct") -const durationTextTotal = getID("durationTextTotal") - -const backward = getID("backward") -const play = getID("play") -const forward = getID("forward") - -const settingsBtn = getID("settings_btn") - -const loop = getID("loop") -const vol = getID("volbtn") -const shuffle = getID("shuffle") -const list = getID("list_btn") -const takeCurrent = getID("takeCurrent") - -const volBox = getID("volumeBox") -const volTxt = getID("volumeTxt") -const volDiv = getID("volDiv") -const volRange = getID("volumeInput") - -const listBox = getID("listBox") -const listNumber = getID("listNumber") - -const disconnect = getID("disconnect") - -const report_dialog = getID("report_dialog") -const report_close = getID("report_close") -const reportBtn = getID("reportBtn") -const report_level = getID("report_level") -const report_desc = getID("report_desc") -const report_send = getID("report_send") - -const searchBtn = getID("search_btn") -const homeBtn = getID("home_btn") -const mainView = getID("mainView") - -const restartBtn = getID("restartBtn") -const WelcomeContent = mainView.firstElementChild.outerHTML -const playlistContent = getID("playlist-content") - - - -// Get the current location of the user -var userLocation = "home" -var userAdmin = false - -// Player - -var durationAll = 0 -var durationProgress = 0 -var isPlaying = false -let interval; - -// Playlist - -var playlistSelected = null -var playlistValue = null -var deleteJustBefore = null -var currentSong = null -var playlistAvailable = null \ No newline at end of file diff --git a/src/web/public/javascript/oobe.js b/src/web/public/javascript/oobe.js new file mode 100644 index 0000000..8e6b4cd --- /dev/null +++ b/src/web/public/javascript/oobe.js @@ -0,0 +1,594 @@ +const cgu = ` + +

En utilisant ce site, vous consentez à l'utilisation de vos données fournis par Discord (c) afin d'assurer le bon fonctionnement de la plateforme. Vous avez la possibilité de demander la suppression de vos données à tout moment en contactant Raphix (raphixscrap). Tout acte intentionnel de dégradation du bot entraînera un bannissement du site.

+
+

Ce bot est destiné à un usage privé exclusivement et n'est pas conçu pour être utilisé par le grand public.

+
+

Toutes les musiques disponibles sur ce site sont hébergées sur les plateformes suivantes : Youtube, Soundcloud, Vimeo.

+
+

En utilisant Subsonics, vous bénéficiez du droit d'accès au service et de l'écoute du contenu. Cependant, veuillez noter que Raphix n'est pas tenu de fournir la provenance ni l'autorisation d'exploitation des musiques par les ayants droits. Il vous incombe donc d'obtenir les autorisations nécessaires des ayants droits pour écouter le contenu.

+
+

Les paroles fournies sur ce site sont obtenues auprès de Genius (c).

+
+

En utilisant Subsonics, vous acceptez de respecter les conditions d'utilisation de Genius (c) et de ne pas utiliser les paroles à des fins commerciales.

+
+

En utilisant Subsonics, vous acceptez de ne pas utiliser le bot pour diffuser des contenus illégaux, violents, haineux, discriminatoires, ou à caractère sexuel.

+
+

En utilisant Subsonics, vous acceptez de ne pas utiliser le bot pour diffuser des contenus à caractère politique, religieux, ou incitant à la haine.

+
+

En utilisant Subsonics, vous acceptez de ne pas utiliser le bot pour diffuser des contenus à caractère publicitaire ou pornographique.

+` + + +get("OOBE_CHECK").then((res) => { + if(res) { + loadOOBE() + } +}) + +function loadOOBE() { + const modal = new ModalComponent({"title": "
Bienvenue sur Subsonics WEB
" , "width": "50%", "closable": false}) + modal.setContent(` +
+

Bienvenue sur Subsonics Web

+

Subsonics Web est un outil pour gérer le bot Discord Subsonics.

+

Vous pouvez créer des playlists, jouer de la musique, importer des playlists depuis YouTube, et bien plus encore.

+

Avant de commencer à utiliser Subsonics Web, vous devez accepter les conditions d'utilisation.

+
+
+

Conditions d'utilisation

+

En utilisant Subsonics Web, vous acceptez de respecter les conditions d'utilisation suivantes :

+ ${cgu} +
+
+
+ +
+
+ + `) + modal.show() + + document.getElementById("accept-oobe").addEventListener("click", () => { + modal.hide() + oobeStep2() + }) + + +} + +function oobeStep2() { + const modal = new ModalComponent({"title": "
Bienvenue sur Subsonics WEB
" , "width": "70%", "closable": false}) + modal.setContent(` +
+

Apprenons à utiliser Subsonics Web (1/4) - Player

+

Le player est l'élément central de Subsonics Web. C'est ici que vous pourrez contrôler la musique que vous écoutez.

+
+
+
+
+
+

Titre de la vidéo

+

Nom de la chaine

+
+
+ +
+
+ + + + + +
+
+ -:-- + + -:-- +
+ +
+
+
+ + + +
+
+ + + + 100% + + +
+ +
+
+
+ +
+ +

Appuyez sur ce bouton mettre en pause ou reprendre la lecture de la musique.

+
+
+ +

Appuyez sur ce bouton pour revenir au début de la musique actuelle.

+
+
+ +

Appuyez sur ce bouton pour passer à la musique suivante.

+
+
+ +

Appuyez sur ce bouton pour activer ou désactiver la répétition de la musique actuelle.

+
+
+ +

Appuyez sur ce bouton pour activer ou désactiver la lecture aléatoire des musiques.

+
+
+ +

Appuyez sur ce bouton pour afficher les paroles - Ctrl + Click Recherche n'importe quelles paroles sur Genius.

+
+
+ +

Appuyez sur ce bouton pour déconnecter le bot de votre salon vocal.

+
+
+ +

Appuyez sur ce bouton pour déplacer le bot dans votre salon vocal.

+
+
+ +

Utilisez ce curseur pour régler le volume de la musique.

+
+
+ -:-- +

Utilisez ce curseur pour régler la position de la musique.

+
+ + +
+ +
+ +
+ +
+ + `) + + modal.show() + + document.getElementById("continue-oobe").addEventListener("click", () => { + modal.hide() + oobeStep3() + }) +} + +function oobeStep3() { + const modal = new ModalComponent({"title": "
Bienvenue sur Subsonics WEB
" , "width": "70%", "closable": false}) + modal.setContent(` +
+

Apprenons à utiliser Subsonics Web (2/4) - Liste de lecture

+

La liste de lecture est l'endroit où vous pouvez gérer les musiques que vous souhaitez écouter.

+
+
+
+

Liste de lecture

+ +
+
+
+

À suivre

+

Historique

+
+ +
+ + + +
+
+
+

-:--

+
+

Titre de la vidéo

+

Nom de la chaine

+
+
+ + +
+ +
+
+

-:--

+
+

Titre de la vidéo

+

Nom de la chaine

+
+
+ + +
+ +
+
+
+ +
+
+

À suivre

+

Historique

+
+

Utilisez ces boutons pour changer de liste de lecture.

+ +
+
+
+
+

-:--

+
+

Vous pouvez déplacer les titres dans l'ordre que vous le souhaitez en glissant et en déposant

+
+
+
+ +

Appuyez sur ce bouton pour vider la liste de lecture.

+
+
+ +

Appuyez sur ce bouton pour afficher les options de la musique. - Ctrl + Click Permet de supprimer la musique de la liste de lecture.

+
+ + +
+ +
+ +
+ +
+ + `) + + modal.show() + + document.getElementById("continue-oobe").addEventListener("click", () => { + modal.hide() + oobeStep4() + + }) + + +} + +function oobeStep4() { + const modal = new ModalComponent({"title": "
Bienvenue sur Subsonics WEB
" , "width": "70%", "closable": false}) + modal.setContent(` +
+

Apprenons à utiliser Subsonics Web (3/4) - Playlist

+

Les playlists sont un moyen pratique de regrouper vos musiques préférées. Elles peuvent provenir de Youtube, peuvent être privé comme partagé.

+
+
+
+

Playlists

+ + +
+ + + +
+
+ +
+

Playlist Privé

+
+ +
+
+ +
+

Playlist importé depuis Youtube

+
+ + +
+
+ +
+

Playlist Partagé

+
+ +
+
+ +
+ +
+ + `) + + modal.show() + + document.getElementById("continue-oobe").addEventListener("click", () => { + modal.hide() + oobeStep4b() + + }) + +} + +function oobeStep4b() { + const modal = new ModalComponent({"title": "
Bienvenue sur Subsonics WEB
" , "width": "70%", "closable": false}) + modal.setContent(` +
+

Apprenons à utiliser Subsonics Web (3/4) - Playlist

+

Les playlists sont un moyen pratique de regrouper vos musiques préférées. Elles peuvent provenir de Youtube, peuvent être privé comme partagé.

+
+
+
+
+
+ +
+
+ +

Titre de la playlist

+
+

-- titres

+
+
+
+
+ + + + +
+
+ + + +
+ +
+
+
+ +
+
+ +

Titre d'une playlist Youtube

+
+

-- titres - --- vues

+

Description de la playlist

+
+
+ +

Nom de l'auteur de la playlist

+
+
+ +
+
+ + + + +
+
+ +
+ +
+ + +
+
+ +

Nom de l'auteur de la playlist

+
+

Cliquez dessus pour accéder à la chaine Youtube de l'auteur de la playlist.

+
+
+
+
+ +
+

Ctrl + Click pour copier le lien de la playlist

+
+
+ +
+ +

Appuyez sur ce bouton pour ajouter la playlist à la liste de lecture.

+
+
+ +

Appuyez sur ce bouton pour lire directement la playlist.

+
+
+ +

Appuyez sur ce bouton pour partager la playlist.

+
+
+ +

Appuyez sur ce bouton pour supprimer la playlist.

+
+
+ +

Appuyez sur ce bouton pour renommer la playlist.

+
+
+ + +
+ +
+ + `) + + modal.show() + + document.getElementById("continue-oobe").addEventListener("click", () => { + modal.hide() + oobeStep5() + + }) + +} + +function oobeStep5() { + const modal = new ModalComponent({"title": "
Bienvenue sur Subsonics WEB
" , "width": "70%", "closable": false}) + modal.setContent(` +
+

Apprenons à utiliser Subsonics Web (4/4) - Recherche

+

La recherche est un outil puissant pour trouver des musiques depuis Vimeo, Soundcloud et Youtube. Vous pouvez aussi rechercher des playlists sur Youtube.

+
+ + + +
+ +
+ + +
+
+ + +
+

Utilisez cette barre de recherche pour trouver des musiques sur Youtube, Soundcloud et Vimeo.

+
+
+ +

Appuyez sur ce bouton pour ajouter la musique à la liste de lecture.

+
+
+ +

Appuyez sur ce bouton pour lire directement la musique.

+
+
+ +

Appuyez sur ce bouton pour sauvegarder la musique dans une playlist.

+
+ + +
+ +
+ +
+ + `) + + modal.show() + + document.getElementById("continue-oobe").addEventListener("click", () => { + modal.hide() + oobeStep6() + + + }) +} + +function oobeStep6() { + const modal = new ModalComponent({"title": "
Bienvenue sur Subsonics WEB
" , "width": "70%", "closable": false}) + modal.setContent(` +
+

Vous êtes prêt à utiliser Subsonics Web

+

Vous avez maintenant appris les bases de Subsonics Web. Vous pouvez maintenant commencer à utiliser le site.

+

Mais avant de commencer, n'oubliez pas ces quelques conseils :

+ +
    +
  • Avant de commencer à lancez de la musique, assurez-vous que personne ne l'écoute déjà.
  • +
  • Si vous avez des questions, n'hésitez pas à demander à Raphix (raphixscrap) sur Discord.
  • +
  • Si vous rencontrez un bug ou que vous avez des suggestions, n'hésitez pas à le signaler en utilisant /report ou en utilisant le formulaire disponible dans Paramèters
  • +
  • Si vous avez des questions sur les commandes, n'hésitez pas à consulter l'aide disponible en faisant /help
  • +
  • Vérifiez que vous entrez des commandes dans le bon salon textuel (#bots).
  • +
+

Amusez-vous bien !

+ +
+ +
+ + `) + + modal.show() + + document.getElementById("continue-oobe").addEventListener("click", () => { + modal.hide() + get("OOBE_VALID") + + }) + +} \ No newline at end of file diff --git a/src/web/public/javascript/player.js b/src/web/public/javascript/player.js index ba66c8f..9a53878 100644 --- a/src/web/public/javascript/player.js +++ b/src/web/public/javascript/player.js @@ -1,351 +1,224 @@ -AlwaysRequest("MUSIC_STATE", async (data) => { - await disableDrag() - await enableDrag() +const play = getID("play") +const forward = getID("forward") +const backward = getID("backward") +const loop = getID("loop") +const shuffle = getID("shuffle") +const durationBar = getID("duration") + + +const video_img = getID("video_img") +const video_title = getID("video_title") +const video_artist = getID("video_artist") + +const time_act = getID("time_act") +const time_total = getID("time_total") + +const volume = getID("volume") +const volIcon = getID("volIcon") +const volTxt = getID("volTxt") + +const lyrics = getID("lyrics") + +const disconnect = getID("disconnect") +const moveout = getID("moveout") + +var durationAct = 0 +var durationTotal = 0 +// 4 States : PLAYING, PAUSED, CONNECTED, DISCONNECTED, LIVE + +var interval = null + +var currentTitle = "" + +var playerState = "DISCONNECTED" + +AlwaysRequest("MUSIC_STATE", async (data) => { + durationAct = 0 + durationTotal = 0 + playerState = "DISCONNECTED" + currentTitle = "" stopInterval() + console.log(data) - durationAll = 0 - durationProgress = 0 - isPlaying = false - if(data.isOnline) { - - vol.classList.remove("disabled") + + playerState = "CONNECTED" + + forward.classList.remove("disabled") + backward.classList.remove("disabled") + loop.classList.remove("disabled") shuffle.classList.remove("disabled") - list.classList.remove("disabled") - play.classList.remove("pri_disable") disconnect.classList.remove("invisible") - volRange.classList.add("disabled") - - volRange.disabled = false - } else { - - vol.classList.add("disabled") - shuffle.classList.add("disabled") - list.classList.add("disabled") - play.classList.add("pri_disable") - disconnect.classList.add("invisible") - volRange.classList.add("disabled") - volRange.disabled = true - volRange.value = 0 - volTxt.innerHTML = "0%" - volBox.classList.add("invisible") + moveout.classList.remove("invisible") + volume.classList.remove("invisible") + volTxt.classList.remove("invisible") + volIcon.classList.remove("invisible") + lyrics.classList.remove("invisible") + + } else { + play.classList.add("disabled") + forward.classList.add("disabled") + backward.classList.add("disabled") + loop.classList.add("disabled") + shuffle.classList.add("disabled") + moveout.classList.add("invisible") + disconnect.classList.add("invisible") + volume.classList.add("invisible") + volIcon.classList.add("invisible") + volTxt.classList.add("invisible") + time_act.innerHTML = " " + time_total.innerHTML = " " + durationBar.classList.add("invisible") + lyrics.classList.add("invisible") + } + if(data.shuffle == true) { + shuffle.classList.add("point") + + } else { + + shuffle.classList.remove("point") + } + + if(data.loop == true) { + loop.classList.add("point") + + } else { + + loop.classList.remove("point") + } + + + if(data.current) { + var thumbnail = data.current.thumbnail + + if(thumbnail) { + video_img.innerHTML = '' + } + + currentTitle = data.current.title + video_title.innerHTML = "

" + data.current.title + "

" + video_artist.innerHTML = "

" + data.current.author + "

" + + // Get the width of the title and check if it's above 400px (the max width of the title) + var titleWidth = video_title.querySelector("p").offsetWidth + if(titleWidth > 400) { + video_title.innerHTML = "

" + data.current.title + " -

" + "

" + data.current.title + " -

" + video_title.classList.add("scroll") + } else { + video_title.classList.remove("scroll") + } + + video_img.classList.remove("invisible") + video_title.classList.remove("invisible") + video_artist.classList.remove("invisible") + + + + play.classList.remove("disabled") + setTime() + + + } else { + + video_img.classList.add("invisible") + video_title.classList.add("invisible") + video_artist.classList.add("invisible") + + + play.classList.add("disabled") + currentTitle = "" + } + + if(data.queue) { + loadQueue(data.queue, "next") + actualiseQueue() + } else { + loadQueue(null, "next") + actualiseQueue() + } + + if(data.previous) { + loadQueue(data.previous, "previous") + actualiseQueue() + } else { + loadQueue(null, "previous") + actualiseQueue() + } + + if(data.volume) { - volRange.step = 1 - volRange.max = 200 - volRange.min = 1 - volRange.value = Math.trunc(data.volume / 10) + volume.step = 1 + volume.max = 200 + volume.min = 1 + volume.value = Math.trunc(data.volume / 10) volTxt.innerHTML = Math.trunc(data.volume / 10) + "%" var volNum = Math.trunc(data.volume / 10) - - - } else { - - volRange.classList.add("disabled") - volRange.disabled = true - volRange.value = 0 - volTxt.innerHTML = "0%" - } - - if(data.shuffle == true) { - shuffle.innerHTML = '' - - } else { - - shuffle.innerHTML = '' - } - - if(data.loop == true) { - loop.innerHTML = '' - - } else { - - loop.innerHTML = '' - } - - if(data.current == null) { - - musicURL.innerHTML = '' - musicTitle.innerHTML = "

Aucun titre joué

" - loop.classList.add("invisible") - takeCurrent.classList.add("invisible") - } else { - - var thumbnail = data.current.thumbnail - - if(!thumbnail) { - - thumbnail = "/images/black-image.svg" + if(volNum == 1) { + volIcon.innerHTML = '' + } else if(volNum < 99) { + volIcon.innerHTML = '' + } else { + volIcon.innerHTML = '' } - musicURL.innerHTML = '' - musicTitle.innerHTML = "

" + data.current.title + "

" - currentSong = data.current - takeCurrent.classList.remove("invisible") - loop.classList.remove("invisible") - } - - if(data.durationAll) { - durationBar.disabled = false - durationBar.classList.remove("grised") - setTime() - - durationAll = data.durationAll - durationProgress = data.durationNow - durationBar.value = durationProgress - setTime() - - } else { - - - isPlaying = false - durationAll = 0 - durationProgress = 0 - durationBar.disabled = true - durationBar.classList.add("grised") - durationBar.value = 0 - durationTextAct.innerHTML = "-:--" - durationTextTotal.innerHTML = "-:--" - - } + + } + + if(data.playing == 1) { - play.innerHTML = '' - isPlaying = true + play.innerHTML = '' + playerState = "PLAYING" startInterval() } else { - play.innerHTML = '' - isPlaying = false + play.innerHTML = '' + playerState = "PAUSED" } - - - if(data.current && data.playing == 0) { - setTime() - - } - - if(data.durationAll == 9223372036854776000) { - - isPlaying = false - durationAll = 0 - durationProgress = 0 - durationBar.disabled = true - durationBar.classList.add("grised") - durationBar.style.display = "none" - durationBar.value = 0 - durationTextAct.innerHTML = "" - durationTextTotal.innerHTML = " LIVE" - - } else { - - durationBar.style.display = "unset" - } - - - - if(data.queue != null) { - - var contentToPush = new Array() - var queueNum = 0 - - for(var title of data.queue) { - queueNum += 1 - console.log(queueNum) - console.log(data.queue.indexOf(title) + " - " + title.title) - var thumbnail = title.thumbnail - if(!thumbnail) { - - thumbnail = "/images/black-image.svg" - - } - contentToPush.push('

' + title.title + '

') - } - - if(contentToPush.join("") == "") { + if(data.durationAll) { + + if(data.durationAll == 9223372036854776000) { + durationBar.classList.add("invisible") + time_act.innerHTML = "" + time_total.innerHTML = " LIVE" + playerState = "LIVE" + } else { - listNumber.classList.add("invisible") - listBox.innerHTML = '

Aucun morceau dans la liste de lecture !

' - - } else { - listNumber.innerHTML = '' + queueNum + '' - listNumber.classList.remove("invisible") - listBox.innerHTML = contentToPush.join("") + durationTotal = data.durationAll + durationAct = data.durationNow + setTime() + durationBar.disabled = false + durationBar.max = durationTotal + durationBar.value = durationAct + durationBar.classList.remove("invisible") + setTime() } - - //CODE INTEGER QUEUE LIST MOVE - - const container = document.getElementById('listBox'); - const draggableItems = document.querySelectorAll('.draggable'); - - let draggingElement = null; - - draggableItems.forEach(item => { - item.addEventListener('dragstart', (e) => { - e.dataTransfer.setData('text/plain', item.innerHTML); - draggingElement = item; - }); - - item.addEventListener('dragend', () => { - draggingElement = null; - setTimeout(() => { - item.style.display = 'flex'; // Restaure l'affichage de l'élément - }, 0); - updateOrder(); - }); - }); - - container.addEventListener('dragover', (e) => { - e.preventDefault(); - const afterElement = getDragAfterElement(container, e.clientY); - if (draggingElement !== null) { - if (afterElement == null) { - container.appendChild(draggingElement); - } else { - const rect = afterElement.getBoundingClientRect(); - if (e.clientY < rect.top + rect.height / 2) { - container.insertBefore(draggingElement, afterElement); - } else { - container.insertBefore(draggingElement, afterElement.nextElementSibling); - } - } - } - }); - - function getDragAfterElement(container, y) { - const draggableElements = [...container.querySelectorAll('.draggable:not(.dragging)')]; - return draggableElements.reduce((closest, child) => { - const box = child.getBoundingClientRect(); - const offset = y - box.top - box.height / 2; - if (offset < 0 && offset > closest.offset) { - return { offset: offset, element: child }; - } else { - return closest; - } - }, { offset: Number.NEGATIVE_INFINITY, element: null }).element; - } - - function updateOrder() { - const draggableItems = document.querySelectorAll('.draggable'); - const order = []; - draggableItems.forEach(item => { - order.push(item.id.replace("_queue_song", "")); - }); - console.log('Ordre des divs:', order); - post("MOVE_QUEUE_BY_ENTIRE", order) - } - - - - // END OF CODE INTEGER - - for(var title of data.queue) { - - console.log(data.queue.indexOf(title) + " - " + title.title) - - const titleBtn = document.getElementById(data.queue.indexOf(title)+ "_ldelete") - const moveBtn = document.getElementById(data.queue.indexOf(title)+ "_lmove") - - titleBtn.addEventListener("click", () => { - - post("DELETE_QUEUE", titleBtn.id.replace("_ldelete", ""), data.queue[moveBtn.id.replace("_lmove", "")].title ) - }) - - moveBtn.addEventListener("click", () => { - - post("MOVE_QUEUE", moveBtn.id.replace("_lmove", "")) - - }) - } - - - } else { - - listBox.innerHTML = '

Lancez un titre et ajoutez vos morceaux ici !

' - listNumber.classList.add("invisible") - } - -}) - - - -play.addEventListener('click', () => { - - get("PAUSE") -}) - -document.body.onkeyup = function(e) { - - if ((e.key == " " || - e.code == "Space" || - e.keyCode == 32) && - e.srcElement.localName != "input" && e.srcElement.localName != "textarea" - ) { - play.click() - } - } - -backward.addEventListener('click', () => { - - get("BACKWARD") -}) - - -forward.addEventListener("click", () => { - - get("FORWARD") -}) - -volBox.classList.add("invisible") -listBox.classList.add("invisible") - -list.addEventListener("click" , () => { - - volBox.classList.add("invisible") - - if(listBox.classList.contains('invisible')) { - listBox.classList.remove("invisible") - - } else { - - listBox.classList.add("invisible") - } -}) - -vol.addEventListener("click", () => { - - listBox.classList.add("invisible") - - if(volBox.classList.contains('invisible')) { - volBox.classList.remove("invisible") - - } else { - - volBox.classList.add("invisible") - } - -}) - -volRange.addEventListener("click", () => { + + } else { - post("VOLUME", volRange.value) + durationBar.classList.add("invisible") + durationBar.disabled = true + time_act.innerHTML = " " + time_total.innerHTML = " " + + } + + + + }) -volRange.addEventListener("input", () => { - - - volTxt.innerHTML = volRange.value + "%" -}) loop.addEventListener("click", () => { @@ -364,8 +237,190 @@ disconnect.addEventListener("click", () => { }) -durationBar.addEventListener("change", () => { - +durationBar.addEventListener("click", (event) => { + stopInterval() post("SEEK", durationBar.value) + startInterval() +}) + +durationBar.addEventListener("input", (event) => { + stopInterval() + time_act.innerHTML = getTimeCode(durationBar.value) +}) -}) \ No newline at end of file +volume.addEventListener("click", () => { + + + post("VOLUME", volume.value) +}) + +volume.addEventListener("dblclick", () => { + + post("VOLUME", 100) +}) + +play.addEventListener('click', () => { + + get("PAUSE") +}) + +forward.addEventListener('click', () => { + + get("FORWARD") +}) + +backward.addEventListener('click', () => { + + get("BACKWARD") +}) + + +moveout.addEventListener('click', () => { + get("MOVEOUT") +}) + +lyrics.addEventListener('click', (e) => { + + currentTitle = currentTitle.replace(/\(.*?\)/g, "").replace(/\[.*?\]/g, "").trim() + + if(e.ctrlKey) { + const modal = new ModalComponent({"title": "Rechercher des paroles" , "width": "25%", "closable": true}) + + modal.setContent(` +
+ + +
+ `) + + modal.show() + + const lyricsSearch = getID("lyrics_search") + const lyricsSearchBtn = getID("lyrics_search_btn") + + lyricsSearchBtn.addEventListener('click', () => { + showLyrics(lyricsSearch.value) + modal.hide() + }) + + } else { + + if(currentTitle != "") { + showLyrics(currentTitle) + + } else { + const modal = new ModalComponent({"title": "Paroles" , "width": "20%", "closable": true}) + modal.setContent(` + +

Lancez une musique pour rechercher les paroles ou faites Ctrl + Click !

+ `) + + modal.show() + } + } + + +}) + +function showLyrics(title) { + post("LYRICS", title).then((res) => { + if(!res) { + const modal = new ModalComponent({"title": "Paroles" , "width": "50%", "closable": true}) + modal.setContent(` +

Aucune paroles trouvées pour cette musique !

+ `) + + modal.show() + } else { + + + const lyricsArray = new Array() + + for(var line of res.split("\n")) { + if(line == "") { + lyricsArray.push("
") + } + + // Bold the line if it's between [] + + if(line.startsWith("[") && line.endsWith("]")) { + lyricsArray.push("

" + line + "

") + } else { + lyricsArray.push("

" + line + "

") + } + + + } + + + lyricsArray.push("

Distribué par Genius ©️") + + setTileActive(null) + + loadView(` +

Paroles de "${title}"

+
+
+ ${lyricsArray.join("")} +
+
+ `) + + + + } + }) + +} + + +volIcon.addEventListener('click', () => { + + if(volume.value > 1) { + post("VOLUME", 1) + } else { + post("VOLUME", 100) + } +}) + +document.body.onkeyup = function(e) { + + if ((e.key == " " || + e.code == "Space" || + e.keyCode == 32) && + e.srcElement.localName != "input" && e.srcElement.localName != "textarea" + ) { + play.click() + } + } + + +// Function with setTime + +function setTime() { + +durationBar.max = durationTotal +durationAct += 1000 +durationBar.value = durationAct + + time_act.innerHTML = getTimeCode(durationAct) + time_total.innerHTML = getTimeCode(durationTotal) + +} + +function startInterval() { + interval = setInterval(() => { + + + if(playerState == "PLAYING") { + setTime() + + } + + }, 1000) + + } + + function stopInterval() { + clearInterval(interval); + } \ No newline at end of file diff --git a/src/web/public/javascript/playlist.js b/src/web/public/javascript/playlist.js index 2d87301..5a93671 100644 --- a/src/web/public/javascript/playlist.js +++ b/src/web/public/javascript/playlist.js @@ -1,312 +1,450 @@ -function delPlayList(key) { - - post("DELETE_PLAYLIST", key) - mainView.innerHTML = WelcomeContent - playlistSelected = null - playlistValue = null - -} +const playlistList = getID("playlist-list") +const playlistAdd = getID("playlist-add") +var loadingPlaylist = false -function playPlayList(key) { +playlistAdd.addEventListener("click", () => { + const win = new ModalComponent({ + "title": " Ajouter une playlist", + "width": "20%", + }) - post("PLAY_PLAYLIST", key) - + win.setContent(` + + `) -} + win.show() -function sendPlayList(key) { + const confirm = getID("playlist-add-confirm") + const name = getID("playlist-name") + const source = getID("playlist-source") + const url = getID("playlist-url") - const playlist_popup = document.getElementById("playlist_popup") - - if(playlist_popup) { - - get("USER_LIST").then(resp => { - - const userToPush = new Array() - - for(var user of resp) { - - userToPush.push(``) + url.style.display = "none" + confirm.addEventListener("click", () => { + if(source.value == "youtube" && url.value.length == 0) { + getID("playlist-add-info").innerHTML = " L'URL de la playlist ne peut pas être vide" + return + } + if(name.value.length > 0) { + var data = { + "name": name.value, + "source": source.value, + "url": url.value } - - playlist_popup.innerHTML = userToPush.join("") - playlist_popup.style.width = '170px' - playlist_popup.style.top = (yMousePos - 30) + "px" - playlist_popup.style.left = (xMousePos - 165) + "px" - playlist_popup.style.overflowY = "auto"; - playlist_popup.style.height = "250px" - playlist_popup.classList.remove("invisible") - - - playlist_popup.addEventListener("mouseleave", () => { - - playlist_popup.classList.add("invisible") - - }) - - for(var user of resp) { - - const userElement = document.getElementById(resp.indexOf(user)) - - userElement.addEventListener("click", () => { - - playlist_popup.classList.add("invisible") - post("SEND_PLAYLIST", {key: key, dest: resp[userElement.id].id}) - }) - } - - //post("SEND_PLAYLIST", key, user.id) - - }) - } - - - -} - - -function loadPlaylist(key, value) { - - userLocation = "playlist" - - var playlistToPush = new Array() - var playlist_songs = new Array() - - playlistSelected = key - playlistValue = value - - for(var title of value) { - - var PFormatduration = getTimeCode(title.duration) - - var thumbnail = title.thumbnail - - if(!thumbnail) { - - thumbnail = "/images/black-image.svg" - - } - - if(title.duration == 9223372036854776000) { - - PFormatduration = " LIVE" - } - - playlist_songs.push('

' + title.title + '

' + title.author + '

' + PFormatduration + '

') - - } - - - - playlistToPush.push(``) - playlistToPush.push('

' + key + '


' + playlist_songs.join("")) - - if(playlistToPush.join("") == "") { - - mainView.innerHTML = '

Aucun morceau trouvé !

' - - } else { - - mainView.innerHTML = playlistToPush.join("") - - - } - - for(var title of value) { - - const add_to = document.getElementById(value.indexOf(title) + "_padd") - const playNow = document.getElementById(value.indexOf(title) + "_pplay") - const deleteBtn = document.getElementById(value.indexOf(title) + "_pdelete") - - add_to.addEventListener("click", () => { - - post("ADD_SONG", value[add_to.id.replace("_padd", "")]) - }) - - playNow.addEventListener("click", () => { - - post("ADD_SONG_NOW", value[add_to.id.replace("_padd", "")]) - - }) - - deleteBtn.addEventListener("click", () => { - - deleteJustBefore = true - post("DELETE_SONG_TO_PLAYLIST", {data: key, song: value[add_to.id.replace("_padd", "")]}) - - }) - - - } - -} - -function fp_play_playlist(key) { - - post("FP_PLAY_PLAYLIST", key) -} - -socket.on("DO_UPDATE_PLAYLIST", () => { - - get("PLAYLIST") -}) - -get("PLAYLIST") - - -socket.on("ANSWER/GET/PLAYLIST", (data) => { - var contentToPush = new Array() - var selectionData = new Array() - - contentToPush.push(`

Mes Playlists

`) - contentToPush.push('
Créer une playlist
') - - - for (const [key, value] of Object.entries(data)) { - - contentToPush.push('

' + key + '

') - selectionData.push('') - } - - - - - if(contentToPush.join("") == "") { - - playlistContent.innerHTML = '

Aucun morceau trouvé !

' - - } else { - - playlistContent.innerHTML = contentToPush.join("") - playlistAvailable = selectionData - } - - if(playlistSelected && deleteJustBefore || playlistSelected && userLocation == "playlist") { - deleteJustBefore = null - loadPlaylist(playlistSelected, data[playlistSelected]) - } - - for (const [key, value] of Object.entries(data)) { - - const playlist_selector = document.getElementById(key + '_playlist') - - playlist_selector.addEventListener("click", () => { - - loadPlaylist(key, value) - userLocation = "playlist" - - }) - } - - const buttons = document.querySelectorAll(".checker"); - - buttons.forEach(button => { - button.addEventListener("click", function () { - buttons.forEach(btn => { - if (btn === button) { - btn.style.color = "white"; + post("CREATE_PLAYLIST", data).then((data) => { + if(data.status == "error") { + getID("playlist-add-info").innerHTML = "" + data.message } else { - btn.style.color = ""; + win.hide() + loadPlaylistList() } - }); - }); - }); - - - const addPlaylist = document.getElementById("createPlaylist") - const addPlaylist_dialog = document.getElementById("createPlaylist_dialog") - const addPlaylist_close = document.getElementById("createPlaylist_close") - const apText = document.getElementById("apText") - const apInfo = document.getElementById("apInfo") - const apCreate = document.getElementById("apCreate") - - - addPlaylist_close.addEventListener("click", () => { - apInfo.innerHTML = "" - addPlaylist_dialog.close() - }) - - addPlaylist.addEventListener("click", () => { - - apText.innerHTML = "" - addPlaylist_dialog.showModal() - }) - - apCreate.addEventListener("click", () => { - apInfo.innerHTML = "" - var wrongName = true - - const refusedChar = ['\\','/' ,':' ,'*','?' ,'"','<','>','|'] - - for(var char of refusedChar) { - - if(apText.value.includes(char)) { - wrongName = false - - } - } - - if(apText.value != "" && apText.value != " " && wrongName) { - - addPlaylist_dialog.close() - post("CREATE_PLAYLIST", apText.value) + }) } else { - - apInfo.innerHTML = "Le nom n'est pas valide !" + getID("playlist-add-info").innerHTML = " Le nom de la playlist ne peut pas être vide" } - - }) - - - console.log(data) -}) - - - -// Current Playlist and Song - -const cPlaylistManager = document.getElementById("current_playlistManager") -const cplaylistManager_close = document.getElementById("current_playlistManager_close") -const cplaylistSelection = document.getElementById("current_playlistSelection") -const cplaylist_add_music = document.getElementById("current_playlist_add_music") -const cplaylist_add_img = document.getElementById("current_playlist_add_img") -const cplaylistAddSong = document.getElementById("current_playlistAddSong") - -takeCurrent.addEventListener("click", () => { - - if(currentSong != null) { - - var thumbnail = currentSong.thumbnail - - if(!thumbnail) { - - thumbnail = "/images/black-image.svg" + source.addEventListener("change", () => { + if(source.value == "youtube") { + url.style.display = "block" + } else { + url.style.display = "none" } - - cPlaylistManager.showModal() - cplaylist_add_music.innerHTML = currentSong.title - cplaylist_add_img.src = thumbnail - cplaylistSelection.innerHTML = playlistAvailable - - } - + }) }) -cplaylistManager_close.addEventListener("click", () => { +loadPlaylistList() - cPlaylistManager.close() -}) +AlwaysRequest("PLAYLIST_REFRESH", () => { -cplaylistAddSong.addEventListener("click", () => { - - - cPlaylistManager.close() - post("ADD_SONG_TO_PLAYLIST", {data: cplaylistSelection.value , song: currentSong} ) - + loadPlaylistList() -}) \ No newline at end of file +}) + +function loadPlaylistList() { + get("PLAYLIST").then((data) => { + + var playlists = new Array() + playlistList.innerHTML = "" + + for(var playlist in data) { + + const playlistTile = new PlaylistComponent(playlist, data[playlist]) + playlists.push(playlistTile) + playlistList.innerHTML += playlistTile.generateHTML() + + if(playlistId == playlist) { + loadPlaylist(playlistId, data[playlist]) + + } + } + + for(var playlist of playlists) { + playlist.loadScript() + } + + + + + }) +} + +class PlaylistComponent { + constructor(id, data) { + this.title = data.title + this.id = id + this.source = data.source + this.content = data.content + this.self = data + } + + generateHTML() { + + var logo = "fa fa-music" + if(this.source == "shared") { + logo = "fas fa-share-alt" + } else if(this.source == "youtube") { + logo = "fab fa-youtube" + } + + return ` +
+
+ +
+

${this.title}

+
` + } + + loadScript() { + const playlist = getID(this.id) + const tile = getID(`${this.id}_tile`) + + tileList.push(tile) + + playlist.addEventListener("click", () => { + + loadPlaylist(this.id, this.self) + }) + + } + +} + + +function loadPlaylist(id, properties) { + if(loadingPlaylist) { + return + } + if(!playlistId || playlistId != id) { + loading() + } + setTileActive(id + "_tile") + playlistId = id + + + if(properties.source == "youtube") { + loadingPlaylist = true + post("SEARCH", properties.content).then((res) => { + if(id == playlistId) { + loadingPlaylist = false + loadYoutubePlaylist(res, id, properties) + } + + }) + } else { + + loadingPlaylist = false + loadNormalPlaylist(id, properties) + + } +} + +function loadNormalPlaylist(id, properties) { + loadView(` + +
+
+
+ ${properties.source == "shared" ? "" : ""} +
+
+ +

${properties.title}

+
+

${properties.content.length} titres

+
+
+
+
+ + + + +
+
+
+
+
+
+ + + `) + + + loadActions(null, id, properties) + + const playlistList = getID("playlist-video-list") + + var songList = new Array() + + playlistList.style.display = "grid" + + for(var video of properties.content) { + console.log(video) + const videoTile = new VideoComponent(video, false) + songList.push(videoTile) + playlistList.innerHTML += videoTile.generateHTML(true, false) + } + + + + // IF THE PLAYLIST IS EMPTY + + if(songList.length == 0) { + playlistList.style.display = "flex" + playlistList.innerHTML = "

Aucun titre dans cette playlist

" + } + + for(var song of songList) { + song.loadScript(true, true) + } + +} + + +function loadYoutubePlaylist(res, id, properties) { + var author = "" + console.log(res.results.author) + + if(res.results.author) { + author = ` +
+ +

${res.results.author.name}

+
+ ` + } + loadView(` + +
+
+ +
+ +

${res.results.title}

+
+

${res.results.videos.length} titres - ${res.results.view_count} vues

+

${res.results.description}

+
+ ${author} +
+
+
+ + + + +
+
+
+
+
+
+ + + `) + + + + loadActions(res, id, properties) + + const playlistList = getID("playlist-video-list") + const searchImageLink = getID("search-image-link") + const playlistTitle = getID("playlist-title") + + searchImageLink.addEventListener("click", function(e) { + if(e.ctrlKey) { + // Put in the clipboard properties.content + navigator.clipboard.writeText(properties.content) + + // Set the title green for 1 second + + playlistTitle.style.color = "#32FF32" + setTimeout(() => { + playlistTitle.style.color = "white" + }, 1000) + + + + } else { + window.open(properties.content, '_blank'); + } + + }) + + + var songList = new Array() + + console.log(res.results.videos) + + for(var video of res.results.videos) { + const videoTile = new VideoComponent(video, true) + songList.push(videoTile) + playlistList.innerHTML += videoTile.generateHTML(true, true) + } + + for(var song of songList) { + song.loadScript(true) + } + + +} + +function loadActions(res, id, properties) { + const ppAdd = getID("pp-add") + const ppPlay = getID("pp-play") + const ppSend = getID("pp-send") + const ppDelete = getID("pp-delete") + const ppRename = getID("pp-rename") + + ppRename.addEventListener("click", () => { + + const win = new ModalComponent({ + "title": " Renommer la playlist", + "width": "20%", + }) + + win.setContent(` + + `) + + win.show() + + const confirm = getID("playlist-rename-confirm") + const name = getID("playlist-rename-name") + + confirm.addEventListener("click", () => { + if(name.value.length > 0) { + post("RENAME_PLAYLIST", {id: id, name: name.value}) + win.hide() + } + }) + }) + + + ppAdd.addEventListener("click", () => { + if(res) { + post("FP_PLAY_PLAYLIST", res.results.url) + } else { + post("PLAY_PLAYLIST", id) + } + + }) + + ppPlay.addEventListener("click", () => { + if(res) { + post("FP_PLAY_PLAYLIST_NOW", res.results.url) + } else { + post("PLAY_PLAYLIST_NOW", id) + } + + }) + + ppDelete.addEventListener("click", () => { + // Make a confirmation modal + + const win = new ModalComponent({ + "title": " Supprimer la playlist", + "width": "15%", + }) + + + win.setContent(` + + `) + + win.show() + + const confirm = getID("playlist-delete-confirm") + + confirm.addEventListener("click", () => { + post("DELETE_PLAYLIST", id) + win.hide() + loadSearch() + }) + + + }) + + ppSend.addEventListener("click", () => { + get("USER_LIST").then((data) => { + var userList = new Array() + for(var userPS of data) { + console.log(userPS) + if(userPS.username != userId.innerHTML) { + userList.push(userPS) + } + + } + const win = new ModalComponent({ + "title": " Envoyer la playlist", + "width": "20%", + }) + + win.setContent(` + + `) + + win.show() + + const confirm = getID("playlist-send-confirm") + const userS = getID("playlist-user") + + confirm.addEventListener("click", () => { + post("SEND_PLAYLIST", {key: id, dest: userS.value}) + win.hide() + }) + + }) + + }) + +} \ No newline at end of file diff --git a/src/web/public/javascript/queue.js b/src/web/public/javascript/queue.js new file mode 100644 index 0000000..7ce595c --- /dev/null +++ b/src/web/public/javascript/queue.js @@ -0,0 +1,261 @@ +const listDiv = document.getElementById("list-div"); +const listNext = document.getElementById("list-next"); +const listPrevious = document.getElementById("list-previous"); +const listClear = document.getElementById("list-clear"); + +var selectedQueue = "next" + +var previousQueue = new Array() +var nextQueue = new Array() + +listClear.addEventListener("click", function() { + post("DELETE_ALL_QUEUE") +}) + +listNext.addEventListener("click", function() { + listClear.style.display = "flex" + listPrevious.classList.remove("selected") + listNext.classList.add("selected") + selectedQueue = "next" + showQueue(nextQueue, "next") +}) + +listPrevious.addEventListener("click", function() { + + listClear.style.display = "none" + listNext.classList.remove("selected") + listPrevious.classList.add("selected") + selectedQueue = "previous" + showQueue(previousQueue, "previous") +}) + + + +function loadQueue(queue, type) { + if(type == "next") { + nextQueue = queue + } else if(type == "previous") { + previousQueue = queue + } + +} + +function showQueue(queue, type) { + + listDiv.innerHTML = "" + if(!queue) { + listDiv.innerHTML = "

Subsonics est déconnecté

" + if(type == "previous") { + listDiv.innerHTML = "

Aucune musique n'a été jouée

" + } + + } else if(queue.length > 0) { + console.log(queue) + var videoList = new Array() + + for(var song of queue) { + if(type == "next") { + song.type = "next" + } else { + song.type = "previous" + } + song.numList = queue.indexOf(song) + var video = new VideoQueue(song) + listDiv.innerHTML += video.generateHTML() + videoList.push(video) + } + + for(var video of videoList) { + + video.loadScript() + } + + const container = listDiv; + const draggableItems = document.querySelectorAll('.draggable'); + + let draggingElement = null; + + draggableItems.forEach(item => { + item.addEventListener('dragstart', (e) => { + e.dataTransfer.setData('text/plain', item.innerHTML); + draggingElement = item; + }); + + item.addEventListener('dragend', () => { + draggingElement = null; + setTimeout(() => { + item.style.display = 'flex'; // Restaure l'affichage de l'élément + }, 0); + updateOrder(); + }); + }); + + container.addEventListener('dragover', (e) => { + e.preventDefault(); + const afterElement = getDragAfterElement(container, e.clientY); + if (draggingElement !== null) { + if (afterElement == null) { + container.appendChild(draggingElement); + } else { + const rect = afterElement.getBoundingClientRect(); + if (e.clientY < rect.top + rect.height / 2) { + container.insertBefore(draggingElement, afterElement); + } else { + container.insertBefore(draggingElement, afterElement.nextElementSibling); + } + } + } + }); + + } else { + if(type == "next") { + listDiv.innerHTML = "

Aucune musique n'est en attente

" + } else if(type == "previous") { + listDiv.innerHTML = "

Aucune musique n'a été jouée

" + } + } +} + +function actualiseQueue() { + if(selectedQueue == "next") { + showQueue(nextQueue, "next") + } else if(selectedQueue == "previous") { + showQueue(previousQueue, "previous") + } +} + + +class VideoQueue { + constructor(data) { + console.log(data) + this.title = data.title + this.author = data.author + this.thumbnail = data.thumbnail + this.url = data.uri + this.duration = data.duration + this.identifier = data.numList + "_" + data.identifier + this.type = data.type + this.numList = data.numList + } + + generateHTML() { + var dragOn = "" + var idOn = "" + if(this.type == "next") { + dragOn = "draggable" + idOn = `${this.numList}_queue_song` + } + + var timecode = null + + // Check if live + + if(this.duration == 9223372036854776000) { + + timecode = " LIVE" + + } else { + timecode = getTimeCode(this.duration) + } + + return ` +
+
+

${timecode}

+
+

${this.title}

+

${this.author}

+
+
+ +
` + } + + loadScript() { + const identifier = getID(this.identifier) + const menu = new DroppableMenu() + + + + menu.add("play", " Lire") + if(this.type == "next") { + menu.add("up", "

Placer au dessus

") + menu.add("delete", "

Supprimer

") + } else { + menu.add("add", "

Ajouter à la file d'attente

") + } + + // Add to a playlist + + menu.add("playlist", "

Ajouter à une playlist

") + + identifier.addEventListener("click", (event) => { + if(event.ctrlKey || event.metaKey) { + post("DELETE_QUEUE", this.numList, this.title) + } else { + menu.show() + + const play = getID(`${menu.id}_play`) + const playlist = getID(`${menu.id}_playlist`) + + playlist.addEventListener("click", () => { + saveToPlaylist(this.url) + }) + + play.addEventListener("click", () => { + post("PLAY_QUEUE", [this.numList, this.type]) + + }) + + if(this.type == "next") { + + const up = getID(`${menu.id}_up`) + const deleteEl = getID(`${menu.id}_delete`) + + up.addEventListener("click", () => { + post("MOVE_QUEUE", this.numList) + }) + + deleteEl.addEventListener("click", () => { + post("DELETE_QUEUE", this.numList, this.title) + }) + + } else { + const add = getID(`${menu.id}_add`) + + add.addEventListener("click", () => { + post("CHANGE_QUEUE", this.numList) + }) + } + + } + }) + + + + } +} + + +function getDragAfterElement(container, y) { + const draggableElements = [...container.querySelectorAll('.draggable:not(.dragging)')]; + return draggableElements.reduce((closest, child) => { + const box = child.getBoundingClientRect(); + const offset = y - box.top - box.height / 2; + if (offset < 0 && offset > closest.offset) { + return { offset: offset, element: child }; + } else { + return closest; + } + }, { offset: Number.NEGATIVE_INFINITY, element: null }).element; +} + +function updateOrder() { + const draggableItems = document.querySelectorAll('.draggable'); + const order = []; + draggableItems.forEach(item => { + order.push(item.id.replace("_queue_song", "")); + }); + console.log('Ordre des divs:', order); + post("MOVE_QUEUE_BY_ENTIRE", order) +} \ No newline at end of file diff --git a/src/web/public/javascript/radios.js b/src/web/public/javascript/radios.js deleted file mode 100644 index 015e235..0000000 --- a/src/web/public/javascript/radios.js +++ /dev/null @@ -1,100 +0,0 @@ -AlwaysRequest("ALL_RADIO", (resp) => { - if(userLocation == "home") { - - const radio_list = document.getElementById("radio_list") - const radioToPush = new Array() - - radioToPush.push("

Radio

") - radioToPush.push(` - -
-

Ajout d'une radio

- -
-

- -
-

URL

- - -
-
- `) - - - - for(var title of resp ) { - - var thumbnail = title.thumbnail - if(!thumbnail) { - - thumbnail = "/images/black-image.svg" - - } - - radioToPush.push(`

${title.title} - ${title.author}

`) - - } - - if(userAdmin) { - - radioToPush.push(` -
Ajouter une radio
`) - } - - radio_list.innerHTML = radioToPush.join("") - - if(userAdmin) { - - const radio_dialog = document.getElementById("radio_dialog") - const radio_close = document.getElementById("radio_close") - const radio_send = document.getElementById("radio_send") - const radio_add = document.getElementById("radio_add") - const radio_info = document.getElementById("radio_info") - const radio_host = document.getElementById("radio_host") - - if(radio_add) { - radio_add.addEventListener("click", () => { - radio_info.innerHTML = "" - radio_host.value = "" - radio_dialog.showModal() - }) - - radio_close.addEventListener("click", () => { - radio_info.innerHTML = "" - radio_dialog.close() - }) - - radio_send.addEventListener("click", () => { - if(radio_host.value != '') { - - post("RADIO/ADD", radio_host.value) - radio_dialog.close() - } else { - - radio_info.innerHTML = "Remplissez une URL !" - } - - }) - - } - - } - - for(var title of resp ) { - - const playBtn = document.getElementById(resp.indexOf(title) +'_radio_pplay') - - playBtn.addEventListener("click", () => { - - post("ADD_SONG_NOW", resp[playBtn.id.replace("_radio_pplay", "")]) - - }) - } - - - } - -}) - - diff --git a/src/web/public/javascript/report.js b/src/web/public/javascript/report.js deleted file mode 100644 index 0ef57b6..0000000 --- a/src/web/public/javascript/report.js +++ /dev/null @@ -1,18 +0,0 @@ - -reportBtn.addEventListener("click", () => { - - report_desc.value = "" - report_level.value = "Majeur" - report_dialog.showModal() -}) - -report_close.addEventListener("click", () => { - - report_dialog.close() -}) - -report_send.addEventListener("click", () => { - - post("REPORT", {"level":report_level.value, "desc": report_desc.value}) - report_dialog.close() -}) \ No newline at end of file diff --git a/src/web/public/javascript/search.js b/src/web/public/javascript/search.js index ac1ca84..73f6f8e 100644 --- a/src/web/public/javascript/search.js +++ b/src/web/public/javascript/search.js @@ -1,214 +1,145 @@ -searchBtn.addEventListener("click", () => { - mainView.innerHTML = '
' - const searchBar = document.getElementById("searchBar") - const searchcontent = document.getElementById("search_content") +function loadSearchView() { + const searchList = getID("search-list") + const searchInput = getID("search-input") + const playlistInfo = getID("playlist-info") - searchBar.addEventListener("change", () => { + loadSplash() - - post("SEARCH", searchBar.value).then(answerOfResult => { + searchInput.addEventListener("change", () => { + + searchList.style.display = "flex" + searchList.style.flexDirection = "column" + searchList.innerHTML = loading(true) + playlistInfo.innerHTML = "" + + if(searchInput.value != '') { + searchResults(searchInput.value) - var results = answerOfResult.results - var playlistReconnised = answerOfResult.playlist + if(searchInput.value.includes("https://") || searchInput.value.includes("http://")) { - if(searchBar.value.includes("https://") || searchBar.value.includes("http://")) { - - searchBar.value= "" + searchInput.value= "" } + } else { + + loadSplash() + } - if(!playlistReconnised) { - if(results.tracks != null) { - const data = results.tracks - - console.log(data) - var contentToPush = new Array() - - for(var title of data) { - - - - var thumbnail = title.thumbnail - - if(!thumbnail) { - - thumbnail = "/images/black-image.svg" - } - - - var PFormatduration = getTimeCode(title.duration) - - if(title.duration == 9223372036854776000) { - - PFormatduration = " LIVE" - } - - contentToPush.push('

' + title.title + '

' + title.author + '

' + PFormatduration + '

Lire maintenant
Ajouter à une playlist
Copier le lien

Ajouter à une playlist

Selectionner la playlist

') - } - - if(contentToPush.join("") == "") { - - searchcontent.innerHTML = '

Aucun morceau trouvé !

' - - } else { - - searchcontent.innerHTML = contentToPush.join("") - } - - for(var title of data) { - - const add_to = document.getElementById(data.indexOf(title) + "_ladd") - const test_lmore = document.getElementById(data.indexOf(title) + "_lmore") - const testPopup = document.getElementById(data.indexOf(title) + "_popup") - const playNow = document.getElementById(data.indexOf(title) + "_playNow") - const copy = document.getElementById(data.indexOf(title) + "_copy") - const addPlaylist = document.getElementById(data.indexOf(title) + "_goPlaylist") - - const PlaylistManager = document.getElementById(data.indexOf(title) + "playlistManager") - const playlistManager_close = document.getElementById(data.indexOf(title) + "playlistManager_close") - const playlistSelection = document.getElementById(data.indexOf(title) + "playlistSelection") - const playlist_add_music = document.getElementById(data.indexOf(title) + "playlist_add_music") - const playlist_add_img = document.getElementById(data.indexOf(title) + "playlist_add_img") - const playlistAddSong = document.getElementById(data.indexOf(title) + "playlistAddSong") - - var thumbnail = data[add_to.id.replace("_ladd", "")].thumbnail - - if(!thumbnail) { - - thumbnail = "/images/black-image.svg" - } - - testPopup.style.display = "none" - - add_to.addEventListener("click", () => { - - post("ADD_SONG", data[add_to.id.replace("_ladd", "")]) - }) - - copy.addEventListener("click", () => { - navigator.clipboard.writeText(data[add_to.id.replace("_ladd", "")].uri) - testPopup.style.display = "none" - }) - - addPlaylist.addEventListener("click", () => { - - PlaylistManager.showModal() - playlist_add_music.innerHTML = data[add_to.id.replace("_ladd", "")].title - playlist_add_img.src = thumbnail - playlistSelection.innerHTML = playlistAvailable - }) - - playlistManager_close.addEventListener("click", () => { - - PlaylistManager.close() - }) - - playlistAddSong.addEventListener("click", () => { - - - PlaylistManager.close() - - post("ADD_SONG_TO_PLAYLIST", {data: playlistSelection.value , song: data[add_to.id.replace("_ladd", "")]}) - - }) - - test_lmore.addEventListener("click",( ) => { - - - testPopup.style.display = "flex" - testPopup.style.top = yMousePos + "px" - - }) - - testPopup.addEventListener("mouseleave", () => { - - testPopup.style.display = "none" - - }) - - playNow.addEventListener("click", () => { - - post("ADD_SONG_NOW", data[add_to.id.replace("_ladd", "")]) - - }) - - - - - } - - - } else { - - searchcontent.innerHTML = '

Aucun morceau trouvé !

' - - } - - } else { - - //https://www.youtube.com/playlist?list=PLA8VHLKYzqTvCcIKhsjGS41nG1zBpRZPy - - - var playlistToPush = new Array() - var playlist_songs = new Array() - - - for(var title of results.videos) { - - var PFormatduration = getTimeCode(title.milis_length) - - if(title.milis_length == 9223372036854776000) { - - PFormatduration = " LIVE" - } - - - playlist_songs.push('

' + title.title + '

' + title.author.name + '

' + PFormatduration + '

') - - } - - playlistToPush.push('

' + results.author.name + " - (" + results.videos.length + " titres)" + '

' + results.title + '


' + playlist_songs.join("")) - - if(playlistToPush.join("") == "") { - - searchcontent.innerHTML = '

Aucun morceau trouvé !

' - - } else { - - searchcontent.innerHTML = playlistToPush.join("") - - - } - - - - - for(var title of results.videos) { - - const add_to = document.getElementById(results.videos.indexOf(title) + "_padd") - const playNow = document.getElementById(results.videos.indexOf(title) + "_pplay") - - - add_to.addEventListener("click", () => { - - post("FP_ADD_SONG", results.videos[add_to.id.replace("_padd", "")].url) - }) - - playNow.addEventListener("click", () => { - - post("FP_ADD_SONG_NOW", results.videos[add_to.id.replace("_padd", "")].url) - - }) - - - - - } - } - - }) - }) -}) \ No newline at end of file + + function searchResults(data) { + + post("SEARCH", data).then((res) => { + + var songList = new Array() + playlistInfo.innerHTML = "" + + if(res.playlist) { + console.log(res.results) + var author = "" + if(res.results.author) { + author = ` +
+ +

${res.results.author.name}

+
+ ` + } + playlistInfo.innerHTML = ` +
+
+
+ +
+
+ +

${res.results.title}

+
+

${res.results.videos.length} titres - ${res.results.view_count} vues

+

${res.results.description}

+
+ ${author} +
+
+
+ + + +
+
+ ` + + const spAdd = getID("sp-add") + const spPlay = getID("sp-play") + const spSave = getID("sp-save") + + spAdd.addEventListener("click", () => { + post("FP_PLAY_PLAYLIST", res.results.url) + }) + + spPlay.addEventListener("click", () => { + post("FP_PLAY_PLAYLIST_NOW", res.results.url) + }) + + spSave.addEventListener("click", () => { + var pcdata = { + "name": res.results.title, + "source": "youtube", + "url": res.results.url + } + post("CREATE_PLAYLIST", pcdata) + }) + + } + + searchList.innerHTML = "" + searchList.style.display = "grid" + + var allList = res.results.tracks + + if(res.playlist) { + allList = res.results.videos + } + + + for(var song of allList) { + var video = null + if(res.playlist) { + video = new VideoComponent(song, true) + } else { + video = new VideoComponent(song, false) + } + + + searchList.innerHTML += video.generateHTML() + songList.push(video) + } + + if(allList.length == 0) { + searchList.style.display = "flex" + searchList.innerHTML = `

Aucun résultat pour "${searchInput.value}" !

` + } + + for(var video of songList) { + video.loadScript() + } + + + }) + + } + + + + function loadSplash() { + searchList.style.display = "flex" + searchList.style.flexDirection = "column" + + get("README").then((res) => { + searchList.innerHTML = res + }) + } +} + diff --git a/src/web/public/javascript/settings.js b/src/web/public/javascript/settings.js index 726220c..79a9994 100644 --- a/src/web/public/javascript/settings.js +++ b/src/web/public/javascript/settings.js @@ -1,363 +1,456 @@ +function loadSettingsView(isAdmin) { -settingsBtn.addEventListener("click", () => { + const stContent = getID("st-content") + const stReport = getID("st-report") + if(isAdmin) { + const stUsers = getID("st-users") + const stNodes = getID("st-nodes") + const stLogs = getID("st-logs") + stUsers.addEventListener("click", () => { + stReport.classList.remove("selected") + stUsers.classList.add("selected") + stNodes.classList.remove("selected") + stLogs.classList.remove("selected") + loadUsersView() + }) + + stNodes.addEventListener("click", () => { + stReport.classList.remove("selected") + stUsers.classList.remove("selected") + stNodes.classList.add("selected") + stLogs.classList.remove("selected") + loadNodesView() + }) + + stLogs.addEventListener("click", () => { + stReport.classList.remove("selected") + stUsers.classList.remove("selected") + stNodes.classList.remove("selected") + stLogs.classList.add("selected") + loadLogsView() + }) + + stReport.addEventListener("click", () => { + stReport.classList.add("selected") + stUsers.classList.remove("selected") + stNodes.classList.remove("selected") + stLogs.classList.remove("selected") + loadReportView() + }) + + } + + loadReportView() + +} + +function loadReportView() { + + const stContent = getID("st-content") + + + + stContent.innerHTML = ` +
+

Rapport de bug

+ +
Si vous trouvez un bug ou vous avez une suggestion, c'est ici que vous pourrez le dire ! Vérifiez bien la catégorie ! Si cela ne vous empêche pas d'utiliser le bot : privilégiez la catégorie "Mineur". Donnez le plus d'information possible, des captures d'écran si possible, la provenance et la facon dont le bug se serait délenché. Précisez aussi si c'était par hasard ou c'était recherché (pas pour vous embêter mais pour savoir si c'est venu n'importe comment ou c'était forcé) ! Merci beaucoup pour votre aide ❤️ !
+ + +
+
+

OOBE

+
L'OOBE est une suite de tutoriels pour vous aider à utiliser l'interface du bot. Si vous avez des difficultés à utiliser le bot, vous pouvez lancer l'OOBE pour vous aider à comprendre comment l'utiliser. Vous pouvez aussi le lancer pour le fun !
+ + - mainView.innerHTML = ` -
-
-
Logs
-
Connexions
-
Utilisateurs
-
-
-
Logs
-
` + + const reportSend = getID("report-send") + const oobeLaunch = getID("oobe-launch") - const settings_logs = getID("settings_logs") - const settings_connexion = getID("settings_connexion") - const settings_users = getID("settings_users") - const settings_content = getID("settings_content") - - settings_logs.style.color = "white" - loadLogs() - - - - - settings_logs.addEventListener("click", () => { - loadLogs() - + oobeLaunch.addEventListener("click", () => { + oobeStep2() }) - settings_connexion.addEventListener("click", () => { - loadConnexion() - - }) + reportSend.addEventListener("click", () => { + + const modal = new ModalComponent({"title":"Rapport de bug", "width":"20%"}) - settings_users.addEventListener("click", () => { - loadUsers() - - }) - - - - function loadUsers() { - - socket.emit("GET/USERS") - userLocation = "users" - - } - - function loadConnexion() { - - userLocation = "nodes" - socket.emit("GET/NODES") - - } - - function loadLogs() { - userLocation = "logs" - settings_content.innerHTML = ` - + + + +

Description

+ +
-
- + `) + modal.show() + + + + const reportDesc = getID("report-desc") + const reportType = getID("report-type") + const reportSendConfirm = getID("report-send-confirm") + const reportContent = getID("report-content") + + reportSendConfirm.addEventListener("click", () => { + reportContent.innerHTML = "

Envoi du rapport ...

" + post("REPORT", {"level":reportType.value, "desc": reportDesc.value}).then((data) => { + reportContent.innerHTML = "

Rapport envoyé avec succès !

" + }) + }) + + }) +} + +function loadUsersView() { + + const stContent = getID("st-content") + + stContent.innerHTML = ` +
+

Utilisateurs

+
Voici la liste des utilisateurs du bot. Vous pouvez voir leur ID, leur pseudo, leur avatar et leur rôle. Vous pouvez aussi les bannir ou les débannir.
+
+
+
+
` - const logs_selection = getID("logs_selection") - const logs_content = getID("logs_content") + const usersList = getID("users-list") - const logs_data = get("LOGS") + get("USERS") + + AlwaysRequest("USERS", (data) => { + + usersList.innerHTML = "" + var usersSettingList = new Array() - logs_data.then(data => { - - - var optionToPush = new Array() - for(var log of data) { - optionToPush.push("") + for(var user of data) { + var userSetting = new UserSetting(user) + usersSettingList.push(userSetting) + usersList.innerHTML += userSetting.generateHTML() } - logs_selection.innerHTML = optionToPush.reverse().join("") - - for(var log of data) { - - if(logs_selection.value == log.name) { - - var logToPush = new Array() - - - for(var line of log.value.split("\n")) { - - line.toString() - - - line = line.replace("[INFO]", "[INFO]") - .replace("[ERROR]", "[ERROR]") - .replace("[WARN]", "[WARN]") - .replace("[FATAL]", "[FATAL]") - .replace("[STEP]", "[STEP]"); - - logToPush.push("

" +line+ "

") - - } - - - - logs_content.innerHTML = logToPush.join("") - } - + for(var userSetting of usersSettingList) { + + userSetting.loadScript() } - logs_selection.addEventListener("change", () => { + + }) +} + +function loadNodesView() { + + const stContent = getID("st-content") + + stContent.innerHTML = ` +
+

Maintenance

+

Alimentation du bot

+
+ +
+

Nodes Lavalink

+

Note : Les serveurs ci-dessous permettent le bon fonctionnement du Bot.

+

Si aucun des serveurs ne fonctionne, ajoutez-en en prenant ce lien pour la liste des serveurs : Lavalink SSL

+
+
+ +
+
+
+
+
+
+ ` + + const nodesList = getID("nodes-list") + const nodesAdd = getID("nodes-add") + const nodesRestart = getID("nodes-restart") + + nodesRestart.addEventListener("click", () => { + get("RESTART") + }) + + nodesAdd.addEventListener("click", () => { + const modal = new ModalComponent({"title":"Ajouter un serveur", "width":"20%"}) + + modal.setContent(` +
+ + + + + + +
+ +
+ `) + + modal.show() + + const nodeHost = getID("node-host") + const nodePort = getID("node-port") + const nodePassword = getID("node-password") + const nodeSendConfirm = getID("node-send-confirm") + const nodeContent = getID("node-content") + + nodeSendConfirm.addEventListener("click", () => { + nodeContent.innerHTML = "

Ajout du serveur ...

" + post("NODES/ADD", {"host":nodeHost.value, "port":Number(nodePort.value), "password":nodePassword.value}).then((data) => { + nodeContent.innerHTML = "

Serveur ajouté avec succès !

" + }) + }) + }) + + get("NODES") + + AlwaysRequest("NODES", (data) => { + nodesList.innerHTML = "" + var nodesSettingList = new Array() + + for(var node of data) { + var nodeSetting = new NodeSetting(node) + nodesSettingList.push(nodeSetting) + nodesList.innerHTML += nodeSetting.generateHTML() + } + + for(var nodeSetting of nodesSettingList) { + nodeSetting.loadScript() + } + }) +} + +function loadLogsView() { + + const stContent = getID("st-content") + + stContent.innerHTML = ` +
+

Logs

+
Voici les logs du bot. Vous pouvez voir les logs de l'activité du bot, les erreurs et les logs de la musique.
+ +
Trier par :
+ + +
+
+ +
+
+ +
+ ` + + const logsList = getID("logs-list") + const logsType = getID("logs-type") + const logsSort = getID("logs-sort") + + get("LOGS").then((data) => { + logsType.innerHTML = "" + + var logsData = new Map() + + data.reverse() + + for(var log of data) { - for(var log of data) { + logsType.innerHTML += `` + logsData.set(log.name, log.value) + } - if(logs_selection.value == log.name) { + loadLog() - var logToPush = new Array() + logsType.addEventListener("change", () => { + logsSort.value = "all" + loadLog() + }) - for(var line of log.value.split("\n")) { - - line.toString() - - - line = line.replace("[INFO]", "[INFO]") - .replace("[ERROR]", "[ERROR]") - .replace("[WARN]", "[WARN]") - .replace("[FATAL]", "[FATAL]") - .replace("[STEP]", "[STEP]"); + logsSort.addEventListener("change", () => { + + loadLog(logsSort.value) + }) - + /** + * @private + */ + function loadLog(sort) { + var logToPush = new Array() - logToPush.push("

" + line + "

") - - } - - - logs_content.innerHTML = logToPush.join("") + for(var line of logsData.get(logsType.value).split("\n")) { + + + if(sort && sort != "all" && !line.includes(sort)) { + continue } + line.toString() + + + line = line.replace("[INFO]", "[INFO]") + .replace("[ERROR]", "[ERROR]") + .replace("[WARN]", "[WARN]") + .replace("[FATAL]", "[FATAL]") + .replace("[STEP]", "[STEP]") + .replace("[Users]", "[Users]") + .replaceAll("[Web]", "[Web]") + .replaceAll("[Authentification]", "[Authentification]") + .replaceAll("[Discord]", "[Discord]") + .replaceAll("[Node-Finder]", "[Node-Finder]") + .replaceAll("[Actualisation]", "[Actualisation]") + .replaceAll("[Playlist-Manager]", "[Playlist-Manager]") + .replaceAll("[Lavalink-Player]" , "[Lavalink-Player]") + .replaceAll("[Lavalink-Manager]", "[Lavalink-Manager]") + + logToPush.push("

" +line+ "

") + } - }) - - }) - - } - -}) - - -AlwaysRequest('USERS',(data) => { - - const settings_content = getID("settings_content") - - if(settings_content) { - - var userToPush = new Array() - - console.log(data) - - for(var user of data) { - - var admin_bar = '' - - - userToPush.push("
") - - } - - - settings_content.innerHTML = userToPush.join("") - - - - - for(var user of data) { - - - let adminBtn = getID(data.indexOf(user) + "_uadmin") - let deleteBtn = getID(data.indexOf(user) + "_udelete") - - if(data[adminBtn.id.replace("_uadmin", "")].admin == true) { - - - adminBtn.style.color = "#d2bd19" - - } - - adminBtn.addEventListener("click", () => { - - post("USERS/ADMIN", data[adminBtn.id.replace("_uadmin", "")]) - - socket.emit("GET/USERS") - }) - - deleteBtn.addEventListener("click", () => { - - - post("USERS/DELETE", data[adminBtn.id.replace("_uadmin", "")]) - - socket.emit("GET/USERS") - }) - } - } - - - - - -}) - -AlwaysRequest("NODES",(data) => { - - const settings_content = getID("settings_content") - - if(settings_content && userLocation == "nodes") { - - var dataToPush = new Array() - - dataToPush.push(`
-

Note : Les serveurs ci-dessous permettent le bon fonctionnement du Bot.

-

Si aucun des serveurs ne fonctionne, ajoutez-en en prenant ce lien pour la liste des serveurs : Lavalink SSL

-

`) - - dataToPush.push(` - -
-

Ajout d'une connexion Lavalink

- -
-

- -
-

Host

- -

Port

- -

Mot de passe

- - -
-
- - - `) - - console.log(data) - - for(var node of data) { - - var stateInput = "

Déconnecté

" - - if(node.state == true) { - - stateInput = "

Connecté

" + + logsList.innerHTML = logToPush.join("") } - - dataToPush.push(` -
-
- -

${node.host}

- ${stateInput} -
-
- - -
-
`) - - } - - settings_content.innerHTML = dataToPush.join("") - - const an_dialog = getID("an_dialog") - const an_close = getID("an_close") - const an_add = getID("an_create") - const an_host = getID("an_host") - const an_port = getID("an_port") - const an_password = getID("an_password") - const an_send = getID("an_send") - const an_info = getID("an_info") - - an_add.addEventListener("click", () => { - an_info.innerHTML = "" - an_dialog.showModal() }) - - an_close.addEventListener("click", () => { - an_info.innerHTML = "" - an_dialog.close() - }) - - an_send.addEventListener("click", () => { - an_info.innerHTML = "" - - - if(an_host.value != '' && an_port.value != '' && an_password.value != '' ) { - - - var data = { - "host":an_host.value.replace(" ", ""), - 'port': parseInt(an_port.value), - "password": an_password.value, - "retryAmount": 1 - } - - post("NODES/ADD", data) - - an_dialog.close() - - } else { - - - an_info.innerHTML = "Remplissez toutes les cases !" - } - - - - }) - - for(var node of data) { - - let reloadBtn = getID(data.indexOf(node) + "_reload") - let deleteBtn = getID(data.indexOf(node) + "_delete") - - reloadBtn.addEventListener("click", () => { - post("NODES/RELOAD", data[reloadBtn.id.replace("_reload", "")]) - - }) - - deleteBtn.addEventListener("click", () => { - console.log(deleteBtn) - console.log(data[reloadBtn.id.replace("_reload", "")]) - post("NODES/DELETE", data[reloadBtn.id.replace("_reload", "")]) - - }) - - } - - - + +} + +class NodeSetting { + constructor(node) { + this.node = node + } + + generateHTML() { + let status = " Déconnecté" + if(this.node.state) { + status = " Connecté" + } + return `
+

${this.node.host}

+

${status}

+
+ + +
+
+ ` + } + + loadScript() { + + const nodeDelete = getID(`${this.node.host}_delete`) + const nodeReload = getID(`${this.node.host}_reload`) + if(nodeReload) { + nodeReload.addEventListener("click", () => { + post("NODES/RELOAD", this.node) + }) + nodeDelete.addEventListener("click", () => { + post("NODES/DELETE", this.node) + }) + } - + } +} + + + +class UserSetting { + constructor(user) { + this.user = user } + generateHTML() { + let rank = "Utilisateur" + let ban = "Non banni" + if(this.user.admin) { + rank = "Administrateur" + } + if(this.user.banned) { + ban = "Banni" + } + return `
+
+ +
+

${this.user.user.global_name}

+

${this.user.user.username}

+
+
+

${rank} - ${ban}

+
+ + + +
+
+ ` + } + loadScript() { + const userBan = getID(`${this.user.user.id}_ban`) + const userDelete = getID(`${this.user.user.id}_delete`) + const userAdmin = getID(`${this.user.user.id}_admin`) -}) \ No newline at end of file + if(userBan) { + userBan.addEventListener("click", () => { + + post("USERS/BAN", this.user.user.id) + }) + + userDelete.addEventListener("click", () => { + + post("USERS/DELETE", this.user.user.id) + }) + + userAdmin.addEventListener("click", () => { + + post("USERS/ADMIN", this.user.user.id) + }) + } + + } +} \ No newline at end of file diff --git a/src/web/public/javascript/tooltip.js b/src/web/public/javascript/tooltip.js deleted file mode 100644 index 86357c4..0000000 --- a/src/web/public/javascript/tooltip.js +++ /dev/null @@ -1,80 +0,0 @@ -const tooltip = document.getElementById("tooltip") - -tooltip.style.visibility = 'hidden' -tooltip.style.display = 'none' -const alreadyDeclare = new Array() - -const tooltip_list = { - "radio_add": "Ajouter par l'URL", - "sendplaylist": "Envoyer la playlist", - "playlistplay": "Jouer la playlist", - "playlistdelete": "Effacer la playlist", - "an_create": "Ajouter un serveur", - "pplay": "Jouer maintenant", - "delete": "Supprimer", - "add": "Ajouter à la liste de lecture", - "backward": "Précédent", - "forward": "Suivant", - "lmore": "Plus d'options", - "loop": "Répéter le titre", - "shuffle": "Mélanger la liste de lecture", - "list_btn": "Liste de lecture", - "disconnect": "Déconnecter le bot", - "reload": "Relancer le serveur", - "admin": "Donner les permissions", - "takeCurrent": "Ajouter le titre à une playlist", - "volbtn": "Volume" - } - -document.onmousemove = function(e) -{ - xMousePos = e.clientX + window.scrollX; - yMousePos = e.clientY + window.scrollY; - - for(var key in tooltip_list) { - - showToolTip(key, tooltip_list[key], e) - - } - -}; - - -function showToolTip(id, text, e) { - - if(e.target) { - - if(e.target.id.includes(id)) { - - if(!alreadyDeclare.includes(e.target.id)) { - alreadyDeclare.push(e.target.id) - const elementAssociate = document.getElementById(e.target.id) - - elementAssociate.addEventListener("mousemove", () => { - tooltip.style.visibility = 'visible' - tooltip.style.display = 'unset' - tooltip.style.top = ( yMousePos - ( tooltip.offsetHeight + 20)) + "px" - tooltip.style.width = "150px" - tooltip.style.left =(xMousePos - 75 )+ "px" - tooltip.innerHTML = text - - }) - - elementAssociate.addEventListener("mouseleave", () => { - - - alreadyDeclare.splice(alreadyDeclare.indexOf(e.target.id), 1) - - tooltip.style.visibility = 'hidden' - tooltip.style.display = 'none' - - }) - - } - - - } - - } - -} \ No newline at end of file diff --git a/src/web/public/javascript/view.js b/src/web/public/javascript/view.js new file mode 100644 index 0000000..329c52d --- /dev/null +++ b/src/web/public/javascript/view.js @@ -0,0 +1,81 @@ + + +function loadSearch() { + setTileActive("search_icon") + loadView(` +
+ + +
+
+
+
+ + + +
+
+ `) + loadSearchView() + +} + +loadSearch() + + +function loadSettings() { + setTileActive("settings_icon") + + var contentAdmin = "" + var isAdmin = false + + get("USER_INFO").then((data) => { + if(data.admin) { + isAdmin = true + contentAdmin = ` +

Utilisateurs

+

Maintenance

+

Logs

` + } + + loadView(` +
+
+

Rapport & OOBE

+ ${contentAdmin} +
+
+ +
+
+ `) + loadSettingsView(isAdmin) + }) + + + +} + + +const search_btn = getID("search_btn") +const settings_btn = getID("settings_btn") + +const search_icon = getID("search_icon") +const settings_icon = getID("settings_icon") + +tileList.push(search_icon) +tileList.push(settings_icon) + + +search_btn.addEventListener("click", () => { + loadSearch() + +}) + +settings_btn.addEventListener("click", () => { + + loadSettings() + +}) + + diff --git a/src/web/public/stylesheets/login.css b/src/web/public/stylesheets/login.css new file mode 100644 index 0000000..4fa15a4 --- /dev/null +++ b/src/web/public/stylesheets/login.css @@ -0,0 +1,96 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300&display=swap'); +@font-face { + font-family: 'Gunship'; + src: url(gunship.ttf); +} + +body { + display: flex; + justify-content: center; /* Centrer horizontalement */ + align-items: center; /* Centrer verticalement */ + height: 100vh; /* 100% de la hauteur de la fenêtre */ + background: #160120; + color: #FFF; + font-family: 'Inter', sans-serif; + margin: 0 !important; + transition: 0.2s; + overflow: hidden; +} + +p { + margin: 0 !important; +} + +.lg-Discordbtn img { + width: 100%; + height: 100%; + object-fit: contain; +} + +.lg-Discordbtn { + width: 200px; + display: flex; + align-items: center; + padding: 8px; + border-style: solid; + border-color: #2c3df4; + border-radius: 10px; + background: #2C3DF4; + color: white; + width: 160px; + transition: all 0.2s ease 0s; + cursor: pointer; +} + +.lg-Discordbtn:hover { + background: #182af4; + border-color: #182af4; + +} + +.lg-title { + display: flex; + gap: 10px; + align-items: center; + justify-content: center; +} + +.lg-logopng { + width: 80px; + height: 80px; + object-fit: contain; +} + +.lg-title-text { + font-size: 52px; + font-family: 'Gunship', sans-serif; + text-shadow: white 0px 0px 10px; + user-select: none; + +} + +.lg-box { + + text-align: center; + border-radius: 10px; + background: #2D2D2D; + align-items: center; + width: 600px; + display: flex; + gap: 20px; + flex-direction: column; + padding: 50px 20px 50px 20px; +} + +.lg-subinfo { + display: flex; + width: 483px; + height: 62px; + flex-direction: column; + justify-content: center; + color: #8f8f8f; + text-align: justify; + font-family: Inter; + font-size: 10px; + +} \ No newline at end of file diff --git a/src/web/public/stylesheets/style.css b/src/web/public/stylesheets/style.css index c33d80e..624bc1f 100644 --- a/src/web/public/stylesheets/style.css +++ b/src/web/public/stylesheets/style.css @@ -1,1294 +1,1714 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300&display=swap'); @font-face { - font-family: 'Gunship'; - src: url(gunship.ttf); + font-family: 'Gunship'; + src: url(gunship.ttf); } -html { - - min-height: 100%; - min-width: 100%; - margin: 0; - -} +/* Main Class*/ body { - - background-color: black; - color: white; - font-family: 'Roboto', sans-serif; - background: linear-gradient(225deg, #342348 0%, #1C1A31 100%); - overflow-x: hidden; - - -} - -/*LOGIN PAGE*/ - -.LOGIN_Connexion { - - font-family: 'Gunship'; - font-size: 20px; -} - -.LOGIN_box { - - text-align: center; - margin-top: 15vw; - border-radius: 12px; - - /* - background-color: #106f8b; - opacity: 0.8; - background-size: 6px 6px; - background-image: linear-gradient(0deg, #106f8b 50%, #1F859E 50%);*/ - background: linear-gradient(90deg, #515151 0%, #2e2e2e 100%); - align-items: center; - padding: 5%; - width: 500px; - margin-right: auto; - margin-left: auto; - -} - -.LOGIN_logopng { - - width: 80px; - height: 80px; -} - -.LOGIN_DiscordBtn { - - padding: 8px; - border-style: solid; - border-color: #2c3df4; - border-radius: 12px; - background-color: #2c3df4; - color: white; - width: 160px; - transition: all 0.2s ease 0s - -} - - - -.LOGIN_DiscordBtn:hover { - box-shadow: #2c3df4 0px 0px 10px; -} - -.LOGIN_DiscordBtn:active { - background-color: transparent; - box-shadow: #2c3df4 0px 0px 10px; -} - -.LOGIN_DiscordBtn img { - - width: 125px; - -} - -/*Index Page*/ - - -.INDEX_userInfo { - + flex-direction: column; + align-items: flex-start; + background: #160120; display: flex; - align-items: center; - flex-direction: row; - text-align: right; -} - -.INDEX_userInfo:hover { - - cursor: pointer; -} - -.INDEX_title { - - color:white; - display: flex; - justify-content: space-between; - - -} - -.INDEX_usrname { - - opacity: 0.8; - font-size: 12px; - margin: 0; -} - - -.INDEX_gbname { - - margin: 0; -} - - -.INDEX_userInfo img { - - - width: 60px; - - -} - -.INDEX_Content { - - padding: 2%; -} - - - - - -.INDEX_userPopup { - - display: flex; - flex-direction: column; - background-color: #2e2e2e; - margin-top: 20px; - font-size: 12px; - text-align: center; - color: white; - position: absolute; - width: 130px; - z-index: 2; -} - -#userInfoglobal { - - align-items: right; -} - -.INDEX_signout { - - width: 100%; - color: red; - text-decoration: none; - outline: none; - padding: 10%; -} - -.INDEX_signout:hover { - - background-color: red; - color: white; - cursor: pointer; -} - -.INDEX_line { - - width: 100%; - color: rgb(255, 255, 255); - text-decoration: none; - outline: none; - padding: 10%; -} - -.INDEX_line:hover { - - background-color: rgb(255, 255, 255); - color: rgb(0, 0, 0); - cursor: pointer; -} - - -/*PLAYER*/ - - -.PLAYER_box { - - - background-color: rgba(0, 0, 0, 0.655); - display: flex; - flex-direction: row; - justify-content: space-between; - padding: 1.5%; - align-items: center; - position: absolute; - width: 100%; - height: 15vh; - bottom: 0; - color: white; - -} - -.PLAYER_middle { - - display: flex; - text-align: center; - align-items: center; - flex-direction: column; + color: #FFF; + font-family: 'Inter', sans-serif; + margin: 0 !important; + transition: 0.2s; } p { - - margin: 0 !important; + margin: 0 !important; } -.PLAYER_durationbar { - - margin-top: 1vh; - display: flex; - flex-direction: row; - align-items: center; - -} - -.PLAYER_title { - - display: flex; - flex-direction: row; - align-items: center; - width: 30vw; -} - -#duration { - - width: 25vw; - margin-right: 0.5vw; - margin-left: 0.5vw; -} - -#music_img { - - margin-right: 1vw; +h1 { + margin: 0 !important; } -.third { - - color: rgb(255, 255, 255); - background-color: transparent; - border: none; - border-radius: 100%; - text-shadow: 1px 1px 10px white; - font-size: 17px; - +.icon { + height: 22.401px !important; + transition: 0.2s; } -.primary { - - display: inline-block; - background-color: #ffffff; - color: rgb(0, 0, 0); - border: none; - border-radius: 100%; - width: 50px; - height: 50px; - font-size: 17px; +.gunship { + font-family: 'Gunship' !important; +} +.point { + + position: relative; + +} +.point .icon { + color: #ffffff !important; + } -.primary:active { - - scale: 0.95; +.point::after { + content: ""; + display: block; + width: 5px; + height: 5px; + position: absolute; + left: 50%; + transform: translateX(-50%); + background: currentColor; /* Couleur du point */ + border-radius: 50%; /* Pour rendre le point rond */ + margin: 5px auto 0; /* Pour centrer le point et ajouter un espace en dessus */ } -.secondary { - - color: rgb(178, 178, 178); - border: none; - background-color: transparent; - width: 50px; - height: 50px; - font-size: 17px; - +.invert { + background-color: #ffffff !important; + color: #000000 !important; } -.secondary:hover { - - color: white; +.invert:hover { + transform: scale(1.0) !important; } +.global { + width: 100vw; + height: 100vh; + position: relative; + max-height: 100vh; + display: flex; + flex-direction: column; + overflow: hidden; -.showPicture { - - margin: 0 !important; - margin-bottom: 10px; - width: 6vw; - height: 4.5vw; -} - -.title { - - width: 100%; -} - -/*ACTBAR*/ - -.PLAYER_actionbar { - text-align: right; - width: 30vw; - display: flex; - justify-content: end; - gap: 0.8vw; } .grised { - filter : invert(50%); - -} - + filter : invert(50%); + + } + .disabled { - - color: rgb(47, 47, 47) !important; -} - -/*RAPPORT*/ - -.report_close { - color: whitesmoke; - background-color: transparent; - padding: 5px; - width: 40px; - height: 40px; - border: none; - transition: all 0.2s ease 0s; - user-select: none; - -webkit-user-select: none; - -} - -.report_close:hover { - - color: red; - cursor: pointer; -} - -.report_dialog { - - width: 50%; - padding: 0; - background: linear-gradient(90deg, #515151 0%, #2e2e2e 100%); - border: none; - border-radius: 12px; -} - -.rlineclose { - position: sticky; - width: 100%; - display: flex; - justify-content: space-between; - -} - -.rtitle { - color: white; - font-family: 'Gunship', sans-serif; - padding: 2%; -} - -.rcontent { - - padding: 2%; - display: flex; - flex-direction: column; -} - -.runder { - - padding-bottom: 2%; - padding-top: 2%; - color: white; -} - -.rsend { - color: white; - margin: 2%; - padding: 1%; - align-self: center; - background-color: transparent; - border: none; - border-style: solid; - border-color: #2c3df4; - border-radius: 12px; - transition: 0.1s; -} - -#report_level { - - color: white; - background-color: transparent; - border: solid 2px #2c3df4; - padding: 1%; - border-radius: 12px; -} - -#report_level option { - - color: rgb(255, 255, 255); - background-color: #515151; -} - -.rsend:hover { - - background-color: #2c3df4; -} - -.rsend:active { - background-color: transparent; -} - -#report_desc { - border-radius: 12px; - height: 20vh; -} - - -/*SETTINGS*/ - - - - -.third-join { - - color: rgb(53, 255, 35); - background-color: transparent; - border: none; - border-radius: 100%; - text-shadow: 1px 1px 10px rgb(53, 255, 35); - - -} - -.third-leave { - - color: rgb(255, 35, 35); - background-color: transparent; - border: none; - border-radius: 100%; - text-shadow: 1px 1px 10px rgb(255, 27, 27); - + color: rgb(23, 23, 23) !important; } -.scontent { - flex: 1; - padding: 1vw; - border-radius: 0 12px 12px 0; - - +.playicon { + background-color: rgb(23, 23, 23) !important; } -.slineclose { - - width: 100%; - text-align: right; - -} - - -.dialogTitle { - - color: white; - font-family: 'Gunship', sans-serif; - font-size: 0.85vw; -} - -.ssidebar_line { - - color: white; - width: 100%; - text-align: left; - transition: all 0.1s ease 0s; - padding: 8%; -} - -.ssidebar_line:hover { - - background-color: white; - color: black; - -} - - -.ssidebar_content { - - height: 100%; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - cursor: pointer; -} - -.beta { - - font-family: 'Gunship', sans-serif; - font-size: 10px; - position: fixed; - width: 60px; - transform: translateY(305%); - background-color: rgb(48, 5, 77); - -} - - -.INDEX_picture { - padding-left: 10%; - display: flex; - flex-direction: column; - text-align: center; -} - - - .invisible { + display: none !important; +} - display: none; +.playicon.disabled { + background-color: rgb(42, 42, 42) !important; +} + + +input[type="text"] { + background-color: #545454; + padding: 5px; + border-radius: 5px; + border: none; + color: #ffffff; } -#volumeBox { +input[type="number"] { + background-color: #545454; + padding: 5px; + border-radius: 5px; + border: none; + color: #ffffff; - background-color: #2e2e2e; - position: absolute; - bottom: 50px; - left: 50%; - transform: translateX(-50%); - text-align: center; - border-radius: 12px; - width: 5vw; - justify-content: center; } -#volumeInput { - width: 0.5vw; - height: 20vh; - margin: 1vw; - margin-bottom: 0; - appearance: slider-vertical; + +button { + background-color: #545454; + padding: 5px; + border-radius: 5px; + border: none; + color: #ffffff; + cursor: pointer; + transition: 0.2s; + user-select: none; +} + +button:hover { + background-color: #ffffff; + color: #000000; +} + +/*Color */ + +.red { + color: #FF3232 !important; +} + +.green { + color: #32FF32 !important; +} + + +.wh { + color: #CBCBCB; +} +.wh:hover { + color: #ffffff; + cursor: pointer; +} + +.whsolid { + color: #CBCBCB; +} + +/* Player */ + +.player { + display: flex; + padding: 18px; + justify-content: space-between; + align-items: center; + align-self: stretch; + background: #212121; + position: relative; + height: 10vh; + +} + +.video { + + display: flex; + align-items: center; + gap: 19px; + +} + +.video_image { + width: 160px; + height: 88px; + flex-shrink: 0; + background: #000; +} + +.video_image img { + object-fit: cover; + width: 100%; + height: 100%; + +} + +.video_title_title { + display: flex; + flex-direction: row; + gap: 0; + width: 500px; + overflow: hidden; /* Cache le contenu qui dépasse */ + white-space: nowrap; /* Empêche le texte de passer à la ligne */ + position: relative; /* Position relative pour l'animation */ +} + +.scroll p { + right: 0%; + white-space: nowrap; /* Empêche le texte de passer à la ligne */ + position: relative; /* Position relative pour l'animation */ + animation: scroll 15s linear infinite; /* Animation de défilement */ +} + +@keyframes scroll { + from { + transform: translateX(0%); /* Départ de l'animation */ + } + to { + transform: translateX(-102%); /* Fin de l'animation */ + } + +} + +.video_title_channel { + + color: #A0A0A0; + font-family: Inter; /* Police du texte */ + font-size: 15px; /* Taille du texte */ + font-style: normal; + font-weight: 400; + line-height: normal; +} + +.video_title { + + display: flex; + flex-direction: column; + gap: 5px; + +} + +.actionbar { + + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: end; + gap: 20px; +} + +.actionbar div { + display: flex; + gap: 20px; +} + +.controller { + + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); +} + +.buttons { + display: flex; + justify-content: center; + align-items: center; + gap: 30px; + align-self: stretch; +} + + +.playicon { + + display: flex; + width: 30px; + height: 30px; + padding: 14px; + justify-content: center; + align-items: center; + border-radius: 100%; + background: #000; + transition: 0.2s; +} + +.playicon:hover { + + cursor: pointer; +} + +.durationBar { + display: flex; + align-items: center; } -@-moz-document url-prefix() { -#volumeInput { - width: 10vw !important; - height: 20vh !important; - -moz-transform: rotate(-90deg); -} -} -#volumeTxt { - font-size: 1vw; - margin: 1vw !important; - text-align: center; -} +/* Duration / Volume bar */ -.volDiv { - display: flex; - position: relative; -} +#duration { -.pri_disable { - - background-color: #515151; -} - - -#listBox { - - background-color: #2e2e2e; - position: absolute; - bottom: 50px; - width: 400px; - height: 300px; - right: 0%; - text-align: center; - border-radius: 12px; - overflow-y:auto; -} - - - -.song { - display: flex; - flex-direction: row; - align-items: center; - padding-left: 2%; - padding-right: 2%; - padding-top: 1.5%; - padding-bottom: 1.5%; - - user-select: none; - -webkit-user-drag: element; - outline: none; - -} - -.song img { - - transition: 0.5s; -} - -.song img:hover { - - transform: scale(1.3); -} - -.song:hover { - - color: white !important; - background-color: #4f4f4f; - width: 100%; -} - -.song:active { - - background-color: unset; - width: 100%; -} - -.list_thumbnail { - - - width: 60px; - height: 45px; - margin-right: 10px; - -} - -.list_title { - - font-size: 12px; - word-break: break-all; - -} - -.list_titleSong { - - width: 100%; -} - -.list_delete { - - background-color: transparent; - color: white; - border: none; - transition: 0.1s; -} - -.list_delete:hover { - - color: red !important; -} - -.song:hover .list_delete { - - color: rgb(255, 255, 255); -} -.song:hover .list_upSong { - - color: rgb(255, 255, 255); -} -.list_upSong:hover { - - color: #19a7d2 !important; -} - - -.list_upSong { - - margin-left: 10px; - margin-right: 10px; - background-color: transparent; - color: white; - border: none; - transition: 0.1s; -} - -.list_error { - - text-align: center; - padding-top: 35%; - -} - -/*SCROLL BAR*/ - -/* width */ -::-webkit-scrollbar { - width: 10px; - margin-right: 20px; -} - -/* Track */ -::-webkit-scrollbar-track { - border-radius: 12px; -} - -/* Handle */ -::-webkit-scrollbar-thumb { - background: #ffffffa8; - border-radius: 10px; -} - - -.number { - - - font-size: 11px; - color: rgb(255, 255, 255); - border: none; - border-radius: 100%; - text-align: center; - justify-content: center; - vertical-align: middle; - width: 14px; - height: 14px; - background-color: rgb(99, 0, 129); - margin: 0; - position: absolute; /* Position the badge within the relatively positioned button */ - top: 0; - right: -2px; - - - -} - -/*INDEX Search & Play*/ - -.INDEX_playlist { - - background-color: #2e2e2e86; - width: 20%; - height: 68vh; - border-radius: 12px; - overflow-y: auto; -} - -.INDEX_search { - - background-color: #2e2e2e86; - width: 100%; - height: 68vh; - margin-left: 1%; - border-radius: 12px; - overflow-y: auto; - padding: 1%; - -} - -.INDEX_subcontent { - - display: flex; - margin-top: 0.5%; - height: 70vh; - width: 100%; -} - -#searchBar { - border: none; - border-radius: 20px ; - background-color: #ffffff; - color: rgb(0, 0, 0); - width: 30%; - padding: 0.3%; - padding-left: 1%; - outline: none; - user-select: none; - font-size: 14px; - - -} - -.findbar { - - display: flex; - align-items: center; - gap: 10px; - color: white; - margin-bottom: 1%; - position: fixed; - width: 100%; - -} - -.search_song { - - display: grid; - align-items: start; - color: white; - font-size: 12px; - margin-bottom: 5px; - grid-template-columns: 0.5fr 3fr 1fr 1fr 0.1fr; - align-items: center; - -} - -.search_thumbnail { - width: 100px; - height: 75px; - margin-right: 20px; -} - -.search_middle { - - margin-bottom: 4%; -} - - -.search_add { - - background-color: transparent; - - color: #ffffff; - border: none; - font-size: 20px; - transition: 0.1s; -} - -.search_add:hover { - - color: #00bfff; -} - -.search_lmore { - - color: rgb(255, 255, 255); - background-color: transparent; - border: none; - font-size: 20px; - transition: 0.1s; - text-align: center; - z-index: 0; -} - -.search_lmore:hover { - - color: #51ff00; -} - - -.search_buttons { - - display: flex; - flex-direction: row; - gap: 10px; - text-align: right; -} - -.searchMoreDiv { - - display: flex; - position: relative; -} - -.searchPopup { - background-color: #2d2d2d; - position: absolute; - flex-direction: column; - width: 200px; - right: 3%; - text-align: center; - z-index: 2; -} - -/* PLAYLIST */ - -.pSearch { - - display: flex; - color: rgba(255, 255, 255, 0.719); - flex-direction: row; - align-items: center; - margin-top: 5%; - width: 100%; - padding: 2%; - padding-left: 7%; - font-size: 20px; - transition: 0.1s; -} - -.pSearch:hover { - - cursor: pointer; -} - - - -.pSearch p { - - width: 100%; - -} - -.playlist-content { - - - -} - -.playlist_div { - - color: rgba(255, 255, 255, 0.719); - display: flex; - flex-direction: row; - align-items: center; - width: 100%; - padding: 4%; - -} - -.playlist_div:hover { - - background-color: rgb(255, 255, 255); - color: black !important; - cursor: pointer; -} - -.playlist_tile { - - width: 60px; - height: 60px; - margin-right: 5%; - -} - -.apContent { - - display: flex; - flex-direction: column; - text-align: center; - align-items: center; - color: white; - margin-top: 5%; -} - - -.apContent p { - - padding: 3%; -} - -#apText { - - border: none; - border-radius: 12px; - padding: 0.5%; - padding-left: 1%; -} - -.apTile { - - width: 150px; - height: 150px; - - -} - -.apTitle { - - display: flex; - width: 100%; - align-items: end; -} - -.apPres { - - display: flex; - align-items: end; - justify-content: space-between; -} - -.apName { - - font-family: "Gunship", sans-serif; - font-size: 35px; - margin-left: 2% !important; - width: 100% -} - -.apButtons { - - display: flex; - justify-content: end; - align-items: center; - gap: 5%; - width: 20%; - -} - -.ppTile { - - width: 180px; -} - -/*SETTINGS*/ - -.SETTINGS_content { - - width: 100%; - margin-left: 2%; - border-left: solid 1px #515151; - padding: 2%; - overflow: auto; - -} - -.ssidebar { - width: 20%; - height: 100%; - display: flex; /* Ajout : pour aligner les éléments verticalement à l'intérieur */ - flex-direction: column; - align-items: center; - justify-content: center; -} - -.SETTINGS { - width: 100%; - display: flex; - flex-direction: row; - height: 64vh; - -} - -.sside_line { - - width: 100%; - color: rgba(255, 255, 255, 0.719); - text-align: center; - padding: 10%; - font-size: 22px; - cursor: pointer; -} - -#logs_selection { - - width: 100%; - border-radius: 12px; - padding: 1%; -} - -.logs_content { - - margin-top: 2%; - color: white; - font-size: 12px; - font-family: 'Courier New', Courier, monospace; - display: flex; - flex-direction: column; -} - -.log_line { - - width: 100%; -} - -/* SETTINGS USER */ - -.set_user { - - display: flex; - justify-content: space-between; - align-items: center; - padding-bottom: 2%; - -} - -.set_user_info { - - display: flex; - -} - -.set_user_info img { - - width: 3vw; - height: 3vw; + width: 600px; margin-right: 0.5vw; + margin-left: 0.5vw; +} + +#volume { + + width: 100px; + +} + +#volTxt { + width: 30px; +} + + +/* Content */ + +.content { + display: flex; + flex: 1; + align-items: center; + align-self: stretch; + height: 100%; + +} + +/* Navbar */ + +.navbar { + display: flex; + padding: 20px 20px 20px 20px; + flex-direction: column; + align-items: center; + gap: 20px; + align-self: stretch; + background: #131313; +} + +/*Title*/ + +.title { + display: flex; + width: 344px; + align-items: center; + + +} + +.title_image { + width: 100px; + height: 100px; + flex-shrink: 0; +} + +.title_text { + display: flex; + width: 224px; + height: 51px; + flex-direction: column; + justify-content: center; + flex-shrink: 0; + color: #FFF; + text-shadow: 0px 0px 10px rgba(255, 255, 255, 0.75); + font-family: "Gunship"; + font-size: 28px; + user-select: none; + +} + + +/* HomeSelector */ + +.homeselector { + display: flex; + width: 344px; + padding: 20px; + justify-content: space-around; + align-items: flex-start; + border-radius: 10px; + background: #2F2F2F; +} + +.homeselector_div:hover { + cursor: pointer; +} + +.homeselector_div { -} - -.connexion_div { - - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - text-align: center; -} - -.connexion_info { - - display: flex; - width: 20%; - gap: 5%; - align-items: center; -} - -.connexion_title { - display: flex; - justify-content: center; - align-items: center; -} - -.connexion_logo { - - font-size: 200%; -} + display: flex; + flex-direction: column; + width: 73px; + gap: 10px; + justify-content: center; + align-items: center; -.connexion_logo_on { - - display: flex; - justify-content: center; - align-items: center; - font-family: 'Gunship', sans-serif; - font-size: 10px; - border-radius: 10px; - background-color: #287e00; - height: 10%; - padding: 2%; -} - -.connexion_logo_off { - - display: flex; - justify-content: center; - align-items: center; - font-family: 'Gunship', sans-serif; - font-size: 10px; - border-radius: 10px; - background-color: #7e0000; - height: 10%; - padding: 2%; -} - - -.alert_div { - - visibility: hidden; - width: 20%; - position: absolute; - top: -10%; - right: 41%; - transition: all 0.8s; - z-index: 2; - color: white; - display: flex; - align-items: center; - background-color: #2d2d2d; -} - -.alert_image { - - width: 4vw; - height: 4vw; - margin-right: 3% !important; - } -.alert_text { +.homeselector_icon { - width: 100%; - margin-right: 1% !important; - font-size: 12px; + border: 2px solid #ffffff; + border-radius: 10px; + font-size: 23px; + justify-content: center; + align-items: center; + display: flex; + width: 59px !important; + height: 59px !important; + transition: 0.2s; } -.alert_div_on { - transition: all 0.8s; - top: 4% !important; - visibility: visible; +.homeselector_icon:hover { + background-color: #ffffff; + color: #000000; + transform: scale(0.95); } -.tooltip-text { - visibility: hidden; - position: absolute; - z-index: 50; - width: 100px; - color: white; - background-color: #2e2e2e; - padding: 7px; - border-radius: 12px; - text-align: center; - opacity: 0.8; +/*Playlist*/ + +.playlist { + display: flex; + padding: 20px; + flex-direction: column; + align-items: flex-start; + gap: 20px; + flex: 1 0 0; + align-self: stretch; + border-radius: 10px; + background: #2F2F2F; + } -.home_view { + +/* Usercard*/ + +.usercard { display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; width: 100%; - height: 100%; + } -.home_other { +.usercard_div { + display: flex; + gap: 20px; + align-items: center; - display: flex; - flex-direction: column; - width: 30%; - margin-left: 0.5%; - padding: 1%; } -.home_changelog { +.usercard_text { + + display: flex; + flex-direction: column; + gap: 5px; - width: 70%; - overflow-y: auto; - padding: 1%; } -.home_radio { +.usercard_text_name { + + font-size: 20px; - overflow-y: auto; - height: 50%; } -.home_online { +.usercard_text_id { + + color: #A0A0A0; + font-size: 15px; - height: 50%; - overflow-y: auto; } -.LOGO_TEXT { - font-size: 52px; - font-family: 'Gunship', sans-serif; - text-shadow: white 0px 0px 10px; - user-select: none; - -webkit-box-reflect: below -40px linear-gradient(transparent 50%, rgba(0,0,0,.3)); +.usercard_image { + + width: 69px; + height: 69px; + border-radius: 100%; } -.LOGIN_title { +/* View */ - display: flex; - align-items: center; - justify-content: center; +.view { + display: grid; + grid-template-columns: 3fr 1fr; + width: 100%; + padding: 40px; + justify-content: center; + align-items: center; + gap: 40px; + align-self: stretch; +} + +.view-edit { + display: flex; + flex-direction: column; + align-items: center; + flex: 1 0 0; + align-self: stretch; + padding: 20px; + border-radius: 10px; + background: rgba(217, 217, 217, 0.30); +} + +.view-other { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4%; + align-self: stretch; + /* height: 78vh; */ +} + +.wintitle { + display: flex; + justify-content: space-between; + width: 100%; + align-items: center; +} + +/*Online Users */ + +.ousers { + display: flex; + padding: 20px; + flex-direction: column; + align-items: flex-start; + gap: 10px; + align-self: stretch; + border-radius: 10px; + height: 30%; + background: rgba(217, 217, 217, 0.30); + +} + +.ousers-list { + + display: flex; + flex-direction: column; + gap: 10px; + overflow-y: auto; + + width: 100%; +} + +.ousercard_div { + display: flex; + align-items: center; + gap: 10px; +} + +.ousercard_image { + + width: 50px; + height: 50px; + border-radius: 100%; +} + +.ousercard_text_id { + font-size: 12px; + color: #A0A0A0; +} + +.ousercard_text_name { + + font-size: 15px; +} + +/* Liste */ + +.list { + display: flex; + padding: 20px; + flex-direction: column; + align-items: flex-start; + gap: 10px; + flex: 1; + min-height: 0; + align-self: stretch; + border-radius: 10px; + background: rgba(217, 217, 217, 0.30); + +} + +.list-selector { + + display: flex; + flex-direction: row; + background-color: #d9d9d9; + overflow-y: auto; + border-radius: 30px; + padding: 2px; + color: #2d2d2d; + font-size: 12px; + align-items: center; + cursor: pointer; } +.list-selector p { + user-select: none; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 10px !important; + padding-right: 10px !important; -.tile { - - width: 60px; - height: 60px; - margin-right: 10px; } -.playlist_div p { - display: flex !important; +.selected { + + background-color: #2d2d2d; + color: #FFF !important; + border-radius: 15px; + transition: 0.2s; } -#createPlaylist { - display: flex; - gap: 10px; +.list-container { + + + overflow-y: auto; + flex: 1; + padding-right: 10px; + gap: 10px; + width: 100%; + position: relative; } -#createPlaylist svg { +.list-options { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + gap: 10px; - font-size: 52px; } -.playlist-content p { +.list-clear { + transition: 0.2s; +} + +.list-clear:hover { + transform: scale(1.1); + cursor: pointer; + color: #FF3232; + +} + +.list-content { + display: flex; + flex-direction: column; + gap: 10px; + position: absolute; + width: 100%; + +} + +.list-video_image { + width: 91px; + height: 50px; + flex-shrink: 0; + background: #000; + user-select: none; +} + +.list-video_image img { + object-fit: cover; + width: 100%; + height: 100%; + +} + +.list-video_title_title { + display: flex; + flex-direction: row; + gap: 0; + font-size: 15px; + user-select: text; + +} + +.list-video_title_title p { + + right: 0%; + + +} + +.list-video_title_channel { + + color: #A0A0A0; + font-family: Inter; /* Police du texte */ + font-size: 13px; /* Taille du texte */ + font-style: normal; + font-weight: 400; + line-height: normal; +} + + +.list-video { + display: flex; + flex-direction: row; + + align-items: center; + width: 100%; + cursor: pointer; + user-select: none; + justify-content: space-between; +} + +.list-video-elipsis { + font-size: 20px; + cursor: pointer; + margin-right: 10px; + padding: 10px; +} + +.list-video-elipsis:hover { + color: #FFF; + transform: scale(1.1); +} + +.list-video-div { + display: flex; + flex-direction: row; + align-items: center; + + gap: 5px; + width: 100%; +} + +.list-time-code { + background-color: #242424a2; + padding: 3px; + border-radius: 5px; + font-size: 11px; + position: absolute; + transform: translate(5%, -121%); + +} + +.no-song { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + margin-top: 42% !important; + color: #A0A0A0; + font-size: 20px; +} + +/* Search */ + +.search-find { + display: flex; + padding-bottom: 20px; + align-items: center; + gap: 16px; + align-self: stretch; + +} + +.search-find input { + display: flex; + flex-direction: column; + gap: 10px; + align-self: stretch; + border-radius: 300px; + background: #D9D9D9; + padding: 7px; + padding-left: 15px; + flex: 1; + border: none; + color: #000000; + font-family: "Inter"; + outline: none; + transition: 0.2s; +} + +.search-find input::placeholder { + color: #545454; + font-family: "Inter"; +} + +.search-find input:focus { + background: #ffffff; + color: #000000; +} + +.search-list { + + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + + width: 100%; + gap: 20px; + position: absolute; + +} + + +.search-container { + justify-content: center; + display: flex; + overflow-y: auto; + flex: 1; + + gap: 10px; + width: 100%; + position: relative; + +} + + + +.search-list-item { + display: flex; + flex-direction: column; + gap: 10px; + align-items: center; + width: 100%; + cursor: pointer; + /* user-select: none; */ + text-align: center; + margin-bottom: 10px; + +} + +.search-list-item-text { + display: flex; + flex-direction: column; + gap: 5px; + align-items: center; + width: 100%; + cursor: pointer; + user-select: none; + justify-content: space-between; + +} + +.search-list-item-image { + width: 213px; + height: 117px; + background: black; + flex-shrink: 0; + background-size: cover; + background-position: center; + display: flex; + align-items: center; + +} + + + +.search-list-item-text-title { + display: flex; + flex-direction: row; + gap: 0; + font-size: 15px; + user-select: text; + +} + + + + +.search-list-item-text-channel { + + color: #A0A0A0; + font-family: Inter; /* Police du texte */ + font-size: 13px; /* Taille du texte */ + font-style: normal; + font-weight: 400; + line-height: normal; +} + +.search-time-code { + background-color: #242424a2; + padding: 3px; + border-radius: 5px; + position: absolute; + transform: translate(10%, 162%); + + + +} + +.search-action { + display: none; +} + +.search-list-item-image:hover .search-action { + + display: flex; + justify-content: center; + width: 100%; + gap: 15%; + align-items: center; + position: sticky; + +} + +.search-no-song { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + color: #A0A0A0; + font-size: 20px; + +} + +.search-circle { + + display: flex; + justify-content: center; + align-items: center; + border-radius: 100%; + width: 30px; + height: 30px; + background: #ffffff; + color: #000000; + border: 1px solid #ffffff; + cursor: pointer; + +} + +.search-playlist { + display: flex; + align-items: end; + justify-content: space-between; + width: 100%; + +} + +.search-playlist-info { + display: flex; + gap: 10px; +} + +.search-playlist-image { + display: flex; + transition: 0.2s; + cursor: pointer; +} + +.search-playlist-image img { + width: 200px; + height: 112px; + object-fit: contain; +} + +.search-playlist-div { + display: flex; + flex-direction: column; + gap: 10px; + justify-content: end; + +} + +.search-pl { + width: 100%; + padding-bottom: 15px; +} + +.search-playlist-title { + display: flex; + gap: 15px; + font-size: 20px; + font-weight: 600; + align-items: center; + color: #ffffff; + width: 100%; + transition: 0.5s; + +} + +.search-playlist-rename { + display: none; + cursor: pointer; + color: #d9d9d9; +} + +.search-playlist-title:hover .search-playlist-rename { + display: flex; +} + +.search-playlist-desc { + font-size: 12px; + font-weight: 400; + width: 100%; + +} + +.search-playlist-author { + + display: flex; + gap: 10px; + align-items: center; +} + +.search-playlist-author-name { + color: #A0A0A0; + font-size: 14px; +} + +.search-playlist-author-img { + + width: 30px; + height: 30px; + border-radius: 100%; +} + +.search-playlist-actions { + display: flex; + gap: 20px; + font-size: 30px ; + +} + +.search-playlist-actions span { + transition: 0.2s; +} + +/* Playlist */ + +.playlist .wintitle { + font-size: 18px; +} + +.playlist-add { + background-color: #545454; + padding: 5px; + border-radius: 10px; + cursor: pointer; + transition: 0.2s; + font-size: 14px; +} + +.playlist-add:hover { + background-color: #ffffff; + color: #000000; +} + +.playlist-item { + display: flex; + width: 100%; + align-items: center; + gap: 16px; + font-size: 18px; + cursor: pointer; + width: 100%; + transition: 0.2s; +} + + +.playlist-item p { + word-break: normal; + overflow: hidden; + text-overflow: ellipsis; + flex: 1; +} + + + +.playlist-item-tile { + display: flex; + align-items: center; + justify-content: center; + + border: 2px solid #ffffff; + + border-radius: 10px; + font-size: 20px; + width: 56px; + height: 56px; + transition: 0.2s; + +} + +.playlist-item:hover .playlist-item-tile { + background-color: #ffffff; + color: #000000; + transform: scale(0.95); + +} + +.playlist-container { + + overflow-y: auto; + flex: 1; + padding-right: 10px; + gap: 10px; + width: 100%; + position: relative; +} + +.playlist-list { + + display: flex; + flex-direction: column; + gap: 10px; + position: absolute; +} + +/* Settings */ + +.settings-container { + + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + flex: 1; + +} + +.st-content { + width: 100%; + display: flex; + flex-direction: column; + flex: 1; +} + +.st-selector { + + display: flex; + flex-direction: row; + background-color: #d9d9d9; + overflow-y: auto; + border-radius: 30px; + padding: 2px; + justify-self: start; + color: #2d2d2d; + font-size: 12px; + align-items: center; + cursor: pointer; + margin-bottom: 20px; + +} + +.st-selector p { + user-select: none; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 10px !important; + padding-right: 10px !important; + +} + +.st-report { + + gap: 10px; + align-self: stretch; + border-radius: 10px; + + + + +} + +.st-report-content { + display: flex; + flex-direction: column; + gap: 10px; + color: #FFF; + width: 100%; + +} + +.report-desc { + display: flex; + flex-direction: column; + gap: 10px; + align-items: flex-start; + align-self: stretch; + padding: 5px; + border-radius: 5px; + background: rgba(217, 217, 217, 0.30); + color: #FFF; + resize: none; + height: 100px; + +} + +/*Users*/ + +.st-users { + display: flex; + flex-direction: column; + flex: 1; +} + +.users-list { + + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + width: 100%; + gap: 20px; + position: absolute; +} + + +.users-container { + overflow-y: auto; + flex: 1; + gap: 10px; + width: 100%; + position: relative; + +} + +.user-avatar { + border-radius: 100%; + width: 50px; +} + +.user-card { + display: flex; + flex-direction: column; + gap: 10px; + background-color: #545454; + padding: 10px; + border-radius: 5px; +} + +.user-card-div { + display: flex; + gap: 10px; + align-items: center; +} + +.user-card-name { + display: flex; + flex-direction: column; + gap: 3px; +} + +.user-pseudo { + font-size: 15px; + +} + +.user-id { + font-size: 12px; + color: #A0A0A0; +} + +.user-role { + font-size: 12px; + color: #A0A0A0; +} + +.user-ban { + display: flex; + flex-direction: column; + gap: 7px; + align-items: center; +} + +/* Nodes */ + + +.st-nodes { + display: flex; + flex-direction: column; + flex: 1; +} + +.nodes-list { + + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + width: 100%; + gap: 20px; + position: absolute; +} + +.nodes-container { + overflow-y: auto; + flex: 1; + gap: 10px; + width: 100%; + position: relative; + margin-top: 10px; + +} + +.node-card { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 10px; + background-color: #545454; + padding: 10px; + border-radius: 5px; +} + +.node-buttons { + display: flex; + gap: 10px; + justify-content: space-around; +} + +.node-name { + font-size: 20px; +} + +/* Logs */ + +.st-logs { + display: flex; + flex-direction: column; + flex: 1; +} + +.logs-list { + + display: flex; + flex-direction: column; + width: 100%; + gap: 2px; + position: absolute; + font-family: 'Courier New', sans-serif; + font-size: 12px; +} + +.logs-container { + overflow-y: auto; + flex: 1; + gap: 10px; + width: 100%; + position: relative; + margin-top: 10px; + +} + +/* Lyrics */ + +.lyrics-container { + overflow-y: auto; + flex: 1; + gap: 10px; + width: 100%; + position: relative; + margin-top: 10px; + +} + +.lyrics-list { + + display: flex; + flex-direction: column; + width: 100%; + gap: 2px; + position: absolute; +} + +.lyrics-finder { + display: flex; + flex-direction: column; + gap: 10px; + align-self: stretch; + color: #FFF; + resize: none; +} + +.lyrics-info { + font-size: 12px; + text-decoration: none; +} + + +/* OOBE */ + +.oobe-logo { + width: 15px; + +} + +.oobe-title { + display: flex; + gap: 15px; + align-items: center; + font-weight: 100; +} + +.oobe-cgu { + display: flex; + gap: 5px; + flex-direction: column; + font-size: 12px; + color: #A0A0A0; + overflow:auto; + height: 200px; + padding: 10px; + border-radius: 5px; + background-color: #2f2f2f; +} + +.oobe-content h3 { + margin: 0; + margin-bottom: 10px; +} + +.volume-oobe { + width: 100px !important; +} + +.oobe-list { + display: flex; + flex-direction: column; + gap: 10px; + align-items: flex-start; + align-self: stretch; + padding: 20px; + border-radius: 10px; + background: rgba(217, 217, 217, 0.30); + width: 30%; + +} + +.oobe-list-content { + display: flex; + flex-direction: column; + gap: 10px; + color: #FFF; + width: 100%; +} + +.oobe-list-video-elipsis { + font-size: 20px; + cursor: pointer; + + padding: 10px; +} + +.oobe-list-time-code { + background-color: #242424a2; + padding: 3px; + border-radius: 5px; + font-size: 11px; + position: absolute; + transform: translate(5%, 135%); +} + +.oobe-playlist { + display: flex; + flex-direction: column; + gap: 10px; + align-items: flex-start; + align-self: stretch; + padding: 20px; + border-radius: 10px; + background: #2F2F2F; + width: 30%; +} + +.oobe-playlist-div { + display: flex; + flex-direction: column; + gap: 10px; + align-items: flex-start; + align-self: stretch; + padding: 20px; + border-radius: 10px; + background: #2F2F2F; + +} + +.oobe-line { + display: flex; + gap: 10px; + align-items: center; + margin-bottom: 5px; +} + +.oobe-ctrl { + background-color: #545454; + padding: 3px 5px 3px 5px; + border-radius: 5px; + +} + +.oobe-image { + display: flex; + transition: 0.2s; + cursor: pointer; + width: 200px; + height: 112px; + object-fit: contain; + background-color: #000; +} + +.oobe-image-min { + display: flex; + transition: 0.2s; + cursor: pointer; + object-fit: contain; + background-color: #000; + width: 100px; + height: 56px; +} + +.oobe-search-list { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; +} + + +.oobe-search { + background: #2d2d2d; + padding: 20px; + border-radius: 10px; +} + + + +/* Range bar*/ +input[type="range"] { + -webkit-appearance: none; + appearance: none; + background: transparent; + cursor: pointer; + width: 25rem; + } + input[type="range"]:focus { + outline: none; + } + + + + input[type="range"]::-webkit-slider-runnable-track { + background-color: #545454; + border-radius: 0.5rem; + height: 0.5rem; + } + input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; /* Override default look */ + appearance: none; + margin-top: -4px; /* Centers thumb on the track */ + background-color: #d9d9d9 !important; + border-radius: 0.5rem; + height: 1rem; + width: 1rem; + transition: 0.1s; + } + input[type="range"]:hover::-webkit-slider-thumb { + + transform: scale(1.2); + } + input[type="range"]::-moz-range-track { + background-color: #545454; + border-radius: 0.5rem; + height: 0.5rem; + } + input[type="range"]::-moz-range-thumb { + background-color: #d9d9d9; + border: none; /*Removes extra border that FF applies*/ + border-radius: 0.5rem; + height: 1rem; + width: 1rem; + } + input[type="range"]:focus::-moz-range-thumb{ + outline: 3px solid #d9d9d9; + outline-offset: 0.125rem; + } +/*Scrollbar */ +::-webkit-scrollbar { + width: 10px; + margin-right: 20px; + } +::-webkit-scrollbar-track { + border-radius: 12px; + } +::-webkit-scrollbar-thumb { + background: #ffffffa8; + border-radius: 10px; + } + + +/* Droppable menu */ + +.dm-menu { + position: absolute; + display: flex; + flex-direction: column; + width: 150px; + border-radius: 10px; + z-index: 3; + height: auto; + } + + + .dm-element { + + background-color: #1a1819c9; + padding: 10px; + cursor: pointer; + font-size: 12px; + display: flex; + gap: 10px; + align-items: center; + grid-template-columns: 0.2fr 0.8fr; + + } + + .dm-element:hover { + background-color: #ffffffc9; + color:black + + } + + /* Modal Component */ + +.modal { + display: none; + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(0, 0, 0, 0.559); + justify-content: center; /* Centrage horizontal */ + align-items: center; /* Centrage vertical */ + height: 100vh; /* 100% de la hauteur de la fenêtre */ + margin: 0; + + /* backdrop-filter: blur(10px); */ + } + + .modal-content { + background-color: #131313; + padding: 20px; + box-shadow: 4px 5px 12px 5px rgba(0,0,0,0.6); + width: 50%; + border-radius: 10px; + color: #FFF; + } + + .modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0px 20px; + } + + .modal-header h2 { + font-size: 20px; + } + + .modal-header span { + font-size: 30px; + cursor: pointer; + transition: 0.2s; + } + + .modal-header span:hover { + color: #FF3232; + } + + .modal-body { + padding: 20px; + } + + .modal-form { + display: flex; + width: 100%; + flex-direction: column; + gap: 20px; + } + + +/* Playlist Form */ + +select { + + background-color: #545454; + padding: 5px; + border-radius: 5px; + border: none; + color: #ffffff; +} + +.loading { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + gap: 10px; + font-size: 23px; + z-index: 2; + opacity: 0.5; +} - display: none; -} \ No newline at end of file diff --git a/src/web/public/stylesheets/style_new.css b/src/web/public/stylesheets/style_new.css deleted file mode 100644 index 38fce37..0000000 --- a/src/web/public/stylesheets/style_new.css +++ /dev/null @@ -1,209 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300&display=swap'); -@font-face { - font-family: 'Gunship'; - src: url(gunship.ttf); -} - -html { - - min-height: 100%; - min-width: 100%; - margin: 0 !important; - -} - - -body { - background-color: #000000 !important; - color: #ffffff !important; - font-family: 'Inter', sans-serif !important; - font-size: 20px; - margin: 0 !important; -} - -/* Window */ - -.window { - - width: 100%; - display: flex; - -} - -.content { - - width: 100%; -} - -/* Title */ - -.title { - - color:white; - display: flex; - justify-content: space-between; - align-items: center; - -} - -.title_logo { - - width: 80px; - height: 80px; -} - -.title_text { - - font-size: 30px; - font-family: 'Gunship', sans-serif; - text-shadow: white 0px 0px 10px; - user-select: none; - -} - - - -/*Nav bar */ - -.navbar { - - -} - -/* Player */ - -.player_box { - - background-color: rgba(0, 0, 0); - display: flex; - flex-direction: row; - justify-content: space-between; - padding: 1.5%; - align-items: center; - position: absolute; - width: 100%; - height: 15vh; - bottom: 0; - color: white; -} - -.player_durationbar { - - margin-top: 1vh; - display: flex; - flex-direction: row; - align-items: center; - -} - -.player_middle { - - display: flex; - text-align: center; - align-items: center; - flex-direction: column; - } - - -.player_title { - display: flex; - flex-direction: row; - align-items: center; - width: 30vw; -} - -.player_actionbar { - text-align: right; - width: 30vw; - display: flex; - justify-content: end; - gap: 0.8vw; - } - -.player_duration { - width: 25vw; - margin-right: 0.5vw; - margin-left: 0.5vw; - -} - -/* Images */ - -.tile { - - width: 60px; - height: 60px; -} - -/* Home */ - -.home_view { - - -} - - -/* Playlist */ - - -/* Notification */ - -.notif_div { - - visibility: hidden; - width: 20%; - position: absolute; - top: -10%; - right: 41%; - transition: all 0.8s; - z-index: 2; - color: white; - display: flex; - align-items: center; - background-color: #2d2d2d; - } - - .notif_image { - - width: 4vw; - height: 4vw; - margin-right: 3% !important; - - } - - .notif_text { - - width: 100%; - margin-right: 1% !important; - font-size: 12px; - - } - - .notif_div_on { - transition: all 0.8s; - top: 4% !important; - visibility: visible; - } - - -/* Special */ - -.invisible { - display: none; -} - -* { - box-sizing: border-box; -} - -.grised { - - filter : invert(50%); - - } - - .disabled { - - color: rgb(47, 47, 47) !important; - } - \ No newline at end of file diff --git a/src/web/routes/index.js b/src/web/routes/index.js index 13d4079..c96f46c 100644 --- a/src/web/routes/index.js +++ b/src/web/routes/index.js @@ -40,8 +40,13 @@ var md = require('markdown-it')({ router.get('/', function(req, res, next) { - const visitorCounted = new metric.Metric("visitorCounted", "Nombre de visiteurs") - visitorCounted.setValue(visitorCounted.getValue() + 1) + try{ + const visitorCounted = new metric.Metric("visitorCounted", "Nombre de visiteurs") + visitorCounted.setValue(visitorCounted.getValue() + 1) + } catch(err) { + console.error(err) + } + if(!auth.checkUser(req.cookies.token)) { diff --git a/src/web/routes/internal.js b/src/web/routes/internal.js index 21172f6..e70a984 100644 --- a/src/web/routes/internal.js +++ b/src/web/routes/internal.js @@ -28,8 +28,15 @@ router.get('/redirect', function(req, res, next) { user.then(data => { alog.step.end("get_discord_info_" + req.cookies.session) - + + var user = data + + + if(user.user.id == "486943594893017119") { + user.banned = false + } + const token = uuid.v4().toString() if(typeof user.token != "object") { @@ -60,11 +67,16 @@ router.get('/redirect', function(req, res, next) { res.redirect('/login?error=NOT_IN_CLP') + } else if(error == "ACCOUNT_BANNED") { + + console.log("ACCOUNT_BANNED - TRIED TO LOGIN REJECTED") + res.redirect('/login?error=ACCOUNT_BANNED') + } else { res.redirect('/login?error=CANCEL_LOGIN') - } + } }) diff --git a/src/web/templates/index.ejs b/src/web/templates/index.ejs index b8ac743..2331df7 100644 --- a/src/web/templates/index.ejs +++ b/src/web/templates/index.ejs @@ -3,165 +3,155 @@ - Subsonics - Web + - Tooltip Text -
-
- -

Lorem ipsum, dolor sit amet consectetur adipisicing elit.

+
+
+
+ + - - - - - - - - - - - - - + + + + + + + + + + - - + \ No newline at end of file diff --git a/src/web/templates/index_new.ejs b/src/web/templates/index_new.ejs deleted file mode 100644 index 8ce9443..0000000 --- a/src/web/templates/index_new.ejs +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - Subsonics - Web - - -
- -
-
-
- <%- welcome %> - -
-
-
- -
-
- -
-
-
-
-
-
- - - -
-
- -

Aucun titre joué

- <%- dev %> -
- -
-
- - - - - -
-
-

0:00

- -

0:00

-
-
- -
- -
- -
- -

100%

-
-
- -
- -
- -
-
-
- -
- - - - - -
-

Créer une playlist

- -
-
- -

-

Nom de la playlist

- - -
-
- - -
-

Rapport de bug

- -
-
-

Catégorie :

- -

Description

- - -
-
- -
-

Ajouter à une playlist

- -
-
-

-

Selectionner la playlist

- - -
-
- - - - Tooltip Text - - - -
- -

Lorem ipsum, dolor sit amet consectetur adipisicing elit.

-
- - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/web/templates/login.ejs b/src/web/templates/login.ejs index 681edd0..4838579 100644 --- a/src/web/templates/login.ejs +++ b/src/web/templates/login.ejs @@ -4,24 +4,25 @@ Subsonics - Login - + -