Let a client add a new soundtrack: it uploads the songs, the server writes them to a new folder in the music folder and adds them to the database, without waiting for the next sync.
Feasibility
Yes. SyncService already has syncSoundtrack(ctx, name) and syncSongs for one folder, so after writing the files the server can sync just that folder.
Plan
Endpoints (token required):
POST /api/v1/soundtracks/uploads with {"name": "Chrono Trigger"} starts an upload.
It checks that the name is a safe folder name (no /, .. or hidden names) and that no soundtrack or folder of that name exists (409).
It returns an upload ID. Files go to a temporary folder, e.g. MUSIC_PATH/.uploads/<id>/. Hidden folders are skipped by the sync.
PUT /api/v1/soundtracks/uploads/{id}/files/{file name} sends one song as the raw body. One request per song keeps requests small, and a failed song can be retried.
Only audio types the sync accepts.
Size limit per file (configurable).
The file name is sanitized.
POST /api/v1/soundtracks/uploads/{id}/finish moves the folder to MUSIC_PATH/<name>, runs syncSoundtrack for it, reloads the search cache and returns the new soundtrack (UUID, songs).
DELETE /api/v1/soundtracks/uploads/{id} cancels the upload. Uploads left unfinished are cleaned up after a day.
Syncing. Refuse uploads while a sync runs (IsSyncing()), and the other way around, so the two never touch the same folder.
Limits. Echo body limit for these routes; a total size cap per upload.
Tests. Integration tests like sync_integration_test.go: upload, finish, the soundtrack and songs are in the database; bad names; duplicate names; a cancelled upload leaves nothing behind.
Questions
The music folder is mounted from ResilioSync in compose.yaml. Is it mounted read-only in production? The server needs write access, and the new folder will then also be synced by Resilio to your other devices. Is that what you want?
Subfolders in an upload (discs) — keep them like the sync does today, or flatten them?
Should the frontend get an upload page too, or only MusicPlayer?
Let a client add a new soundtrack: it uploads the songs, the server writes them to a new folder in the music folder and adds them to the database, without waiting for the next sync.
## Feasibility
Yes. `SyncService` already has `syncSoundtrack(ctx, name)` and `syncSongs` for one folder, so after writing the files the server can sync just that folder.
## Plan
- **Endpoints** (token required):
1. `POST /api/v1/soundtracks/uploads` with `{"name": "Chrono Trigger"}` starts an upload.
- It checks that the name is a safe folder name (no `/`, `..` or hidden names) and that no soundtrack or folder of that name exists (409).
- It returns an upload ID. Files go to a temporary folder, e.g. `MUSIC_PATH/.uploads/<id>/`. Hidden folders are skipped by the sync.
2. `PUT /api/v1/soundtracks/uploads/{id}/files/{file name}` sends one song as the raw body. One request per song keeps requests small, and a failed song can be retried.
- Only audio types the sync accepts.
- Size limit per file (configurable).
- The file name is sanitized.
3. `POST /api/v1/soundtracks/uploads/{id}/finish` moves the folder to `MUSIC_PATH/<name>`, runs `syncSoundtrack` for it, reloads the search cache and returns the new soundtrack (UUID, songs).
4. `DELETE /api/v1/soundtracks/uploads/{id}` cancels the upload. Uploads left unfinished are cleaned up after a day.
- **Syncing.** Refuse uploads while a sync runs (`IsSyncing()`), and the other way around, so the two never touch the same folder.
- **Limits.** Echo body limit for these routes; a total size cap per upload.
- **Tests.** Integration tests like `sync_integration_test.go`: upload, finish, the soundtrack and songs are in the database; bad names; duplicate names; a cancelled upload leaves nothing behind.
## Questions
- The music folder is mounted from ResilioSync in `compose.yaml`. Is it mounted read-only in production? The server needs write access, and the new folder will then also be synced by Resilio to your other devices. Is that what you want?
- Subfolders in an upload (discs) — keep them like the sync does today, or flatten them?
- Should the frontend get an upload page too, or only MusicPlayer?
## Used by
- MusicPlayer: upload from the app, Sansan/MusicPlayer#50.
Sansan
added the feature label 2026-10-09 16:04:08 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Let a client add a new soundtrack: it uploads the songs, the server writes them to a new folder in the music folder and adds them to the database, without waiting for the next sync.
Feasibility
Yes.
SyncServicealready hassyncSoundtrack(ctx, name)andsyncSongsfor one folder, so after writing the files the server can sync just that folder.Plan
POST /api/v1/soundtracks/uploadswith{"name": "Chrono Trigger"}starts an upload./,..or hidden names) and that no soundtrack or folder of that name exists (409).MUSIC_PATH/.uploads/<id>/. Hidden folders are skipped by the sync.PUT /api/v1/soundtracks/uploads/{id}/files/{file name}sends one song as the raw body. One request per song keeps requests small, and a failed song can be retried.POST /api/v1/soundtracks/uploads/{id}/finishmoves the folder toMUSIC_PATH/<name>, runssyncSoundtrackfor it, reloads the search cache and returns the new soundtrack (UUID, songs).DELETE /api/v1/soundtracks/uploads/{id}cancels the upload. Uploads left unfinished are cleaned up after a day.IsSyncing()), and the other way around, so the two never touch the same folder.sync_integration_test.go: upload, finish, the soundtrack and songs are in the database; bad names; duplicate names; a cancelled upload leaves nothing behind.Questions
compose.yaml. Is it mounted read-only in production? The server needs write access, and the new folder will then also be synced by Resilio to your other devices. Is that what you want?Used by