updated README.md
This commit is contained in:
parent
d11681b78d
commit
672553cdf1
|
|
@ -36,3 +36,5 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
tmp/
|
tmp/
|
||||||
library_cache.db
|
library_cache.db
|
||||||
musicroom.db
|
musicroom.db
|
||||||
|
blastoise.db
|
||||||
|
config.json
|
||||||
|
|
|
||||||
16
README.md
16
README.md
|
|
@ -1,15 +1,21 @@
|
||||||
# NeoRose
|
# Blastoise
|
||||||
|
|
||||||
To install dependencies:
|
Everything that I've wanted out of a networked music player. Self-host. Play your music through the server, but also cache all the tracks locally.
|
||||||
|
|
||||||
|
But most importantly, listen to the same stuff as your friends.
|
||||||
|
|
||||||
|
Its actually more of a file downloader than a normal music streamer. Built with bun.
|
||||||
|
|
||||||
|
First time setup:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun install
|
bun install
|
||||||
```
|
```
|
||||||
|
|
||||||
To run:
|
to launch the server
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run
|
bun run server.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
This project was created using `bun init` in bun v1.3.8. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
have a look at the config.json that gets created the first time.
|
||||||
|
|
|
||||||
2
auth.ts
2
auth.ts
|
|
@ -1,6 +1,6 @@
|
||||||
import { validateSession, hasPermission, type User } from "./db";
|
import { validateSession, hasPermission, type User } from "./db";
|
||||||
|
|
||||||
const COOKIE_NAME = "musicroom_session";
|
const COOKIE_NAME = "blastoise_session";
|
||||||
|
|
||||||
export function getSessionToken(req: Request): string | null {
|
export function getSessionToken(req: Request): string | null {
|
||||||
const cookie = req.headers.get("cookie");
|
const cookie = req.headers.get("cookie");
|
||||||
|
|
|
||||||
2
bun.lock
2
bun.lock
|
|
@ -3,7 +3,7 @@
|
||||||
"configVersion": 1,
|
"configVersion": 1,
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "musicroom",
|
"name": "blastoise",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"music-metadata": "^11.11.2",
|
"music-metadata": "^11.11.2",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
2
db.ts
2
db.ts
|
|
@ -1,6 +1,6 @@
|
||||||
import { Database } from "bun:sqlite";
|
import { Database } from "bun:sqlite";
|
||||||
|
|
||||||
const DB_PATH = "./musicroom.db";
|
const DB_PATH = "./blastoise.db";
|
||||||
const SESSION_EXPIRY_DAYS = 7;
|
const SESSION_EXPIRY_DAYS = 7;
|
||||||
const GUEST_SESSION_EXPIRY_HOURS = 24;
|
const GUEST_SESSION_EXPIRY_HOURS = 24;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "musicroom",
|
"name": "blastoise",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "bun run server.ts"
|
"start": "bun run server.ts"
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@
|
||||||
const M = window.MusicRoom;
|
const M = window.MusicRoom;
|
||||||
|
|
||||||
// Load stream-only preference from localStorage
|
// Load stream-only preference from localStorage
|
||||||
M.streamOnly = localStorage.getItem("musicroom_streamOnly") === "true";
|
M.streamOnly = localStorage.getItem("blastoise_streamOnly") === "true";
|
||||||
|
|
||||||
// Toggle stream-only mode
|
// Toggle stream-only mode
|
||||||
M.setStreamOnly = function(enabled) {
|
M.setStreamOnly = function(enabled) {
|
||||||
M.streamOnly = enabled;
|
M.streamOnly = enabled;
|
||||||
localStorage.setItem("musicroom_streamOnly", enabled ? "true" : "false");
|
localStorage.setItem("blastoise_streamOnly", enabled ? "true" : "false");
|
||||||
M.showToast(enabled ? "Stream-only mode enabled" : "Caching enabled");
|
M.showToast(enabled ? "Stream-only mode enabled" : "Caching enabled");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
M.channels = channels;
|
M.channels = channels;
|
||||||
M.renderChannelList();
|
M.renderChannelList();
|
||||||
// Try saved channel first, fall back to default
|
// Try saved channel first, fall back to default
|
||||||
const savedChannelId = localStorage.getItem("musicroom_channel");
|
const savedChannelId = localStorage.getItem("blastoise_channel");
|
||||||
const savedChannel = savedChannelId && channels.find(c => c.id === savedChannelId);
|
const savedChannel = savedChannelId && channels.find(c => c.id === savedChannelId);
|
||||||
const targetChannel = savedChannel || channels.find(c => c.isDefault) || channels[0];
|
const targetChannel = savedChannel || channels.find(c => c.isDefault) || channels[0];
|
||||||
M.connectChannel(targetChannel.id);
|
M.connectChannel(targetChannel.id);
|
||||||
|
|
@ -158,7 +158,7 @@
|
||||||
oldWs.close();
|
oldWs.close();
|
||||||
}
|
}
|
||||||
M.currentChannelId = id;
|
M.currentChannelId = id;
|
||||||
localStorage.setItem("musicroom_channel", id);
|
localStorage.setItem("blastoise_channel", id);
|
||||||
const proto = location.protocol === "https:" ? "wss:" : "ws:";
|
const proto = location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
M.ws = new WebSocket(proto + "//" + location.host + "/api/channels/" + id + "/ws");
|
M.ws = new WebSocket(proto + "//" + location.host + "/api/channels/" + id + "/ws");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ window.MusicRoom = {
|
||||||
|
|
||||||
// Volume
|
// Volume
|
||||||
preMuteVolume: 1,
|
preMuteVolume: 1,
|
||||||
STORAGE_KEY: "musicroom_volume",
|
STORAGE_KEY: "blastoise_volume",
|
||||||
|
|
||||||
// Playback state
|
// Playback state
|
||||||
localTimestamp: 0,
|
localTimestamp: 0,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<h1>MusicRoom <span id="sync-indicator"></span></h1>
|
<h1>Blastoise <span id="sync-indicator"></span></h1>
|
||||||
|
|
||||||
<div id="login-panel">
|
<div id="login-panel">
|
||||||
<h2>Sign in to continue</h2>
|
<h2>Sign in to continue</h2>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// Default implementation uses IndexedDB, can be swapped for Electron file API
|
// Default implementation uses IndexedDB, can be swapped for Electron file API
|
||||||
|
|
||||||
const TrackStorage = (function() {
|
const TrackStorage = (function() {
|
||||||
const DB_NAME = 'musicroom';
|
const DB_NAME = 'blastoise';
|
||||||
const DB_VERSION = 1;
|
const DB_VERSION = 1;
|
||||||
const STORE_NAME = 'tracks';
|
const STORE_NAME = 'tracks';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -619,7 +619,7 @@ serve({
|
||||||
|
|
||||||
// Auth: logout
|
// Auth: logout
|
||||||
if (path === "/api/auth/logout" && req.method === "POST") {
|
if (path === "/api/auth/logout" && req.method === "POST") {
|
||||||
const token = req.headers.get("cookie")?.match(/musicroom_session=([^;]+)/)?.[1];
|
const token = req.headers.get("cookie")?.match(/blastoise_session=([^;]+)/)?.[1];
|
||||||
if (token) {
|
if (token) {
|
||||||
const user = validateSession(token);
|
const user = validateSession(token);
|
||||||
console.log(`[AUTH] Logout: user="${user?.username ?? "unknown"}" session=${token}`);
|
console.log(`[AUTH] Logout: user="${user?.username ?? "unknown"}" session=${token}`);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue