| Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Add *slog.Logger to podcastService with NewPodcastServiceWithLogger.
- Wire logger from cmd/player main.go.
- Run CheckFeeds concurrently: one goroutine per feed with WaitGroup.
- Add structured logging for start/finish per feed and overall count.
- Log feed failures at Warn level so they are visible but not fatal.
- Ensure nil logger safety with slog.Default fallback.
- Add tests: empty list, concurrent OK, list error, single feed error,
all feeds error.
|
|
Refactor ~112-line DownloadEpisode into four focused helpers:
- resolveEpisodeAndSet: permission + path building
- buildEpisodePath: filename logic
- downloadEnclosure: HTTP fetch to disk
- persistDownloadedEpisode: DB + probe + cleanup
Also: pass ctx through to HTTP request via NewRequestWithContext.
Added tests for happy path, 404, and missing episode/feed/set.
|
|
|
|
SubscribeFeed was ~100 lines and did too much: admin check, feed parsing,
filesystem setup, DB set creation, permission grant, feed creation, cover
download, episode insertion, and marking checked.
Refactored into focused helpers:
- verifyAdmin – admin gate
- resolveSetPath – sanitize name and build disk path
- createPodcastSet – mkdir, create set row, grant owner perm
- rollbackSet – delete set row + remove directory
- createPodcastFeed – insert feed row
- insertPodcastEpisodes – bulk insert parsed episodes
Injected dependency fields (parseFeed, parseFeedReader, downloadCover)
into podcastService so unit tests can replace them with fakes instead of
hitting real HTTP or disk.
Added internal/service/podcast_test.go with coverage for:
- happy path SubscribeFeed
- non-admin rejection
- user lookup error
- feed parse error
- set creation error (directory cleaned up)
- grant permission error (rollback)
- feed creation error (rollback)
- resolveSetPath / sanitize helpers
- DownloadEpisode permission check
- upsertFeedEpisodes (new + skip existing)
- updateFeedFromParsed
- insertPodcastEpisodes
|
|
(task z0)
|
|
Adds the Go race detector to the default Test target in Magefile.go
and includes -count=1 to avoid stale cached results. This improves
reliability for concurrent code paths and CI runs.
Refs: v0
|
|
- Covers ParseFeed, ParseFeedReader, parsedFeedFromGoFeed, extractImageURL,
parseDuration, DownloadCoverImage.
- Positive and negative tests (invalid XML, HTTP errors, network errors,
bad enclosure length, zero duration, nil pubDate, empty file size,
file write/read body errors, missing cover URL).
- Achieves 100% statement coverage for the package.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fails for cover.jpg
When scanning image files (e.g. cover.jpg in audiobook folders),
thumbnailForImage can fail or produce a missing .thumbnails/cover.jpg.
This caused broken thumbnails in the grid.
- scanner.go buildThumbnailPath: after generating an image thumbnail,
verify the output file exists via fs.Stat. If it does not exist,
fall back to using the original image path as the thumbnail_path.
- browse.go GetThumbnail: if os.Stat(ThumbnailPath) fails and the
media type is image, fall back to serving the original AbsPath.
All tests pass.
|
|
|
|
|
|
|
|
- In fullscreen, press 'c' to toggle object-fit between contain (default)
and fill (stretches to fill, no aspect ratio preservation).
- Adds .player.crop-mode video { object-fit: fill; } in player.css.
- Adds toggleCrop() in player.js that toggles a crop-mode class and a
small UI indicator (✂️) in the controls, visible only in fullscreen.
- Resets crop mode back to contain when exiting fullscreen (via Escape,
minimize, or fullscreenchange event).
- Wires the 'c' hotkey in keyboard.js and registers toggleCrop in app.js.
- Adds crop-indicator to index.html and detach.html controls, and
documents the shortcut in the help modal.
|
|
|
|
|
|
- Fix boolean scanning from SQLite INTEGER columns (intToBool helper)
- Fix BrowseSet LIMIT 0 returning zero episodes (use 1000 instead)
- Fix checkFeed double-fetch by parsing from resp.Body directly
+ Add ParseFeedReader for body reuse
- Fix file handle leak in DownloadEpisode (explicit Close before ImportMediaFile)
- Fix incomplete rollback in DownloadEpisode (remove file + delete media row)
- Fix 204 No Content handler writing 'null' body
- Fix DownloadCoverImage to accept *http.Client with timeout
- Deduplicate uniqueFilename into shared internal/service/filename.go
- Wire frontend renderPodcastEpisodes into renderBrowse from API data
- Refactor podcasts.js: remove extra API call, fix toggle toast, remove duplicate toast
- Add Config.PodcastCheckMinutes + PODCAST_CHECK_INTERVAL_MINUTES env var
- Start background CheckFeeds goroutine in main.go with ticker
- Update NewPodcastService to accept checkInterval parameter
- Log errors from CheckFeeds and episode creation instead of silently discarding
|
|
|