Commit graph

761 commits

Author SHA1 Message Date
Your GitHub Name
220f991fae fix: prefer topic channel for album artist 2026-07-16 12:34:03 -07:00
Your GitHub Name
c104e30451 feat: add AlbumArtistPostProcessor to fill missing album-artist metadata 2026-07-15 15:40:36 -07:00
Alex Shnitman
fdfbfed5e2 fix: prevent playlist/channel title path traversal (closes GHSA-vh67-38x4-w8pc)
Sanitize path separators and .. segments in playlist/channel titles before they are baked into yt-dlp output templates, and refuse downloads whose resolved output directory escapes DOWNLOAD_DIR.
2026-07-13 23:07:39 +03:00
Alex Shnitman
3ea4732c5d fix: harden download lifecycle, subscriptions, and UI robustness
Addresses a full-project review. Backend correctness and availability:

- ytdl: cancel() only SIGKILLs the child's process group when the child
  actually became its own group leader, so a race (or failed setpgrp)
  can no longer kill the whole server; kill the group on cancel and on
  shutdown to avoid orphaned ffmpeg children
- ytdl: dedicated ThreadPoolExecutor for download supervision so active
  downloads can't starve extract_info / live probes on the default pool
- ytdl/main/subscriptions: route fire-and-forget tasks through a
  bg_tasks helper that keeps a strong ref and logs failures
- subscriptions: run flat-playlist extraction in an executor and check
  feeds with bounded concurrency so one slow feed can't block the loop;
  set last_checked on failure so broken feeds aren't retried every 60s
- main: validate ids on /start & /delete and numeric env vars at startup;
  return 400 (not 500) on bad subscriptions/update input; serve /history
  from memory; move get_custom_dirs off the event loop; restrict t=
  stripping to YouTube hosts; drop double percent-decode in state guard
- dl_formats/ytdl: enforce requested caption format via
  FFmpegSubtitlesConvertor and strip VTT header metadata only in the
  pre-cue region so real dialogue is preserved
- ytdl: throttle progress events, dedup adds against pending, clear
  filename/size on error and reject out-of-dir trashcan deletes, pin
  fork start-method on Linux only

Frontend:

- retry deletes the done record only after a successful re-add
- surface HTTP errors for delete/start and reset the deleting flag
- ignore late 'updated' events for rows no longer in the queue
- track table rows by map key; FileSizePipe uses base-1024

Also: HTTPS-aware Docker healthcheck, dead-code removal, and shared
helpers for path-containment and yt-dlp option merging. Adds/updates
unit tests throughout (250 backend tests passing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 08:08:14 +03:00
Alex Shnitman
e2c777842e fix: honor OUTPUT_TEMPLATE for channel downloads (closes #1024)
Detect YouTube channel tabs that yt-dlp reports as playlists so channel downloads use OUTPUT_TEMPLATE_CHANNEL and its empty fallback instead of OUTPUT_TEMPLATE_PLAYLIST.
2026-07-10 09:49:59 +03:00
Alex Shnitman
c34a18de7a upgrade dependencies 2026-07-10 09:48:48 +03:00
Alex
d6bcf182c5
Merge pull request #1023 from lanthaler/no-entries-archive
Don't mark a subscription as broken just because all entries are filtered out as they have already been downloaded
2026-07-09 08:17:00 +03:00
Markus Lanthaler
ad90609c9b Don't mark a subscription as broken just because all entries are filtered out as they have already been downloaded
This happens if archive.txt is used
2026-07-08 22:54:33 +00:00
Alex
5315630ab0
Merge pull request #1021 from mvanhorn/fix/960-atomic-store-nfs-eperm
fix: fall back to a direct write when AtomicJsonStore.save cannot use a temp file (NFS EPERM)
2026-07-05 21:26:49 +03:00
Matt Van Horn
54463baf0e
fix: fsync parent dir after direct-write fallback for durability parity 2026-07-05 04:11:12 -07:00
Matt Van Horn
b00d4785ee
fix: serialize state before truncating in the direct-write fallback 2026-07-05 04:04:54 -07:00
Matt Van Horn
96e88a3555
fix: force 0600 on fallback state rewrites, not just creation 2026-07-05 04:00:59 -07:00
Matt Van Horn
49a46a7d1c
fix: create fallback state file with owner-only 0600 permissions 2026-07-05 03:57:19 -07:00
Matt Van Horn
961b54aa83
fix: make fsync best-effort so only mkstemp/replace failures fall back 2026-07-05 03:53:22 -07:00
Matt Van Horn
e0549d6c24
fix: surface real storage errors from direct-write fsync fallback 2026-07-05 03:49:15 -07:00
Matt Van Horn
f315b75bb2
fix: limit atomic-write fallback to atomic-unsupported errnos 2026-07-05 03:44:57 -07:00
Matt Van Horn
c2c129db61
fix: fall back to direct write when atomic state save hits EPERM on NFS 2026-07-05 03:42:07 -07:00
Alex
363f159a0a
Merge pull request #1020 from alexta69/copilot/fix-dockerhub-build-push
Pin pnpm version to fix Docker build failure
2026-07-05 07:51:08 +03:00
copilot-swe-agent[bot]
38c0ca22f4
Pin pnpm version in packageManager field to fix Docker build
corepack prepare pnpm --activate without a version was resolving to
12.0.0-alpha.0 (broken pre-release), causing the dockerhub-build-push
job to fail. Adding packageManager field pins it to a stable release.
2026-07-05 04:21:32 +00:00
copilot-swe-agent[bot]
24ae8f0742
Initial plan 2026-07-05 04:18:28 +00:00
AutoUpdater
0a946cc352 upgrade yt-dlp from 2026.6.9 to 2026.7.4 2026-07-05 00:28:09 +00:00
Alex Shnitman
51fd203b71 upgrade to Angular 22 2026-06-28 21:12:20 +03:00
Alex Shnitman
d136344c26 upgrade dependencies 2026-06-28 21:08:08 +03:00
dependabot[bot]
33f1412fac Bump actions/checkout from 6 to 7 in the github-actions group
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-28 21:06:58 +03:00
Alex Shnitman
ce897ee009 fix open download of cookie files 2026-06-20 09:52:34 +03:00
Alex Shnitman
dd1b4c2436 upgrade dependencies 2026-06-20 09:52:34 +03:00
Alex
8752b500d6
Merge pull request #1004 from akeeton/docker-audio-download-dir
Create AUDIO_DOWNLOAD_DIR in Docker image
2026-06-18 06:45:50 +03:00
Andrew Keeton
04b9366764 Incorporate PR feedback
Move the default assignment of AUDIO_DOWNLOAD_DIR from the Dockerfile to docker-entrypoint.sh, and change the default value from "/downloads" to $DOWNLOAD_DIR.
2026-06-17 17:17:44 -04:00
Alex Shnitman
b73e95f405 upgrade dependencies 2026-06-16 21:57:07 +03:00
Alex Shnitman
64d0d62878 fix empty PUBLIC_HOST_AUDIO_URL handling (closes #1010) 2026-06-16 21:47:07 +03:00
Alex Shnitman
37f7af0555 fix batch download (closes #1008) 2026-06-16 21:37:05 +03:00
Alex Shnitman
5aa7d033e2 review fixes 2026-06-16 21:35:07 +03:00
Alex Shnitman
5429200fba support live streams (closes #302, closes #752, closes #978) 2026-06-13 17:39:14 +03:00
Alex Shnitman
72d60ea55a upgrade dependencies 2026-06-12 12:45:38 +03:00
Alex Shnitman
a9b2e07a59 nightly release README update 2026-06-12 10:16:19 +03:00
Andrew Keeton
d157444877 Create AUDIO_DOWNLOAD_DIR in Docker image 2026-06-11 17:22:55 -04:00
AutoUpdater
e30a24ff70 upgrade yt-dlp from 2026.3.17 to 2026.6.9 2026-06-10 00:36:22 +00:00
Alex Shnitman
ee20512410 add option for following nightly yt-dlp releases (closes #999) 2026-06-06 09:42:26 +03:00
Alex Shnitman
897d52cd0d styling improvements 2026-05-30 15:35:52 +03:00
Alex Shnitman
baa72c0e94 fix pnpm upgrade to the correct package age limit 2026-05-29 14:36:05 +03:00
Alex Shnitman
66d8fa570b Merge branch 'pr-977' 2026-05-29 14:14:05 +03:00
Alex Shnitman
cf2d2dd465 review fixes 2026-05-29 14:13:47 +03:00
Alex Shnitman
0b5617e96c Merge branch 'pr-990' (iOS Web Share for completed downloads) 2026-05-29 13:25:22 +03:00
Alex Shnitman
56c0ad3b5f fix catch 2026-05-29 13:23:25 +03:00
Alex Shnitman
4478d1394e upgrade dependencies 2026-05-29 13:20:04 +03:00
Helmut
ad92607a21 fix(ui): drop redundant tooltip on share button
iOS doesn't have hover, so the tooltip only ever showed on desktop —
where the share-arrow glyph is universally recognised anyway. Aria-
label stays for screen readers.
2026-05-29 05:24:49 +02:00
Helmut
6ff364aacf feat(ui): warn before share + surface failures for large files
Web Share fails silently when iOS' share sheet refuses the payload,
typically because the file exceeds the platform's soft size limit
(~50–100 MB depending on iOS version). The previous patch logged to
the console but the user saw nothing — staring at a button that
'does nothing' is poor UX.

Adds two layers of feedback:

1. Pre-flight size check (SHARE_SIZE_WARN_BYTES = 80 MB, conservative
   relative to iOS' actual limit) with a confirm() dialog before the
   fetch. Avoids spending bandwidth pulling a 150 MB blob into the
   browser only for navigator.canShare to reject it.

2. Surfaces canShare-rejection AND share()-failure as a visible
   alert() suggesting the user fall back to the download link next
   to the share button.

Tested locally with files from 0.7 MB up to 150.7 MB: small files
share unchanged, the 150 MB file now produces a pre-flight warning
the user can dismiss, and any subsequent rejection produces a clear
alert instead of silently no-op'ing.
2026-05-29 04:56:52 +02:00
Helmut
39a8948976 feat(ui): add iOS Web Share button next to download link
Adds a share button to the completed-list action row that hands the
downloaded file off to the platform share sheet via navigator.share().
On iOS Safari/Chrome this surfaces the native Save-to-Photos / Save-to-
Files / AirDrop options for videos and images, and Files / 3rd-party
app targets for audio. On platforms without Web Share support (Desktop
Firefox/Chrome/Safari) the button hides itself; the existing download
link remains the universal fallback.

Implementation notes:
- canShareDownloads() requires both navigator.share AND navigator.canShare
  (Desktop Safari has the former without the latter; we always intend
  to share a file, not a URL)
- shareDownload() fetches the file via the existing buildDownloadLink()
  helper, wraps it in a File, then runs canShare() before share() so we
  can bail out cleanly on platforms that reject the MIME type
- AbortError (user dismisses sheet) is silenced; other errors logged
- Tooltip on the button explains the iOS behaviour briefly

Refs alexta69/metube#582 — addresses the 'add to Photos.app' request
without depending on the iOS Shortcut, which has had reliability issues
(cf #763).
2026-05-28 07:34:13 +02:00
Sean McCollum
f0348581c2 remove circle and make labels with help text have an underline 2026-05-25 00:13:12 -07:00
Sean McCollum
e2773db65a make ui more mobile mobile-friendly
Remove popovers and replace with question icons you have to click
Replace combobox in output > Download Folder with an autocomplete
2026-05-04 10:42:17 -07:00