Add player functionality with HLS support and API integration
- Implemented a new Player class in player.js to handle audio playback, including HLS support using hls.js. - Created a shared API module in api.js for making HTTP requests with proper error handling. - Added DOM utility functions in dom.js for creating and clearing elements. - Introduced WebSocket connection handling in ws.js for real-time updates. - Developed a comprehensive CSS stylesheet for styling the application, including a high-contrast theme.
This commit is contained in:
63
server/routes/me.js
Normal file
63
server/routes/me.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Router } from 'express';
|
||||
import { requireUser } from '../auth.js';
|
||||
import { getDb } from '../db/index.js';
|
||||
|
||||
export const router = Router();
|
||||
|
||||
router.use(requireUser);
|
||||
|
||||
router.get('/favorites', (req, res) => {
|
||||
const rows = getDb().prepare(`
|
||||
SELECT s.*, f.position
|
||||
FROM favorites f JOIN stations s ON s.id = f.station_id
|
||||
WHERE f.user_id = ? AND s.enabled = 1
|
||||
ORDER BY f.position ASC, f.created_at ASC
|
||||
`).all(req.user.id);
|
||||
res.json(rows.map((r) => ({
|
||||
id: r.id, uuid: r.uuid, name: r.name, slug: r.slug, homepage: r.homepage, country: r.country,
|
||||
genres: r.genres ? JSON.parse(r.genres) : [], image_url: r.image_url, category: r.category, position: r.position
|
||||
})));
|
||||
});
|
||||
|
||||
router.put('/favorites/:stationId', (req, res) => {
|
||||
const stationId = Number(req.params.stationId);
|
||||
const position = Number(req.body?.position ?? 0);
|
||||
getDb().prepare(`
|
||||
INSERT INTO favorites (user_id, station_id, position) VALUES (?, ?, ?)
|
||||
ON CONFLICT(user_id, station_id) DO UPDATE SET position = excluded.position
|
||||
`).run(req.user.id, stationId, position);
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
router.delete('/favorites/:stationId', (req, res) => {
|
||||
getDb().prepare('DELETE FROM favorites WHERE user_id = ? AND station_id = ?')
|
||||
.run(req.user.id, Number(req.params.stationId));
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
router.get('/profile', (req, res) => {
|
||||
const row = getDb().prepare('SELECT * FROM profiles WHERE user_id = ?').get(req.user.id);
|
||||
res.json(row || { user_id: req.user.id, display_name: req.user.username, theme: 'dark', default_volume: 0.7 });
|
||||
});
|
||||
|
||||
router.patch('/profile', (req, res) => {
|
||||
const { display_name, theme, default_volume } = req.body || {};
|
||||
getDb().prepare(`
|
||||
INSERT INTO profiles (user_id, display_name, theme, default_volume) VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
display_name = COALESCE(excluded.display_name, profiles.display_name),
|
||||
theme = COALESCE(excluded.theme, profiles.theme),
|
||||
default_volume = COALESCE(excluded.default_volume, profiles.default_volume)
|
||||
`).run(req.user.id, display_name ?? null, theme ?? null, default_volume ?? null);
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
router.get('/history', (req, res) => {
|
||||
const rows = getDb().prepare(`
|
||||
SELECT h.*, s.name AS station_name, s.slug AS station_slug
|
||||
FROM play_history h JOIN stations s ON s.id = h.station_id
|
||||
WHERE h.user_id = ?
|
||||
ORDER BY h.started_at DESC LIMIT 50
|
||||
`).all(req.user.id);
|
||||
res.json(rows);
|
||||
});
|
||||
Reference in New Issue
Block a user