add backend files

master
adb-sh 2 years ago
parent 0767ee6530
commit 65b3db1fcc

1
.gitignore vendored

@ -0,0 +1 @@
./backend/node_modules

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "frontend"]
path = frontend
url = https://git.cybre.town/adb/spot2gether-frontend

@ -0,0 +1,3 @@
APP_SPOTIFY_CLIENT_ID=
APP_SPOTIFY_CLIENT_SECRET=
APP_SPOTIFY_REDIRECT_URI="http://127.0.0.1:8083/auth/callback"

@ -0,0 +1,50 @@
import { Client, Player } from "spotify-api.js";
import { store } from "../store.mjs";
import { randomString } from "../lib/randomString.js";
import axios from "axios";
export const applyAuthRoutes = (router) => {
router.post('/', async (req, res) => {
if (!req.body.code || !req.body.state) {
res.status(400);
res.send({ message: 'code or state missing ' });
return;
}
const { code, state } = req.body;
try {
const params = new URLSearchParams();
params.append('grant_type', 'authorization_code');
params.append('code', code);
params.append('redirect_uri', store.redirectURL);
const config = {
headers: {
'Authorization': 'Basic ' + (new Buffer(store.clientID + ':' + store.clientSecret).toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded',
}
};
const tokens = (await axios.post('https://accounts.spotify.com/api/token', params, config))?.data;
const client = await Client.create({
token: {
clientID: store.clientID,
clientSecret: store.clientSecret,
redirectURL: store.redirectURL,
refreshToken: tokens.refresh_token,
},
});
const player = new Player(client);
const accessToken = randomString(64);
store.users.push({ client, player, accessToken, listeners: [], role: 'none' });
res.status(200);
res.send({ message: 'authorized', accessToken });
} catch (e) {
console.log(e.message);
res.status(500);
res.send({ message: 'unauthorized' });
}
});
};

@ -0,0 +1,18 @@
import { applyUserRoutes, applyUserRoutesPublic } from "./user.mjs";
export const applyApiRoutes = (router) => {
router.get('/test', (req, res) => {
res.status(200);
res.send({ message: 'connection is working' });
});
applyUserRoutes(router);
};
export const applyPublicRoutes = (router) => {
applyUserRoutesPublic(router);
};

@ -0,0 +1,110 @@
import { store } from "../store.mjs";
export const applyUserRoutes = (router) => {
applyUserRoutesPublic(router);
router.post('/user/joinSession', async (req, res) => {
if (!req.body?.userId) {
res.status(400);
res.send({ message: 'userId is undefined' });
return;
}
const { userId } = req.body.userId;
if (res.locals.user.role === 'host') {
res.status(400);
res.send({ message: 'user is host' });
return;
}
const host = store.users.find(({ client }) => client.user.id === userId)
host.listeners.push(res.locals.user);
res.locals.user.role = 'listener';
res.locals.user.listeningTo = host;
res.status(200);
res.send({ message: 'joined' });
});
router.delete('/user/leaveSession', async (req, res) => {
if (res.locals.user.role === 'host') {
res.status(400);
res.send({ message: 'user is host' });
return;
}
const host = store.users.find(({ client }) => client.user.id === userId)
host.listeners.push(res.locals.user);
res.locals.user.role = 'none';
res.locals.user.listeningTo.listeners = res.locals.user.listeningTo.listeners.filter(
({ client }) => client.user.id !== res.locals.user.client.user.id
);
res.locals.user.listeningTo = null;
res.status(200);
res.send({ message: 'left' });
});
router.get('/user/currentlyPlaying', async (req, res) => {
const currentlyPlaying = await res.locals.user.player?.getCurrentlyPlaying('track');
res.status(200);
res.send({ currentlyPlaying });
});
router.get('/user/role', (req, res) => {
res.status(200);
res.send({ role: res.locals.user?.role });
});
/*router.post('/user/role', async (req, res) => {
if (
req.body.role !== 'host' ||
req.body.role !== 'listener' ||
req.body.role !== 'none'
) {
res.status(400);
res.send({ message: 'role value is invalid' });
}
const { role } = req.body;
try {
res.locals.user.listeners = [];
res.locals.user.role = role;
res.status(200);
res.send({ role });
} catch (e) {
res.status(500);
res.send({ message: 'server error' });
}
});*/
};
export const applyUserRoutesPublic = (router) => {
router.get('/users/:userId/info', async (req, res) => {
if (!req.params.userId) {
res.status(400);
res.send({ message: 'userId is missing' });
}
const { userId } = req.params;
const host = store.users.find(({ client }) => client.user.id === userId);
if (!host?.player) {
res.status(400);
res.send({ message: 'user is not registered' });
return;
}
try {
const currentlyPlaying = await host?.player?.getCurrentlyPlaying('track');
res.status(200);
res.send({
currentlyPlaying,
user: {
displayName: host.client.user.displayName,
totalFollowers: host.client.user.totalFollowers,
images: host.client.user.images,
},
});
} catch (e) {
console.log(e);
res.status(500);
res.send({ message: 'server error' });
}
});
};

@ -0,0 +1,32 @@
import express from "express";
import { auth } from "./middlewares/auth.mjs";
import { applyAuthRoutes } from "./api/auth.mjs";
import { applyApiRoutes, applyPublicRoutes } from "./api/index.mjs";
// express server
const port = 3000;
const app = express();
const router = express.Router();
const authRouter = express.Router();
const publicRouter = express.Router();
router.use(express.json());
authRouter.use(express.json());
publicRouter.use(express.json());
app
.use('/api/v1', router)
.use('/api/auth', authRouter)
.use('/api/public', publicRouter);
applyAuthRoutes(authRouter);
router.use(auth);
applyApiRoutes(router);
applyPublicRoutes(publicRouter);
app.listen(port);
console.log('ready');

@ -0,0 +1,7 @@
export const randomString = (length) => {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for ( let i = 0; i < length; i++ )
result += characters.charAt(Math.floor(Math.random() * characters.length));
return result;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,17 @@
{
"name": "spot2gether",
"version": "0.1.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Alban David Becker",
"dependencies": {
"axios": "^0.27.2",
"express": "^4.18.1",
"spotify-api.js": "^9.2.3"
}
}

@ -0,0 +1,6 @@
export const store = {
users: [],
clientID: '02d74b98c7904d6498b0b79def49cc5c',
clientSecret: 'e43b819037eb48e6b190865fc2c47b21',
redirectURL: 'http://127.0.0.1:8083/auth/callback',
};

@ -1,47 +0,0 @@
version: '3'
services:
redis:
image: redis:alpine
expose:
- 6379
restart: always
environment:
- REDIS_REPLICATION_MODE=master
backend:
image: node:alpine
restart: always
expose:
- 3000
volumes:
- ./backend/:/home/node/app/backend/
- ./helpers/:/home/node/app/helpers/
working_dir: /home/node/app/backend
environment:
- NODE_ENV=production
command: sh -c 'npm i && nodejs index.mjs'
links:
- redis
depends_on:
- redis
frontend:
image: node:alpine
volumes:
- ./frontend/:/home/node/app/frontend/
working_dir: /home/node/app/frontend
command: sh -c 'npm i --also=dev && npm run build'
nginx:
image: nginx:alpine
restart: always
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./frontend/dist/:/var/www/html/
ports:
- "8083:8080"
links:
- backend
depends_on:
- backend
Loading…
Cancel
Save