Commit Graph

85 Commits

Author SHA1 Message Date
ShukeBta 542e85a067 fix: reduce emby load and stabilize strm scan 2026-06-11 00:18:51 +08:00
ShukeBta 859d6e9d24 implement automatic strm generation 2026-06-10 21:36:55 +08:00
ShukeBta fd0428ee7d fix cloud library mounts and artwork caching 2026-06-10 20:43:42 +08:00
ShukeBta 0bf983cec8 fix: improve cloud mount scanning feedback 2026-06-10 18:46:30 +08:00
ShukeBta 0f82cb3084 feat: improve OpenList cloud storage support 2026-06-10 00:08:35 +08:00
ShukeBta eab8c3c709 feat: add clouddrive2 storage bridge 2026-06-09 20:22:00 +08:00
ShukeBta bfb0243712 fix: limit ffprobe concurrency 2026-06-09 19:18:21 +08:00
ShukeBta 7d7f3cc758 feat: add cloud transfer and cache optimizations 2026-06-09 19:03:28 +08:00
ShukeBta a55fc502ca feat: add configurable scraper throttling 2026-06-09 17:56:25 +08:00
ShukeBta 76fe0dbde9 feat: scrape metadata after organize 2026-06-09 17:00:24 +08:00
ShukeBta fe0e7a09ce fix: improve media file organization workflow 2026-06-09 13:57:34 +08:00
ShukeBta 2e26b71478 fix: add organize ingest action 2026-06-08 10:39:02 +08:00
ShukeBta dea45c5423 fix: load full poster wall media 2026-06-07 22:46:57 +08:00
ShukeBta 8c8d472524 fix: add smart download classification 2026-06-07 21:34:21 +08:00
ShukeBta a5d061afa6 refactor: split site adapters and site page modules 2026-06-07 18:55:51 +08:00
ShukeBta df02fd1166 fix: harden bot accounts and download handling 2026-06-07 18:30:27 +08:00
ShukeBta 33698daa3f refactor: split oversized route and subscription modules 2026-06-07 14:59:32 +08:00
ShukeBta d77e890f51 fix(app): close feature association gaps 2026-06-07 12:55:27 +08:00
ShukeBta b38d47a27d feat(bot): manage device policy via telegram commands 2026-06-07 12:24:21 +08:00
ShukeBta cf2f77f35d chore(repo): add lint config and normalize scripts 2026-06-07 11:54:45 +08:00
ShukeBta d94330b30f fix(subscription): prevent duplicate qb downloads 2026-06-07 10:05:58 +08:00
shuk shuk 22b64d3d47 fix(organize): strip release tags/roman numerals/season markers; de-hardcode paths
feat(bot): button menu, capacity/open-reg quota, redemption codes, user mgmt,
account expiry + signin streak, device anti-sharing + inactivity cleanup,
one-click kick, self-service username/password

- Consolidate organize/rename defaults into Tools panel

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-07 09:54:14 +08:00
soldosluka857 f1d87638f3 fix(subscription): apply rules on RSS path, dedup movies via library, MoviePilot-style default excludes
- runOne (RSS) now applies matchesSubscriptionRules so ExcludeWords/Resolution/Quality/Effects/ReleaseGroups take effect (previously only the Filter regex ran, so editing 排除 had no effect on RSS subscriptions)
- movie candidate selection now consults library availability: non-wash subscriptions skip titles already in the library, stopping repeated downloads of 10bit/Dolby releases (aligns with MoviePilot 'download once = satisfied')
- add MoviePilot-style default exclude list (cam/ts/枪版/trailer/sample...) merged with user excludes; latin tokens matched on word boundaries to avoid substring false positives
- frontend: send rule fields as raw strings on edit so 排除词 can be cleared/changed (was dropped by '|| undefined')

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 23:14:22 +08:00
ShukeBta de3f1f3bb4 fix: honor licensed user limits 2026-05-30 21:48:09 +08:00
soldosluka857 74271081f4 feat(cloud): 115/夸克网盘 providers with cookie + QR login and 302 playback
Add a pluggable cloud-disk subsystem (internal/service/cloud) exposing remote
files as playable media via HTTP 302 redirects, so the host never transcodes
nor (by default) streams the bytes:

- quark (夸克网盘): cookie auth, directory listing + download_url resolution.
- cloud115 (115 网盘): cookie auth + QR-code login flow (token/poll/exchange);
  pickcode → CDN URL resolved for 302 offload.
- StorageConfigService gains cloud types, Ping() probes, List/Resolve/Import.
- New endpoints: admin /cloud/:type/{list,import,qr/start,qr/poll} and authed
  /cloud/play/:type (302 redirect, or reverse-proxy when the link needs auth
  headers). Imported files become Media rows with STRMURL → the play endpoint.
- Frontend: 115网盘/夸克网盘 tabs with cookie input, 115 QR-code login, a cloud
  file browser and one-click 302 import.

Providers are exercised against httptest mock servers (list/resolve/QR state
machine). Live login + playback require a real cloud account.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 21:04:23 +08:00
soldosluka857 e50282178d feat(playback): client direct-play decode mode (release host transcoding)
Add an admin toggle playback.direct_only that offloads all decoding to the
client. When enabled:
- Emby PlaybackInfo no longer advertises SupportsTranscoding nor a
  TranscodingUrl, forcing Emby/Infuse/Yamby clients to direct play.
- HLS endpoints refuse (ErrTranscodeDisabled) so the host never spawns ffmpeg.
- Web player forces direct play, hides the HLS toggle, and surfaces a hint.
Exposed via /system/info (direct_play_only) and the Settings page.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 21:04:23 +08:00
Shuke 48aa08fc94 Revert "feat(playback): client direct-play decode mode (release host transcoding)"
This reverts commit 8fd2ab4b51.
2026-05-30 21:04:03 +08:00
Shuke 6a9096d3aa Revert "feat(cloud): 115/夸克网盘 providers with cookie + QR login and 302 playback"
This reverts commit c6455103e6.
2026-05-30 21:04:03 +08:00
soldosluka857 c6455103e6 feat(cloud): 115/夸克网盘 providers with cookie + QR login and 302 playback
Add a pluggable cloud-disk subsystem (internal/service/cloud) exposing remote
files as playable media via HTTP 302 redirects, so the host never transcodes
nor (by default) streams the bytes:

- quark (夸克网盘): cookie auth, directory listing + download_url resolution.
- cloud115 (115 网盘): cookie auth + QR-code login flow (token/poll/exchange);
  pickcode → CDN URL resolved for 302 offload.
- StorageConfigService gains cloud types, Ping() probes, List/Resolve/Import.
- New endpoints: admin /cloud/:type/{list,import,qr/start,qr/poll} and authed
  /cloud/play/:type (302 redirect, or reverse-proxy when the link needs auth
  headers). Imported files become Media rows with STRMURL → the play endpoint.
- Frontend: 115网盘/夸克网盘 tabs with cookie input, 115 QR-code login, a cloud
  file browser and one-click 302 import.

Providers are exercised against httptest mock servers (list/resolve/QR state
machine). Live login + playback require a real cloud account.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 20:23:55 +08:00
soldosluka857 8fd2ab4b51 feat(playback): client direct-play decode mode (release host transcoding)
Add an admin toggle playback.direct_only that offloads all decoding to the
client. When enabled:
- Emby PlaybackInfo no longer advertises SupportsTranscoding nor a
  TranscodingUrl, forcing Emby/Infuse/Yamby clients to direct play.
- HLS endpoints refuse (ErrTranscodeDisabled) so the host never spawns ffmpeg.
- Web player forces direct play, hides the HLS toggle, and surfaces a hint.
Exposed via /system/info (direct_play_only) and the Settings page.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 20:23:55 +08:00
soldosluka857 f0bc066134 feat(telegram): admin-toggleable Bot registration + remove duplicate 最近入库 on 运行状态
- Add telegram.registration_enabled setting (default off); admins toggle via
  Settings page or /registration on|off bot command.
- Add /register (/reg /signup) bot command: when enabled, regular users can
  create a MediaStation account and auto-bind their Telegram. Reuses AuthService
  (username-taken / user-limit handling) and keeps new accounts as regular users.
- Regular users still limited to bind / adult-toggle / start / help; all other
  commands remain admin-only.
- Update /start and /help text to surface registration when enabled.
- Remove the duplicate 最近入库 module from the 运行状态 (stats) page; the homepage
  already shows recently added.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 18:34:00 +08:00
soldosluka857 d03f84e78d feat(organize): organize arbitrary source dir (e.g. downloads) with dedup + 洗版
- Add OrganizeDirectory service: walk an arbitrary source directory (download
  dir / NAS direct-read path) and organize video files into the destination,
  without requiring the source to be a registered library.
- Dedup: skip media already present in the destination (matched by scanned DB
  identity title+year[/season+episode], robust to dir case/layout, plus a
  filesystem folder fallback).
- 洗版 (resolution replacement): when the source resolution is higher than the
  existing version, replace the lower-res file (+NFO sidecar +DB row). Prefers
  scanned dimensions, then ffprobe, then filename token; never replaces on
  unknown resolution.
- New endpoints: GET /admin/organize/sources (download/media dir candidates)
  and POST /admin/organize/source.
- UI: ToolsPage adds a '整理来源目录(去重+洗版)' form so operators can pick the
  download dir as the organize source.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 16:29:15 +08:00
soldosluka857 8f0c6d2324 feat(organize): separate source dir from destination dir (从源目录整理到目的地目录)
Previously organize only exposed a single 'target dir' that was actually
the destination, conflating 源目录 (where files to organize live) with
目的地目录 (where organized files go). Add an explicit source directory:

- OrganizeOptions gains SourcePath; DestPath replaces the old TargetPath
  (destination) for clarity. New organize.source_dir setting + source_path
  request override; resolveSourceRoot falls back to library path.
- OrganizeLibraryWithOptions only organizes media located under the source
  root, so operators can point at a specific download/staging folder and
  organize into a distinct destination.
- Handler accepts source_path/dest_path (target_path kept as a deprecated
  alias for the destination, backward compatible).
- Settings page splits into 整理源目录(待整理) + 整理目的地目录; Tools organize
  panel exposes 源目录 + 目的地目录 inputs with clear copy.

Defaults are unchanged (source = destination = library path) so existing
setups behave identically. Adds a regression test that organize is scoped
to the source directory.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 13:02:36 +08:00
soldosluka857 b2ccd04844 fix(dlna): always return non-nil device slice so API serializes [] not null
The DLNA device list endpoint could return {"devices":null} in two cases:
the SSDP-failure path returned a nil slice, and the cached path copied an
empty cache via append([]DLNADevice(nil), cache...) which also yields nil.
The web UI reads res.devices.length, so a null devices field crashed the
DLNA page to a white screen. Return non-nil slices in both paths and guard
the frontend with a null coalesce. Adds a regression test.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 13:02:16 +08:00
soldosluka857 b9b7b7052a feat(organize/scan): transfer modes, seeding-safe relocation, inode dedup, incremental scanning
- Organizer: add move/copy/hardlink/symlink transfer modes (default move),
  per-request target_path/transfer_mode overrides, and honor organize.target_dir
  / organize.transfer_mode settings.
- keep_seeding (default on): escalate move->hardlink (cross-device->copy) so the
  qBittorrent source stays in place and continues seeding after organize.
- qBittorrent SetLocation + POST /downloads/relocate to migrate whole torrents
  while keeping them seeding.
- Scanner: FileID (device:inode) hardlink dedup to avoid duplicate recognition
  and double-counted storage; extract single-file ingest.
- Watcher: recursive watch + incremental per-file ingest/remove instead of full
  re-scan; periodic full library scan now gated behind scan.periodic_enabled
  (default off) to reduce disk wear.
- Telegram bot: handle callback_query in polling, declare allowed_updates in
  webhook, answer callbacks.
- Frontend: settings for transfer mode / keep_seeding / periodic scan; organize
  panel target dir + transfer mode overrides.
- Tests for transfer modes, organizer resolution, SetLocation, inode dedup,
  incremental ingest/remove.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 12:01:46 +08:00
ShukeBta d35086f49d fix: hide adult libraries across dashboard views 2026-05-30 03:50:52 +08:00
ShukeBta e8c2cf1ea4 fix: require password only for adult visibility changes 2026-05-30 03:45:01 +08:00
ShukeBta ce9abf6306 fix: repair user password reset and recreate flow 2026-05-30 03:33:36 +08:00
ShukeBta 99ecae0c44 fix: add global adult library visibility controls 2026-05-30 03:24:08 +08:00
ShukeBta f8ef35c8e1 fix: stabilize telegram bot proxy and legacy permissions 2026-05-30 02:54:25 +08:00
ShukeBta 67ba1bdcce fix: clarify telegram member binding permissions 2026-05-30 02:19:22 +08:00
ShukeBta 3c946559f5 fix: simplify telegram channel access rules 2026-05-30 02:16:18 +08:00
ShukeBta 7e01c42857 fix: improve telegram channel connectivity 2026-05-30 02:07:09 +08:00
ShukeBta be6b8bf27f fix: tighten telegram channel binding 2026-05-30 01:54:26 +08:00
ShukeBta b5e11b6938 fix: secure adult visibility and telegram bot access 2026-05-30 01:39:11 +08:00
ShukeBta 99fe7329f7 fix: isolate play profiles per user 2026-05-29 15:56:51 +08:00
ShukeBta 633a8cf715 fix: enforce adult profile pin visibility 2026-05-29 15:16:20 +08:00
ShukeBta 931db7a242 fix: handle wrapped permission responses 2026-05-29 14:11:51 +08:00
ShukeBta a8395c9de7 fix: enforce transcoding resource controls 2026-05-29 13:54:19 +08:00
ShukeBta 27df93fa3d feat: add licensing and access controls 2026-05-29 12:47:54 +08:00