mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 13:04:23 +00:00
basically done
This commit is contained in:
@@ -14,6 +14,9 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<script>
|
||||||
|
localStorage.setItem( 'music-player-config', 'sse' );// Or 'ws'
|
||||||
|
</script>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
<span class="material-symbols-outlined move-icon" @click="moveSong( song.id, 'down' )" title="Move song down" v-if="canBeMoved( 'down', song.id )">arrow_downward</span>
|
<span class="material-symbols-outlined move-icon" @click="moveSong( song.id, 'down' )" title="Move song down" v-if="canBeMoved( 'down', song.id )">arrow_downward</span>
|
||||||
<h3 class="song-title">{{ song.title }}</h3>
|
<h3 class="song-title">{{ song.title }}</h3>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" placeholder="Additional information for remote display" v-model="song.additionalInfo">
|
<input type="text" placeholder="Additional information for remote display" v-model="song.additionalInfo" @focusin="kbControl( 'on' )" @focusout="kbControl( 'off' )">
|
||||||
<p class="playing-in">{{ getTimeUntil( song ) }}</p>
|
<p class="playing-in">{{ getTimeUntil( song ) }}</p>
|
||||||
</div>
|
</div>
|
||||||
<button @click="deleteSong( song.id )" class="small-buttons" title="Remove this song from the queue" v-if="canBeMoved( 'down', song.id ) || canBeMoved( 'up', song.id )"><span class="material-symbols-outlined">delete</span></button>
|
<button @click="deleteSong( song.id )" class="small-buttons" title="Remove this song from the queue" v-if="canBeMoved( 'down', song.id ) || canBeMoved( 'up', song.id )"><span class="material-symbols-outlined">delete</span></button>
|
||||||
@@ -43,6 +43,9 @@
|
|||||||
import type { AppleMusicSongData, ReadFile, Song } from '@/scripts/song';
|
import type { AppleMusicSongData, ReadFile, Song } from '@/scripts/song';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import searchView from './searchView.vue';
|
import searchView from './searchView.vue';
|
||||||
|
import { useUserStore } from '@/stores/userStore';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const search = ref( searchView );
|
const search = ref( searchView );
|
||||||
const props = defineProps( {
|
const props = defineProps( {
|
||||||
@@ -83,6 +86,14 @@
|
|||||||
return pl;
|
return pl;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
const kbControl = ( action: string ) => {
|
||||||
|
if ( action === 'off' ) {
|
||||||
|
userStore.setKeyboardUsageStatus( false );
|
||||||
|
} else {
|
||||||
|
userStore.setKeyboardUsageStatus( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const openSearch = () => {
|
const openSearch = () => {
|
||||||
if ( search.value ) {
|
if ( search.value ) {
|
||||||
search.value.controlSearch( 'show' );
|
search.value.controlSearch( 'show' );
|
||||||
|
|||||||
@@ -9,12 +9,16 @@
|
|||||||
|
|
||||||
// These functions handle connections to the backend with socket.io
|
// These functions handle connections to the backend with socket.io
|
||||||
|
|
||||||
import { io, type Socket } from "socket.io-client"
|
import { io, type Socket } from "socket.io-client";
|
||||||
|
import type { SSEMap } from "./song";
|
||||||
|
|
||||||
class SocketConnection {
|
class SocketConnection {
|
||||||
socket: Socket;
|
socket: Socket;
|
||||||
roomName: string;
|
roomName: string;
|
||||||
isConnected: boolean;
|
isConnected: boolean;
|
||||||
|
useSocket: boolean;
|
||||||
|
eventSource?: EventSource;
|
||||||
|
toBeListenedForItems: SSEMap;
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
this.socket = io( localStorage.getItem( 'url' ) ?? '', {
|
this.socket = io( localStorage.getItem( 'url' ) ?? '', {
|
||||||
@@ -22,6 +26,8 @@ class SocketConnection {
|
|||||||
} );
|
} );
|
||||||
this.roomName = location.pathname.split( '/' )[ 2 ];
|
this.roomName = location.pathname.split( '/' )[ 2 ];
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
|
this.useSocket = localStorage.getItem( 'music-player-config' ) === 'ws';
|
||||||
|
this.toBeListenedForItems = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,16 +36,51 @@ class SocketConnection {
|
|||||||
*/
|
*/
|
||||||
connect (): Promise<any> {
|
connect (): Promise<any> {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
this.socket.connect();
|
if ( this.useSocket ) {
|
||||||
this.socket.emit( 'join-room', this.roomName, ( res: { status: boolean, msg: string, data: any } ) => {
|
this.socket.connect();
|
||||||
if ( res.status === true ) {
|
this.socket.emit( 'join-room', this.roomName, ( res: { status: boolean, msg: string, data: any } ) => {
|
||||||
this.isConnected = true;
|
if ( res.status === true ) {
|
||||||
resolve( res.data );
|
this.isConnected = true;
|
||||||
} else {
|
resolve( res.data );
|
||||||
console.debug( res.msg );
|
} else {
|
||||||
|
console.debug( res.msg );
|
||||||
|
reject( 'ERR_ROOM_CONNECTING' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
fetch( localStorage.getItem( 'url' ) + '/socket/joinRoom?room=' + this.roomName, { credentials: 'include' } ).then( res => {
|
||||||
|
if ( res.status === 200 ) {
|
||||||
|
this.eventSource = new EventSource( localStorage.getItem( 'url' ) + '/socket/connection?room=' + this.roomName, { withCredentials: true } );
|
||||||
|
|
||||||
|
this.eventSource.onmessage = ( e ) => {
|
||||||
|
const d = JSON.parse( e.data );
|
||||||
|
if ( this.toBeListenedForItems[ d.type ] ) {
|
||||||
|
this.toBeListenedForItems[ d.type ]( d.data );
|
||||||
|
} else if ( d.type === 'basics' ) {
|
||||||
|
resolve( d.data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eventSource.onerror = ( e ) => {
|
||||||
|
if ( this.isConnected ) {
|
||||||
|
this.isConnected = false;
|
||||||
|
console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Reconnecting due to connection error!' );
|
||||||
|
console.debug( e );
|
||||||
|
|
||||||
|
this.eventSource = undefined;
|
||||||
|
|
||||||
|
setTimeout( () => {
|
||||||
|
this.connect();
|
||||||
|
}, 500 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
reject( 'ERR_ROOM_CONNECTING' );
|
||||||
|
}
|
||||||
|
} ).catch( () => {
|
||||||
reject( 'ERR_ROOM_CONNECTING' );
|
reject( 'ERR_ROOM_CONNECTING' );
|
||||||
}
|
} );
|
||||||
} );
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +92,19 @@ class SocketConnection {
|
|||||||
*/
|
*/
|
||||||
emit ( event: string, data: any ): void {
|
emit ( event: string, data: any ): void {
|
||||||
if ( this.isConnected ) {
|
if ( this.isConnected ) {
|
||||||
this.socket.emit( event, { 'roomName': this.roomName, 'data': data } );
|
if ( this.useSocket ) {
|
||||||
|
this.socket.emit( event, { 'roomName': this.roomName, 'data': data } );
|
||||||
|
} else {
|
||||||
|
fetch( localStorage.getItem( 'url' ) + '/socket/update', {
|
||||||
|
method: 'post',
|
||||||
|
body: JSON.stringify( { 'event': event, 'roomName': this.roomName, 'data': data } ),
|
||||||
|
credentials: 'include',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'charset': 'utf-8'
|
||||||
|
}
|
||||||
|
} ).catch( () => {} );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +115,12 @@ class SocketConnection {
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
registerListener ( event: string, cb: ( data: any ) => void ): void {
|
registerListener ( event: string, cb: ( data: any ) => void ): void {
|
||||||
if ( this.isConnected ) {
|
if ( this.useSocket ) {
|
||||||
this.socket.on( event, cb );
|
if ( this.isConnected ) {
|
||||||
|
this.socket.on( event, cb );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.toBeListenedForItems[ event ] = cb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +130,11 @@ class SocketConnection {
|
|||||||
*/
|
*/
|
||||||
disconnect (): void {
|
disconnect (): void {
|
||||||
if ( this.isConnected ) {
|
if ( this.isConnected ) {
|
||||||
this.socket.disconnect();
|
if ( this.useSocket ) {
|
||||||
|
this.socket.disconnect();
|
||||||
|
} else {
|
||||||
|
this.eventSource!.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,17 @@
|
|||||||
// These functions handle connections to the backend with socket.io
|
// These functions handle connections to the backend with socket.io
|
||||||
|
|
||||||
import { io, type Socket } from "socket.io-client"
|
import { io, type Socket } from "socket.io-client"
|
||||||
|
import type { SSEMap } from "./song";
|
||||||
|
|
||||||
class NotificationHandler {
|
class NotificationHandler {
|
||||||
socket: Socket;
|
socket: Socket;
|
||||||
roomName: string;
|
roomName: string;
|
||||||
roomToken: string;
|
roomToken: string;
|
||||||
isConnected: boolean;
|
isConnected: boolean;
|
||||||
|
useSocket: boolean;
|
||||||
|
eventSource?: EventSource;
|
||||||
|
toBeListenedForItems: SSEMap;
|
||||||
|
reconnectRetryCount: number;
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
this.socket = io( localStorage.getItem( 'url' ) ?? '', {
|
this.socket = io( localStorage.getItem( 'url' ) ?? '', {
|
||||||
@@ -24,6 +29,9 @@ class NotificationHandler {
|
|||||||
this.roomName = '';
|
this.roomName = '';
|
||||||
this.roomToken = '';
|
this.roomToken = '';
|
||||||
this.isConnected = false;
|
this.isConnected = false;
|
||||||
|
this.useSocket = localStorage.getItem( 'music-player-config' ) === 'ws';
|
||||||
|
this.toBeListenedForItems = {};
|
||||||
|
this.reconnectRetryCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,18 +47,24 @@ class NotificationHandler {
|
|||||||
res.text().then( text => {
|
res.text().then( text => {
|
||||||
this.roomToken = text;
|
this.roomToken = text;
|
||||||
this.roomName = roomName;
|
this.roomName = roomName;
|
||||||
this.socket.connect();
|
if ( this.useSocket ) {
|
||||||
this.socket.emit( 'create-room', {
|
this.socket.connect();
|
||||||
name: this.roomName,
|
this.socket.emit( 'create-room', {
|
||||||
token: this.roomToken
|
name: this.roomName,
|
||||||
}, ( res: { status: boolean, msg: string } ) => {
|
token: this.roomToken
|
||||||
if ( res.status === true ) {
|
}, ( res: { status: boolean, msg: string } ) => {
|
||||||
this.isConnected = true;
|
if ( res.status === true ) {
|
||||||
|
this.isConnected = true;
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject( 'ERR_ROOM_CONNECTING' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
this.sseConnect().then( data => {
|
||||||
resolve();
|
resolve();
|
||||||
} else {
|
} ).catch( );
|
||||||
reject( 'ERR_ROOM_CONNECTING' );
|
}
|
||||||
}
|
|
||||||
} );
|
|
||||||
} );
|
} );
|
||||||
} else if ( res.status === 409 ) {
|
} else if ( res.status === 409 ) {
|
||||||
reject( 'ERR_CONFLICT' );
|
reject( 'ERR_CONFLICT' );
|
||||||
@@ -61,6 +75,56 @@ class NotificationHandler {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sseConnect (): Promise<void> {
|
||||||
|
return new Promise( ( resolve, reject ) => {
|
||||||
|
if ( this.reconnectRetryCount < 5 ) {
|
||||||
|
fetch( localStorage.getItem( 'url' ) + '/socket/joinRoom?room=' + this.roomName, { credentials: 'include' } ).then( res => {
|
||||||
|
if ( res.status === 200 ) {
|
||||||
|
this.eventSource = new EventSource( localStorage.getItem( 'url' ) + '/socket/connection?room=' + this.roomName, { withCredentials: true } );
|
||||||
|
this.eventSource.onopen = () => {
|
||||||
|
this.isConnected = true;
|
||||||
|
this.reconnectRetryCount = 0;
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eventSource.onmessage = ( e ) => {
|
||||||
|
const d = JSON.parse( e.data );
|
||||||
|
if ( this.toBeListenedForItems[ d.type ] ) {
|
||||||
|
this.toBeListenedForItems[ d.type ]( d.data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eventSource.onerror = ( e ) => {
|
||||||
|
if ( this.isConnected ) {
|
||||||
|
this.isConnected = false;
|
||||||
|
console.log( '[ SSE Connection ] - ' + new Date().toISOString() + ': Reconnecting due to connection error!' );
|
||||||
|
console.debug( e );
|
||||||
|
|
||||||
|
this.eventSource = undefined;
|
||||||
|
|
||||||
|
this.reconnectRetryCount += 1;
|
||||||
|
setTimeout( () => {
|
||||||
|
this.sseConnect();
|
||||||
|
}, 500 * this.reconnectRetryCount );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
reject( 'ERR_ROOM_CONNECTING' );
|
||||||
|
}
|
||||||
|
} ).catch( () => {
|
||||||
|
reject( 'ERR_ROOM_CONNECTING' );
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
if ( confirm( 'Connection lost and it could not be reestablished. Please click ok to retry or press cancel to stop retrying. Your share will be deleted as a result thereof.' ) ) {
|
||||||
|
this.reconnectRetryCount = 0;
|
||||||
|
this.sseConnect();
|
||||||
|
} else {
|
||||||
|
this.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit an event
|
* Emit an event
|
||||||
* @param {string} event The event to emit
|
* @param {string} event The event to emit
|
||||||
@@ -69,7 +133,19 @@ class NotificationHandler {
|
|||||||
*/
|
*/
|
||||||
emit ( event: string, data: any ): void {
|
emit ( event: string, data: any ): void {
|
||||||
if ( this.isConnected ) {
|
if ( this.isConnected ) {
|
||||||
this.socket.emit( event, { 'roomToken': this.roomToken, 'roomName': this.roomName, 'data': data } );
|
if ( this.useSocket ) {
|
||||||
|
this.socket.emit( event, { 'roomToken': this.roomToken, 'roomName': this.roomName, 'data': data } );
|
||||||
|
} else {
|
||||||
|
fetch( localStorage.getItem( 'url' ) + '/socket/update', {
|
||||||
|
method: 'post',
|
||||||
|
body: JSON.stringify( { 'event': event, 'roomName': this.roomName, 'roomToken': this.roomToken, 'data': data } ),
|
||||||
|
credentials: 'include',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'charset': 'utf-8'
|
||||||
|
}
|
||||||
|
} ).catch( () => {} );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +157,11 @@ class NotificationHandler {
|
|||||||
*/
|
*/
|
||||||
registerListener ( event: string, cb: ( data: any ) => void ): void {
|
registerListener ( event: string, cb: ( data: any ) => void ): void {
|
||||||
if ( this.isConnected ) {
|
if ( this.isConnected ) {
|
||||||
this.socket.on( event, cb );
|
if ( this.useSocket ) {
|
||||||
|
this.socket.on( event, cb );
|
||||||
|
} else {
|
||||||
|
this.toBeListenedForItems[ event ] = cb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,15 +171,33 @@ class NotificationHandler {
|
|||||||
*/
|
*/
|
||||||
disconnect (): void {
|
disconnect (): void {
|
||||||
if ( this.isConnected ) {
|
if ( this.isConnected ) {
|
||||||
this.socket.emit( 'delete-room', {
|
if ( this.useSocket ) {
|
||||||
name: this.roomName,
|
this.socket.emit( 'delete-room', {
|
||||||
token: this.roomToken
|
name: this.roomName,
|
||||||
}, ( res: { status: boolean, msg: string } ) => {
|
token: this.roomToken
|
||||||
this.socket.disconnect();
|
}, ( res: { status: boolean, msg: string } ) => {
|
||||||
if ( !res.status ) {
|
this.socket.disconnect();
|
||||||
alert( 'Unable to delete the room you were just in. The name will be blocked until the next server restart!' );
|
if ( !res.status ) {
|
||||||
}
|
alert( 'Unable to delete the room you were just in. The name will be blocked until the next server restart!' );
|
||||||
} );
|
}
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
fetch( localStorage.getItem( 'url' ) + '/socket/deleteRoom', {
|
||||||
|
method: 'post',
|
||||||
|
body: JSON.stringify( { 'roomName': this.roomName, 'roomToken': this.roomToken } ),
|
||||||
|
credentials: 'include',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'charset': 'utf-8'
|
||||||
|
}
|
||||||
|
} ).then( res => {
|
||||||
|
if ( res.status === 200 ) {
|
||||||
|
this.eventSource!.close();
|
||||||
|
} else {
|
||||||
|
alert( 'Unable to delete the room you were just in. The name will be blocked until the next server restart!' );
|
||||||
|
}
|
||||||
|
} ).catch( () => {} );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
MusicPlayerV2-GUI/src/scripts/song.d.ts
vendored
4
MusicPlayerV2-GUI/src/scripts/song.d.ts
vendored
@@ -89,3 +89,7 @@ export interface SongMove {
|
|||||||
songID: string;
|
songID: string;
|
||||||
newPos: number;
|
newPos: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SSEMap {
|
||||||
|
[key: string]: ( data: any ) => void;
|
||||||
|
}
|
||||||
1
backend/package-lock.json
generated
1
backend/package-lock.json
generated
@@ -43,6 +43,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../../store/sdk/dist": {
|
"../../store/sdk/dist": {
|
||||||
|
"name": "store.janishutz.com-sdk",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { Server } from 'socket.io';
|
|||||||
import crypto from 'node:crypto';
|
import crypto from 'node:crypto';
|
||||||
import type { Room, Song } from './definitions';
|
import type { Room, Song } from './definitions';
|
||||||
import storeSDK from 'store.janishutz.com-sdk';
|
import storeSDK from 'store.janishutz.com-sdk';
|
||||||
|
import bodyParser from 'body-parser';
|
||||||
|
|
||||||
declare let __dirname: string | undefined
|
declare let __dirname: string | undefined
|
||||||
if ( typeof( __dirname ) === 'undefined' ) {
|
if ( typeof( __dirname ) === 'undefined' ) {
|
||||||
@@ -182,6 +183,170 @@ const run = () => {
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
ROUTES FOR SERVER SENT EVENTS VERSION
|
||||||
|
*/
|
||||||
|
// Connected clients have their session ID as key
|
||||||
|
interface SocketClientList {
|
||||||
|
[key: string]: SocketClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SocketClient {
|
||||||
|
response: express.Response;
|
||||||
|
room: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ClientReferenceList {
|
||||||
|
/**
|
||||||
|
* Find all clients connected to one room
|
||||||
|
*/
|
||||||
|
[key: string]: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const importantClients: SocketClientList = {};
|
||||||
|
const connectedClients: SocketClientList = {};
|
||||||
|
const clientReference: ClientReferenceList = {};
|
||||||
|
|
||||||
|
app.get( '/socket/connection', ( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( request.query.room ) {
|
||||||
|
if ( socketData[ String( request.query.room ) ] ) {
|
||||||
|
response.writeHead( 200, {
|
||||||
|
'Content-Type': 'text/event-stream',
|
||||||
|
'Cache-Control': 'no-cache',
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
} );
|
||||||
|
response.status( 200 );
|
||||||
|
response.flushHeaders();
|
||||||
|
response.write( `data: ${ JSON.stringify( { 'type': 'basics', 'data': socketData[ String( request.query.room ) ] } ) }\n\n` );
|
||||||
|
const sid = sdk.getSessionID( request );
|
||||||
|
if ( sdk.checkAuth( request ) ) {
|
||||||
|
importantClients[ sid ] = { 'response': response, 'room': String( request.query.room ) };
|
||||||
|
}
|
||||||
|
connectedClients[ sid ] = { 'response': response, 'room': String( request.query.room ) };
|
||||||
|
if ( !clientReference[ String( request.query.room ) ] ) {
|
||||||
|
clientReference[ String( request.query.room ) ] = [];
|
||||||
|
}
|
||||||
|
if ( !clientReference[ String( request.query.room ) ].includes( sid ) ) {
|
||||||
|
clientReference[ String( request.query.room ) ].push( sid );
|
||||||
|
}
|
||||||
|
request.on( 'close', () => {
|
||||||
|
try {
|
||||||
|
importantClients[ sid ] = undefined;
|
||||||
|
} catch ( e ) { /* empty */ }
|
||||||
|
const cl = clientReference[ String( request.query.room ) ];
|
||||||
|
for ( let c in cl ) {
|
||||||
|
if ( cl[ c ] === sid ) {
|
||||||
|
cl.splice( parseInt( c ), 1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connectedClients[ sid ] = undefined;
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
app.get( '/socket/getData', ( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( request.query.room ) {
|
||||||
|
response.send( socketData[ String( request.query.room ) ] );
|
||||||
|
} else {
|
||||||
|
response.status( 400 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
app.get( '/socket/joinRoom', ( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( request.query.room ) {
|
||||||
|
if ( socketData[ String( request.query.room ) ] ) {
|
||||||
|
response.send( 'ok' );
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
app.post( '/socket/update', bodyParser.json(), ( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( socketData[ request.body.roomName ] ) {
|
||||||
|
if ( request.body.update === 'tampering' ) {
|
||||||
|
const clients = clientReference[ request.body.roomName ];
|
||||||
|
for ( let client in clients ) {
|
||||||
|
if ( importantClients[ clients[ client ] ] ) {
|
||||||
|
importantClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'update': 'tampering', 'data': true } ) + '\n\n' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( socketData[ request.body.roomName ].roomToken === request.body.roomToken ) {
|
||||||
|
let send = false;
|
||||||
|
let update = '';
|
||||||
|
|
||||||
|
if ( request.body.event === 'playback-start-update' ) {
|
||||||
|
send = true;
|
||||||
|
update = 'playback-start';
|
||||||
|
socketData[ request.body.roomName ].playbackStart = request.body.data;
|
||||||
|
} else if ( request.body.event === 'playback-update' ) {
|
||||||
|
send = true;
|
||||||
|
update = 'playback';
|
||||||
|
socketData[ request.body.roomName ].playbackStatus = request.body.data;
|
||||||
|
} else if ( request.body.event === 'playlist-update' ) {
|
||||||
|
send = true;
|
||||||
|
update = 'playlist';
|
||||||
|
socketData[ request.body.roomName ].playlist = request.body.data;
|
||||||
|
} else if ( request.body.event === 'playlist-index-update' ) {
|
||||||
|
send = true;
|
||||||
|
update = 'playlist-index';
|
||||||
|
socketData[ request.body.roomName ].playlistIndex = request.body.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( send ) {
|
||||||
|
const clients = clientReference[ request.body.roomName ];
|
||||||
|
for ( let client in clients ) {
|
||||||
|
if ( connectedClients[ clients[ client ] ] ) {
|
||||||
|
connectedClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'type': update, 'data': request.body.data } ) + '\n\n' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.send( 'ok' );
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_CANNOT_SEND' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app.post( '/socket/deleteRoom', bodyParser.json(), ( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( request.body.roomName ) {
|
||||||
|
if ( socketData[ request.body.roomName ] ) {
|
||||||
|
if ( socketData[ request.body.roomName ].roomToken === request.body.roomToken ) {
|
||||||
|
socketData[ request.body.roomName ] = undefined;
|
||||||
|
const clients = clientReference[ request.body.roomName ];
|
||||||
|
for ( let client in clients ) {
|
||||||
|
if ( connectedClients[ clients[ client ] ] ) {
|
||||||
|
connectedClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'update': 'delete-share', 'data': true } ) + '\n\n' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.send( 403 ).send( 'ERR_UNAUTHORIZED' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 400 ).send( 'ERR_NO_ROOM_NAME' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
GENERAL ROUTES
|
||||||
|
*/
|
||||||
app.get( '/', ( request: express.Request, response: express.Response ) => {
|
app.get( '/', ( request: express.Request, response: express.Response ) => {
|
||||||
response.send( 'Please visit <a href="https://music.janishutz.com">https://music.janishutz.com</a> to use this service' );
|
response.send( 'Please visit <a href="https://music.janishutz.com">https://music.janishutz.com</a> to use this service' );
|
||||||
} );
|
} );
|
||||||
|
|||||||
Reference in New Issue
Block a user