Version 0.3.0 - Ajout de l'interface Web - First Steps to it

This commit is contained in:
CICD - Pipeline 2023-08-24 22:51:40 +02:00
parent d6fb056096
commit 5b2b444b02
24 changed files with 1233 additions and 43 deletions

1
data/betas.json Normal file
View File

@ -0,0 +1 @@
["486943594893017119","442290526545510421"]

16
package-lock.json generated
View File

@ -6,7 +6,7 @@
"packages": {
"": {
"name": "subsonics-web",
"version": "0.2.2",
"version": "0.2.3",
"dependencies": {
"cookie": "^0.5.0",
"cookie-parser": "^1.4.6",
@ -14,6 +14,7 @@
"ejs": "^3.1.9",
"erela.js": "^2.4.0",
"express": "^4.18.2",
"express-favicon": "^2.0.4",
"nodemon": "^2.0.22",
"socket.io": "^4.6.1",
"uuid": "^9.0.0",
@ -704,6 +705,14 @@
"node": ">= 0.10.0"
}
},
"node_modules/express-favicon": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/express-favicon/-/express-favicon-2.0.4.tgz",
"integrity": "sha512-JDGzumJdwF+WcJf+qwyhdpF1yzducuMCxZa+G6hxR3hor7ae/1CqpAPj8FXCGaGtqBA6ExDMfeszjuYRw5GUuQ==",
"engines": {
"node": ">=4"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -2250,6 +2259,11 @@
"vary": "~1.1.2"
}
},
"express-favicon": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/express-favicon/-/express-favicon-2.0.4.tgz",
"integrity": "sha512-JDGzumJdwF+WcJf+qwyhdpF1yzducuMCxZa+G6hxR3hor7ae/1CqpAPj8FXCGaGtqBA6ExDMfeszjuYRw5GUuQ=="
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",

View File

@ -1,7 +1,7 @@
{
"name": "subsonics-web",
"author": "Raphix",
"version": "0.2.3",
"version": "0.3.0",
"nodemonConfig": {
"ext": "js, html",
"ignore": [
@ -18,6 +18,7 @@
"ejs": "^3.1.9",
"erela.js": "^2.4.0",
"express": "^4.18.2",
"express-favicon": "^2.0.4",
"nodemon": "^2.0.22",
"socket.io": "^4.6.1",
"uuid": "^9.0.0",
@ -26,5 +27,6 @@
"scripts": {
"start": "nodemon src/main.js",
"dev": "set DEV=true& nodemon src/main.js"
}
},
"beta_on": true
}

View File

@ -6,6 +6,7 @@ const { __glob } = require("./global-variables")
const { LogType } = require("../modules/sub-log")
const { List } = require("./sub-list")
const nodeFinder = require("./nodes-finder")
const subplayer = require("./sub-player")
const client = new Client({
intents:[GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers],
@ -13,6 +14,11 @@ const client = new Client({
const membersVoices = new Map()
module.exports.getClient = function () {
return client
}
module.exports.DiscordBot = class {
constructor(config, dlog) {
@ -193,6 +199,9 @@ function startErelaManager(dlog, config) {
plog.log("Nouveau Player instancié dans : " + channel.name)
})
process.emit("MUSIC_UPDATE_STATE")
})
client.manager.on("playerDestroy", (player) => {
@ -202,12 +211,15 @@ function startErelaManager(dlog, config) {
plog.log("Player supprimé dans : " + channel.name)
})
process.emit("MUSIC_UPDATE_STATE")
})
client.manager.on("trackStart", (song) => {
plog.log("Lecture de '" + song.queue.current.title + "' de '" + song.queue.current.author + "'")
list.setCurrent(song)
process.emit("MUSIC_UPDATE_STATE")
})
@ -222,6 +234,9 @@ function startErelaManager(dlog, config) {
}
}
process.emit("MUSIC_UPDATE_STATE")
})
// Emitted whenever a node connects
@ -235,6 +250,7 @@ function startErelaManager(dlog, config) {
})
// THIS IS REQUIRED. Send raw events to Erela.js
client.on("raw", d => client.manager.updateVoiceState(d));
}

View File

@ -5,12 +5,14 @@ const root = path.resolve(__dirname, '../../')
const __glob = {
CONFIG: root + path.sep + "data" + path.sep + "config.json",
USERS: root + path.sep + "data" + path.sep + "users.json",
BETA_USERS: root + path.sep + "data" + path.sep + "betas.json",
ROOT: root,
WEB_DIR: root + path.sep + "src" + path.sep + "web",
COMMANDS: root + path.sep + "src" + path.sep + "commands",
SUBLOG: root + path.sep + "src" + path.sep + "modules" + path.sep + "sub-log.js",
SUBPLAYER: root + path.sep + "src" + path.sep + "modules" + path.sep + "sub-player.js",
SUBLIST: root + path.sep + "src" + path.sep + "modules" + path.sep + "sub-list.js",
DISCORDBOT: root + path.sep + "src" + path.sep + "modules" + path.sep + "discord-bot.js",
PACKAGE: root + path.sep + "package.json",
DATA: root + path.sep + "data" + path.sep,
NODES: root + path.sep + "data" + path.sep + "nodes.json",
@ -21,7 +23,8 @@ const __web = {
ROUTER: webroot + "routes" + path.sep,
PUBLIC: webroot + "public",
TEMPLATES: webroot + "templates"
TEMPLATES: webroot + "templates",
ICON: webroot + "public" + path.sep + "images" + path.sep + "logo.ico"
}
module.exports = { __glob, __web };

View File

@ -1,5 +1,5 @@
const { resolve } = require("path");
const { __glob } = require("../modules/global-variables");
const { __glob, __web } = require("../modules/global-variables");
const { LogType } = require('./sub-log');
const fs = require("fs")
@ -7,6 +7,9 @@ const alog = new LogType("Authentification")
var users = new Map()
var sessions = new Array()
var betausers = new Array()
var packageJson = JSON.parse(fs.readFileSync(__glob.PACKAGE))
updateUsers()
@ -78,12 +81,32 @@ module.exports.getDiscordUser = function (code, session) {
reject("MIGRATE_ACCOUNT_ONLY")
} else {
if(packageJson.beta_on == false) {
user.auth = authorizationKey
Object.assign(user, userInfo)
resolve(user)
} else {
if(betausers.includes(userInfo.user.id)) {
user.beta = true
Object.assign(user, userInfo)
resolve(user)
} else {
reject("NOT_IN_BETA")
}
}
}
@ -173,17 +196,30 @@ module.exports.removeUser = function (token) {
function updateUsers() {
if(!fs.existsSync(__glob.BETA_USERS)){
fs.writeFileSync(__glob.BETA_USERS, '[]')
}
if(!fs.existsSync(__glob.USERS)){
fs.writeFileSync(__glob.USERS, '[]')
}
const userDB = JSON.parse(fs.readFileSync(__glob.USERS))
const betausersDB = JSON.parse(fs.readFileSync(__glob.BETA_USERS))
for (const user of userDB) {
users.set(user.token, user)
}
for (const id of betausersDB) {
betausers.push(id)
}
alog.log("Actualisation de " + userDB.length + " utilisateurs depuis : " + __glob.USERS)
alog.log("Actualisation de " + betausersDB.length + " utilisateurs bêtas depuis : " + __glob.BETA_USERS)
}

View File

@ -14,6 +14,11 @@ module.exports.List = class {
}
getList() {
return next
}
destroy() {
next = new Array()

View File

@ -2,7 +2,9 @@ const { SlashCommandBuilder, EmbedBuilder, DefaultWebSocketManagerOptions } = re
const { __glob } = require("../modules/global-variables");
const { LogType } = require("./sub-log");
const { List } = require("./sub-list")
var ytfps = require("ytfps")
const discord = require("./discord-bot")
var ytfps = require("ytfps");
const list = new List()
@ -71,6 +73,7 @@ module.exports.play = async function (client, interaction) {
}
process.emit("MUSIC_UPDATE_STATE")
}
@ -116,9 +119,29 @@ module.exports.pause = function (client, interaction) {
} else {
// [A FINIR POUR WEB]
if(!client) {
client = discord.getClient()
}
let player = client.manager.players.get("137291455336022018")
if(player) {
if(player.playing) {
player.pause(true)
} else {
player.pause(false)
}
}
}
process.emit("MUSIC_UPDATE_STATE")
}
module.exports.getState = function(client, interaction) {
@ -150,6 +173,7 @@ module.exports.getState = function(client, interaction) {
}
}
module.exports.skip = function (client, interaction) {
@ -193,12 +217,41 @@ module.exports.skip = function (client, interaction) {
} else {
// [A FINIR POUR WEB]
if(!client) {
client = discord.getClient()
}
let player = client.manager.players.get("137291455336022018")
if(list.haveSongs()) {
player.stop()
}
}
process.emit("MUSIC_UPDATE_STATE")
}
module.exports.seek = function (data) {
client = discord.getClient()
let player = client.manager.players.get("137291455336022018")
player.seek(data)
process.emit("MUSIC_UPDATE_STATE")
}
module.exports.previous = function (client, interaction) {
if(interaction) {
@ -238,8 +291,91 @@ module.exports.previous = function (client, interaction) {
}
} else {
if(!client) {
client = discord.getClient()
}
let player = client.manager.players.get("137291455336022018")
if(list.havePreviousSongs()){
list.__next_add(player.queue.current)
player.play(list.previous())
}
}
process.emit("MUSIC_UPDATE_STATE")
}
const clog = new LogType("Actualisation")
module.exports.updateMusicState = function (client, action) {
if(!client) {
client = discord.getClient()
}
let player = client.manager.players.get("137291455336022018")
var currentTitle = "null"
const data = {
"playing": 0,
"current":null,
"isOnline": false,
"queue": null,
"loop": false,
"durationNow": null,
"durationAll": null,
"volume": null
}
if(player) {
data["current"] = player.queue.current
if(player.queueRepeat == true) {
data["loop"] = true
}
data["volume"] = player.volume * 10
if(player.queue.current) {
data["durationNow"] = player.position
data["durationAll"] = player.queue.current.duration
currentTitle = player.queue.current.title
}
if(player.playing == true && player.paused == false) {
data["playing"] = 1
} else {
data["playing"] = 0
}
data["queue"] = list.getList();
data["isOnline"] = true
}
if(action == "end") {
data["current"] = null;
data["isOnline"] = false
}
clog.log("Actualisation de tous les clients - Titre : " + currentTitle)
return data
}
// FINI
@ -284,6 +420,8 @@ module.exports.leave = function (client, interaction) {
}
process.emit("MUSIC_UPDATE_STATE")
}

View File

@ -5,7 +5,7 @@ const log = require("./sub-log");
const auth = require("./sub-auth");
const cook = require("cookie")
const wlog = new LogType("Web")
const subplayer = require(__glob.SUBPLAYER);
module.exports.WebServer = class {
constructor() {
@ -23,6 +23,7 @@ function init() {
const path = require('path');
const cookieParser = require('cookie-parser');
const http = require("http");
const favicon = require('express-favicon');
const app = express();
@ -49,7 +50,7 @@ function init() {
app.use('/', indexRouter);
app.use('/login', loginRouter);
app.use("/internal", internalRouter)
app.use(favicon(__web.ICON));
app.use(function (req, res, next) {
next(createError(404));
@ -134,6 +135,14 @@ function IOConnection(io) {
const alog = log.getInstance("Authentification")
process.on("MUSIC_UPDATE_STATE", () => {
const data = subplayer.updateMusicState()
io.sockets.emit("/ALWAYS/MUSIC_STATE", data)
})
io.on("connection", (socket) => {
wlog.log("[SOCKET] - Nouvelle session : " + socket.id)
@ -141,8 +150,11 @@ function IOConnection(io) {
socket.on("disconnect", () => {
wlog.log("[SOCKET] - Fin de session : " + socket.id)
})
// SPECIAL
socket.on("GET/DISCORD_LOGIN_LINK", () => {
@ -160,8 +172,54 @@ function IOConnection(io) {
io.emit("ANSWER/GET/DISCORD_LOGIN_LINK", discordlink )
})
GetRequest(socket, "USER_INFO", () => {
var cookies = socket.handshake.headers.cookie
cookies = cook.parse(cookies)
var token = cookies.token
socket.on("GET/USER_INFO", () => {
const user = auth.getUser(token)
alog.log("Envoi des informations Discord de '" + user.user.username + "' à '" + socket.id + "'" )
socket.emit("ANSWER/GET/USER_INFO",user)
})
GetRequest(socket, "MUSIC_STATE", () => {
var cookies = socket.handshake.headers.cookie
cookies = cook.parse(cookies)
var token = cookies.token
const data = subplayer.updateMusicState()
const user = auth.getUser(token)
socket.emit("ANSWER/GET/MUSIC_STATE", "Bienvenue " + user.user.username + " ! ")
io.sockets.emit("/ALWAYS/MUSIC_STATE", data)
})
GetRequest(socket, "PAUSE", () => {
subplayer.pause()
io.emit("ANSWER/GET/PAUSE", "OK")
})
GetRequest(socket, "BACKWARD", () => {
subplayer.previous()
io.emit("ANSWER/GET/BACKWARD", "OK")
})
GetRequest(socket, "FORWARD", () => {
subplayer.skip()
io.emit("ANSWER/GET/FORWARD", "OK")
})
// SEND REQUEST
socket.on("SEND/SEEK", (data) => {
var cookies = socket.handshake.headers.cookie
@ -173,24 +231,67 @@ function IOConnection(io) {
if(auth.checkUser(token)) {
const user = auth.getUser(token)
alog.log("Envoi des informations Discord de '" + user.user.username + "' à '" + socket.id + "'" )
socket.emit("ANSWER/GET/USER_INFO",user)
subplayer.seek(data)
} else {
io.emit("ANSWER/GET/USER_INFO", {"error":"USER_DONT_EXIST"})
io.emit("ANSWER/SEND/SEEK", {"error":"USER_DONT_EXIST"})
}
} else {
io.emit("ANSWER/GET/USER_INFO", {"error":"TOKEN_NOT_FINDED"})
io.emit("ANSWER/SEND/SEEK", {"error":"TOKEN_NOT_FINDED"})
}
})
})
}
function GetRequest (socket, name, func) {
socket.on("GET/" + name, () => {
var cookies = socket.handshake.headers.cookie
if(cookies) {
cookies = cook.parse(cookies)
var token = cookies.token
if(auth.checkUser(token)) {
func()
} else {
io.emit("ANSWER/GET/" + name, {"error":"USER_DONT_EXIST"})
}
} else {
io.emit("ANSWER/GET/" + name, {"error":"TOKEN_NOT_FINDED"})
}
})
}

View File

@ -0,0 +1,3 @@
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100" height="100" fill="black" />
</svg>

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -15,7 +15,7 @@ function get(request) {
return new Promise((resolve, reject) => {
socket.emit("GET/" + request)
console.log("Envoi de la requête : " + request)
console.log("Envoi de la requête GET : " + request)
socket.once("ANSWER/GET/" + request, (answer) => {
@ -28,3 +28,27 @@ function get(request) {
})
}
function send(request, data) {
return new Promise((resolve, reject) => {
socket.emit("SEND/" + request, data)
console.log("Envoi de la requête SEND : " + request)
socket.once("ANSWER/SEND/" + request, (answer) => {
console.log("Réponse pour la requête : " + request)
resolve(answer)
})
})
}
function getSocket() {
return socket
}

View File

@ -1,8 +1,243 @@
const userInfoDiv = document.getElementById("userInfo")
const userInfoPopup = document.getElementById("userPopup")
const userInfoglobal = document.getElementById("userInfoglobal")
const musicTitle = document.getElementById("music_title")
const musicURL = document.getElementById("music_img")
const durationBar = document.getElementById("duration")
const durationTextAct = document.getElementById("durationTextAct")
const durationTextTotal = document.getElementById("durationTextTotal")
const backward = document.getElementById("backward")
const play = document.getElementById("play")
const forward = document.getElementById("forward")
const settings_dialog = document.getElementById("SETTINGS_dialog")
const settings_close = document.getElementById("SETTINGS_close")
const settingsBtn = document.getElementById("settingsBtn")
const userInfo = get("USER_INFO")
settingsBtn.addEventListener("click", () => {
settings_dialog.showModal()
})
settings_close.addEventListener("click",() => {
settings_dialog.close()
})
var durationAll = 0
var durationProgress = 0
var isPlaying = false
let interval;
durationBar.addEventListener("change", () => {
send("SEEK", durationBar.value)
})
userInfo.then(user => {
userInfoDiv.innerHTML = "<img src='https://cdn.discordapp.com/avatars/" + user.user.id + "/" + user.user.avatar + "'><p>" + user.user.global_name + "</p><p>" + user.user.username + "</p>"
var betastar = ""
if(user.beta) {
betastar = "<p class='beta'>BETA</p>"
}
userInfoDiv.innerHTML = "<div class='INDEX_userInfo_name'><p class='INDEX_gbname'>" + user.user.global_name + "</p><p class='INDEX_usrname'>" + user.user.username + "</p></div><div class='INDEX_picture'><img src='https://cdn.discordapp.com/avatars/" + user.user.id + "/" + user.user.avatar + "'>" + betastar + "</div>"
})
userInfoDiv.addEventListener("click", () => {
userInfoPopup.classList.add("INDEX_userPopup_Visible")
userInfoPopup.classList.remove("INDEX_userPopup")
})
userInfoglobal.addEventListener("mouseleave", () => {
userInfoPopup.classList.add("INDEX_userPopup")
userInfoPopup.classList.remove("INDEX_userPopup_Visible")
})
get("MUSIC_STATE").then(data => {
console.log(data)
})
play.addEventListener('click', () => {
get("PAUSE")
})
backward.addEventListener('click', () => {
get("BACKWARD")
})
forward.addEventListener("click", () => {
get("FORWARD")
})
socket.on("/ALWAYS/MUSIC_STATE", (data) => {
stopInterval()
console.log(data)
durationAll = 0
durationProgress = 0
isPlaying = false
if(data.current == null) {
musicURL.innerHTML = '<img class="showPicture" src="images/black-image.svg">'
musicTitle.innerHTML = "<p>Aucun titre joué</p>"
} else {
musicURL.innerHTML = '<img class="showPicture" src="' + data.current.thumbnail + '">'
musicTitle.innerHTML = "<p>" + data.current.title + "</p>"
}
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 = '<i class="fas fa-pause"></i>'
isPlaying = true
startInterval()
} else {
play.innerHTML = '<i class="fas fa-play"></i>'
isPlaying = false
}
if(data.current && data.playing == 0) {
setTime()
}
})
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
}

Binary file not shown.

View File

@ -0,0 +1,451 @@
@font-face {
font-family: 'Gunship';
src: url(Gunship.ttf);
}
html {
min-height: 100%;
min-width: 100%;
margin: 0;
}
body {
background-color: black;
color: white;
font-family: 'Roboto', sans-serif;
background: linear-gradient(90deg, rgba(76,72,140,1) 0%, rgba(0,0,0,1) 100%),
linear-gradient(90deg, rgb(101, 95, 185) 0%, rgb(48, 48, 48) 100%);
}
/*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: 60px;
height: 60px;
}
.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 {
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: none;
}
.INDEX_userPopup_Visible {
display: flex;
flex-direction: column;
background-color: #2e2e2e;
margin-top: 20px;
font-size: 12px;
text-align: center;
color: white;
}
#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(155, 155, 155);
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%;
bottom: 0;
color: white;
}
.PLAYER_middle {
display: flex;
text-align: center;
align-items: center;
flex-direction: column;
}
p {
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;
}
.third {
color: rgb(47, 47, 47);
background-color: transparent;
border: none;
border-radius: 100%;
text-shadow: 1px 1px 10px white;
font-size: 0.9vw;
margin-left: 0.8vw;
}
.primary {
display: inline-block;
background-color: #ffffff;
color: rgb(0, 0, 0);
border: none;
border-radius: 100%;
width: 50px;
height: 50px;
font-size: 1vw;
}
.primary:active {
scale: 0.95;
}
.secondary {
color: rgb(178, 178, 178);
border: none;
background-color: transparent;
width: 50px;
height: 50px;
font-size: 1vw;
}
.secondary:hover {
color: white;
}
.showPicture {
margin: 0 !important;
margin-bottom: 10px;
width: 4vw;
height: 4vw;
}
.title {
width: 100%;
}
.PLAYER_actionbar {
text-align: right;
width: 30vw;
}
.grised {
filter : invert(50%);
}
/*SETTINGS*/
.SETTINGS_dialog {
width: 40vw;
height: 25vw;
padding: 0;
background: linear-gradient(90deg, #515151 0%, #2e2e2e 100%);
border: none;
border-radius: 12px;
}
.SETTINGS_content {
display: flex;
width: 100%;
flex-direction: row;
}
.ssidebar {
width: 12vw;
position: sticky;
height: 25vw;
background-color: #2d2d2d;
border-radius: 12px 0 0 12px;
display: flex; /* Ajout : pour aligner les éléments verticalement à l'intérieur */
flex-direction: column; /* Ajout : pour aligner les éléments verticalement à l'intérieur */
}
.scontent {
flex: 1;
padding: 1vw;
border-radius: 0 12px 12px 0;
}
.slineclose {
width: 100%;
text-align: right;
}
.SETTINGS_close {
}
.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(300%);
background-color: rgb(48, 5, 77);
}
.INDEX_picture {
padding-left: 10%;
display: flex;
flex-direction: column;
text-align: center;
}
.SETTINGS_close {
color: red;
background-color: transparent;
border-radius: 50vw;
border-color: red;
border-style: solid;
padding: 5px;
width: 40px;
height: 40px;
transition: all 0.2s ease 0s;
}
.SETTINGS_close:hover {
color: white;
background-color: red;
cursor: pointer;
}

View File

@ -18,4 +18,5 @@ router.get('/', function(req, res, next) {
});
module.exports = router;

View File

@ -44,10 +44,16 @@ router.get('/redirect', function(req, res, next) {
alog.step.error("get_discord_info_" + req.cookies.session)
console.log(error)
if(error == "MIGRATE_ACCOUNT_ONLY") {
res.redirect('/login?error=MIGRATE_ACCOUNT_ONLY')
} else if(error == "NOT_IN_BETA") {
res.redirect('/login?error=NOT_IN_BETA')
} else {
res.redirect('/login?error=CANCEL_LOGIN')

View File

@ -21,7 +21,39 @@ router.get('/', function(req, res, next) {
}
res.render("login")
var error = ""
if(req.query.error == "CANCEL_LOGIN") {
error = "<p style='color:red; margin-bottom: 0.5vw !important;'>Une erreur est survenue lors de l'authentification !</p>"
}
if(req.query.error == "MIGRATE_ACCOUNT_ONLY") {
error = "<p style='color:red; margin-bottom: 0.5vw !important;'>Uniquement les comptes migrés sont accéptés !</p>"
}
if(req.query.error == "IS_NOT_IN_CLP") {
error = "<p style='color:red; margin-bottom: 0.5vw !important;'>Que fais-tu là ? Seul les membres du CLP peuvent contrôler le Bot</p>"
}
if(req.query.error == "ACCOUNT_BANNED") {
error = "<p style='color:red; margin-bottom: 0.5vw !important;'>Ton compte a été banni !</p>"
}
if(req.query.error == "NOT_IN_BETA") {
error = "<p style='color:red; margin-bottom: 0.5vw !important;'>Demande à Raphix pour t'inscrire à la Beta !</p>"
}
res.render("login", {login: error})
}
});

View File

@ -1,11 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<html>
<head>
<title>Subsonics - Error</title>
</head>
<body>
<h1>ERROR !</h1>
</body>
<link rel='stylesheet' href='/stylesheets/style.css'/>
<style>
body {
padding: 2%;
}
div {
background-color: rgb(32, 32, 32);
border-radius: 1vw;
padding: 2%;
}
button {
color: red;
background-color: transparent;
border-radius: 1vw;
border-color: red;
border-style: solid;
padding: 10px;
transition: all 0.2s ease 0s;
}
button:hover {
color: white;
background-color: red;
cursor: pointer;
}
</style>
</head>
<body>
<div>
<h1>Erreur</h1>
<h2><%= message %> - <%= error.status %></h1>
<pre><%= error.stack %></pre>
</div>
<br>
<a href="/"><button>Revenir au concert</button></a>
</body>
</html>

View File

@ -7,11 +7,83 @@
<title>Subsonics - Web</title>
</head>
<body>
<h1>Subsonics</h1>
<div id="userInfo"></div>
<a href="/internal/logout"><button>Disconnect</button></a>
<div class="INDEX_Content">
<div class="INDEX_title">
<div class=" LOGIN_title">
<img class="LOGIN_logopng" src="/images/logo.png">
<img src="/images/title.png">
</div>
<div id="userInfoglobal">
<div class="INDEX_userInfo" id="userInfo"></div>
<div class="INDEX_userPopup" id="userPopup">
<div id="settingsBtn" class="INDEX_line"><i class="fa-solid fa-wrench"></i> Paramètres</div>
<a class="INDEX_signout" href="/internal/logout"><i class="fa fa-sign-out " aria-hidden="true"></i> Déconnexion</a>
</div>
</div>
</div>
</div>
<div class="PLAYER_box">
<div class="PLAYER_title">
<span id="music_img"><img class="showPicture" src="/images/black-image.svg"></span>
<span id="music_title" class="title"><p>Aucun titre joué</p></span>
</div>
<div class="PLAYER_middle">
<div class="playbar">
<button id="backward" class="secondary"><i class="fas fa-step-backward"></i></button>
<button id="play" class="primary"><i class="fas fa-play"></i></button>
<button id="forward" class="secondary"><i class="fas fa-step-forward"></i></button>
</div>
<div class="PLAYER_durationbar">
<p id="durationTextAct" class="durationText">0:00</p>
<input id="duration" type="range" value="0" max="100">
<p id="durationTextTotal" class="durationText">0:00</p>
</div>
</div>
<div class="PLAYER_actionbar">
<button id="heart" class="third"><i class="fa fa-heart"></i></button>
<button id="vol" class="third"><i class="fa fa-volume-up"></i></button>
<button id="loop" class="third"><i class="fa fa-retweet"></i></button>
<button id="shuffle" class="third"><i class="fa fa-shuffle"></i></button>
<button id="list" class="list third"><i class="fa fa-list-ol"><p class="number" id="listNumber"></p></i></button>
</div>
</div>
<dialog class="SETTINGS_dialog" id="SETTINGS_dialog">
<div class="SETTINGS_content">
<div class="ssidebar">
<h2 style=" padding: 1vw; position: absolute;" class="dialogTitle"><i class="fa fa-wrench"></i> Paramètres</h2>
<div class="ssidebar_content">
<div class="ssidebar_line"><i class="fa-solid fa-newspaper"></i> Logs</div>
<div class="ssidebar_line"><i class="fa-solid fa-tower-cell"></i> Connexions</div>
<div class="ssidebar_line"><i class="fa-solid fa-people-group"></i> Gestion d'accès</div>
<div class="ssidebar_line"><i class="fa-solid fa-shield"></i> Bêta</div>
</div>
</div>
<div class="scontent">
<div class="slineclose">
<button id="SETTINGS_close" class="SETTINGS_close"><i class="fa-solid fa-xmark"></i></button>
</div>
<p style="color: red; font-size: 72px; text-align: center; font-family: 'Gunship', sans-serif;" >NOT WORKING</p>
</div>
</div>
</dialog>
<script src="/socket.io/socket.io.js"></script>
<script src="/javascript/IO.js"></script>
<script src="/javascript/__index_script.js"></script>
<script defer src="https://use.fontawesome.com/releases/v6.4.2/js/all.js" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</body>
</html>

View File

@ -4,14 +4,26 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Subsonics - Login</title>
<link rel='stylesheet' href='/stylesheets/style.css'/>
</head>
<body>
<h1>Subsonics Login</h1>
<button id="loginBtn">Connexion</button>
<p>Fait avec le 💖 par Raphix</p>
<div class="LOGIN_box">
<div class="LOGIN_title">
<img class="LOGIN_logopng" src="/images/logo.png">
<img src="/images/title.png">
</div>
<h2 class="LOGIN_Connexion">Connexion</h2>
<%- login %>
<button class="LOGIN_DiscordBtn" id="loginBtn"><img src="/images/discord-logo-white.png"></button>
<p style="padding: 20px;">Fait avec le 💖 par Raphix</p>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="/javascript/IO.js"></script>
<script src="/javascript/__login_script.js"></script>
<script defer src="https://use.fontawesome.com/releases/v6.4.2/js/all.js" crossorigin="anonymous"></script>
</body>
</html>