chore: prepare backend

This commit is contained in:
2026-09-03 08:46:53 +02:00
parent 223478f7cc
commit c123673ca5
9 changed files with 161 additions and 42 deletions
+28
View File
@@ -0,0 +1,28 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": [
"foss",
"hosted"
],
"default": "foss",
"description": "Mode to use for the login. If set to hosted, sdk configuration needs to be complete"
},
"clientMode": {
"type": "string",
"enum": [
"sse",
"poll"
],
"default": "poll",
"description": "Default information retrieval mode for the basic remote displays. Polling is slightly cheaper at the cost of responsiveness"
},
"webUrl": {
"type": "string",
"description": "The URL to the frontend. Just the host, in form https://music.janishutz.com"
}
}
}
+4
View File
@@ -0,0 +1,4 @@
{
"$schema": "../config.schema.json",
"mode": "foss"
}
+6 -33
View File
@@ -1,14 +1,13 @@
import cors from 'cors'; import devtoken from './routes/devtoken';
import express from 'express'; import express from 'express';
import expressSession from 'express-session'; import expressSession from 'express-session';
import fs from 'fs';
import jwt from 'jsonwebtoken';
import path from 'path'; import path from 'path';
const run = () => { const run = () => {
const app = express(); const app = express();
// TODO: Use db store for this (via sdk or stubs)
app.use( expressSession( { app.use( expressSession( {
'secret': 'dev', 'secret': 'dev',
'resave': true, 'resave': true,
@@ -16,45 +15,19 @@ const run = () => {
} ) ); } ) );
app.get( '/', ( request: express.Request, response: express.Response ) => { app.get( '/', ( _request: express.Request, response: express.Response ) => {
response.send( 'HELLO WORLD' ); response.send( 'HELLO WORLD' );
} ); } );
const privateKey = fs.readFileSync( path.join(
__dirname,
'/config/apple_private_key.p8'
) ).toString();
const musicApiConfig = JSON.parse( fs.readFileSync( path.join(
__dirname,
'/config/apple-music-api.config.secret.json'
) ).toString() );
app.get( '/dev-token', cors( {
'origin': 'http://localhost:8081',
'credentials': true
} ), ( _request: express.Request, response: express.Response ) => {
// sign dev token
const now = new Date().getTime();
const tomorrow = now + ( 24 * 3600 * 1000 );
const jwtToken = jwt.sign( {
'iss': musicApiConfig.teamID,
'iat': Math.floor( now / 1000 ),
'exp': Math.floor( tomorrow / 1000 )
}, privateKey, {
'algorithm': 'ES256',
'keyid': musicApiConfig.keyID
} );
response.send( jwtToken );
} );
app.use( ( _request: express.Request, response: express.Response ) => { app.use( ( _request: express.Request, response: express.Response ) => {
response.sendFile( path.join( __dirname, '' ) ); response.sendFile( path.join( __dirname, '' ) );
} ); } );
devtoken.routes( app );
const PORT = process.env.PORT || 8080; const PORT = process.env.PORT || 8080;
app.listen( PORT ); app.listen( PORT );
+39
View File
@@ -0,0 +1,39 @@
import cors from 'cors';
import express from 'express';
import fs from 'fs';
import jwt from 'jsonwebtoken';
import path from 'path';
const routes = ( app: express.Application ) => {
const privateKey = fs.readFileSync( path.join(
__dirname,
'/../config/apple_private_key.p8'
) ).toString();
const musicApiConfig = JSON.parse( fs.readFileSync( path.join(
__dirname,
'/../config/apple-music-api.config.secret.json'
) ).toString() );
app.get( '/dev-token', cors( {
'origin': 'http://localhost:8081',
'credentials': true
} ), ( _request: express.Request, response: express.Response ) => {
// sign dev token
const now = new Date().getTime();
const tomorrow = now + ( 24 * 3600 * 1000 );
const jwtToken = jwt.sign( {
'iss': musicApiConfig.teamID,
'iat': Math.floor( now / 1000 ),
'exp': Math.floor( tomorrow / 1000 )
}, privateKey, {
'algorithm': 'ES256',
'keyid': musicApiConfig.keyID
} );
response.send( jwtToken );
} );
};
export default {
routes
}
+20
View File
@@ -0,0 +1,20 @@
import express from 'express';
import tracking from './tracking';
import update from './update';
const routes = ( app: express.Application ) => {
tracking.routes( app );
update.routes( app );
app.get( '/room/create', ( request: express.Request, response: express.Response ) => {
} );
app.get( '/room/:id/close', ( request: express.Request, response: express.Response ) => {
} );
};
export default {
routes
};
+24
View File
@@ -0,0 +1,24 @@
import express from 'express';
const routes = ( app: express.Application ) => {
app.get( '/room/:id/tracking/exit', ( request: express.Request, response: express.Response ) => {
} );
app.get( '/room/:id/tracking/ping', ( request: express.Request, response: express.Response ) => {
} );
app.get( '/room/:id/tracking/connect', ( request: express.Request, response: express.Response ) => {
} );
app.get( '/room/:id/admin', ( request: express.Request, response: express.Response ) => {
// Endpoint for the streamer to connect to, all above events are sent there
} );
};
export default {
routes
};
+23
View File
@@ -0,0 +1,23 @@
import express from 'express';
const routes = ( app: express.Application ) => {
app.get( '/room/:id/connect', ( request: express.Request, response: express.Response ) => {
} );
app.get( '/room/:id/poll', ( request: express.Request, response: express.Response ) => {
} );
app.get( '/room/:id/update/playlist', ( request: express.Request, response: express.Response ) => {
} );
app.get( '/room/:id/update/state', ( request: express.Request, response: express.Response ) => {
} );
};
export default {
routes
};
+11
View File
@@ -0,0 +1,11 @@
import express from 'express';
const routes = ( app: express.Application ) => {
app.get( '/user/playlists', ( request: express.Request, response: express.Response ) => {
} );
app.post( '/user/playlists', ( request: express.Request, response: express.Response ) => {
} );
};
+3 -6
View File
@@ -1,15 +1,12 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const getSubscriptions = ( _uid: string ) => { const getSubscriptions = ( _uid: string ) => {
return [ return [ {
{
'id': 'com.janishutz.MusicPlayer.subscription', 'id': 'com.janishutz.MusicPlayer.subscription',
'expires': new Date().getTime() + 200000, 'expires': new Date().getTime() + 200000,
'status': true 'status': true
} } ];
];
}; };
export default { export default {
getSubscriptions, getSubscriptions
}; };