feat(api): streaming, transcoding, events, history and likes (M3)
- tracks carry a stream_url signed for the user for 12 h and the user's reaction; /stream checks the signature, expiry and that the user is not blocked, then hands the file to nginx by X-Accel-Redirect (or serves it with Range support when X_ACCEL=false) - original by default; formats browsers can't play and explicit high/medium/low go through Opus transcoding, never upwards: a lossy source under the target bitrate stays original; transcodes are cached per file and size, deduplicated in flight, limited by TRANSCODE_CONCURRENCY and trimmed hourly by LRU to the size limit - /events takes up to 500 events with client UUIDs, drops repeats and events older than 30 days, counts plays (≥ half or 4 min, or finished), early skips and history entries (≥ 30 s) - history with clearing, likes and dislikes with cursors and totals, track reactions, playback state with last-write-wins, tracks batch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8b76aa3964
commit
c05e523cbe
16 files changed
+3913
-155
No files matched your search
@@ -88,7 +88,9 @@ func Middleware(svc *Service, log *slog.Logger) func(http.Handler) http.Handler
|
||||
r.ContentLength = 2
|
||||
}
|
||||
// Обложки открывает <img> без заголовка Authorization — ссылку защищает подпись.
|
||||
cover := r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/api/v1/covers/")
|
||||
// Аудио открывает <audio> — тоже без заголовка; ссылка подписана для пользователя.
|
||||
cover := (r.Method == http.MethodGet || r.Method == http.MethodHead) &&
|
||||
(strings.HasPrefix(r.URL.Path, "/api/v1/covers/") || strings.HasPrefix(r.URL.Path, "/api/v1/stream/"))
|
||||
if !strings.HasPrefix(r.URL.Path, "/api/v1/") || publicRoutes[route] || cover {
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user