Commit Graph

1823 Commits

Author SHA1 Message Date
Estrella Pan
0dd8ce99ad test: add regression tests for issues #992 and #1005
- #992: title_parser returns None for non-episodic resources instead of crashing
- #1005: BangumiDatabase.search_official_title method exists and works correctly

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 08:14:06 +01:00
Estrella Pan
d980c3c714 fix(parser): handle None return from raw_parser to avoid AttributeError (#992)
When raw_parser fails to parse non-episodic resources (movies, collections),
it returns None. Add guard clause in title_parser to skip these gracefully
instead of crashing on attribute access. Downgrade log level from error to
info since this is expected behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 08:12:18 +01:00
Estrella Pan
66a2b45f57 Merge remote-tracking branch 'origin/3.2-dev' into 3.2-dev 2026-03-01 08:07:26 +01:00
Estrella Pan
1d35b654e7 Merge pull request #998 from HuajunGao/fix/bangumi-search-official-title 2026-03-01 08:02:40 +01:00
Estrella Pan
ccafd04432 Merge pull request #1003 from EstrellaXD/3.2-dev
Release 3.2.5
3.2.5
2026-02-28 22:52:18 +01:00
Estrella Pan
61ff20fef6 fix(api): preserve masked passwords on config save and allow private IPs in setup (#995, #1001)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:48:38 +01:00
Estrella Pan
17de8fa8fe Merge pull request #1000 from HuajunGao/fix/mcp-sse-none-response
Thanks for catching this! Clean fix for the SSE disconnect issue.
2026-02-28 22:46:44 +01:00
Estrella Pan
903ecaf84a Merge pull request #999 from HuajunGao/fix/default-filter-regex
Thanks for the fix! The regex alignment makes sense.
2026-02-28 22:46:42 +01:00
Estrella Pan
62ee9f02ec Merge pull request #997 from HuajunGao/fix/config-sensitive-field-overwrite 2026-02-28 22:32:00 +01:00
HuajunGao
ab64186a38 fix(mcp): return Response() from handle_sse to prevent NoneType error
When an MCP client disconnects, Starlette tries to call the return value
of the handle_sse endpoint as an ASGI response. Since the function had
no return statement it returned None, causing:

  TypeError: 'NoneType' object is not callable

The mcp library's own SseServerTransport docstring explicitly documents
this requirement. Fix by adding 'return Response()' and importing
starlette.responses.Response.
2026-02-28 14:54:43 +11:00
HuajunGao
a263c0821e fix(config): align default filter regex from \d+-\d to \d+-\d+
The per-bangumi default in Bangumi model already uses \d+-\d+ to filter
batch/collection torrents (e.g. '01-13'). The global RSSParser default
was inconsistently using \d+-\d (one fewer +), which has subtly different
matching behaviour.

Align both defaults to \d+-\d+ for consistency.
2026-02-28 14:32:59 +11:00
HuajunGao
d4e50509dd fix(database): add missing search_official_title method to BangumiDatabase
BangumiDatabase.search_official_title() was called in
notification/manager.py (_get_poster) but never implemented,
causing a RenameThread crash:

  'BangumiDatabase' object has no attribute 'search_official_title'

Add the method as a simple exact-match lookup on Bangumi.official_title,
consistent with the existing search_id / search_rss pattern.
2026-02-28 12:14:50 +11:00
HuajunGao
6fb8421000 fix(config): restore sensitive fields before saving to prevent credential overwrite
When GET /config/get returns config to the frontend, sensitive fields
(password, token, api_key, secret) are masked as '********'.  If the
user changes any non-sensitive setting (e.g. ssl: true → false) and
saves, the frontend sends back the masked placeholder verbatim.  The
backend was saving it directly, overwriting the real credential with
the literal string '********', breaking authentication silently.

Add _restore_sensitive() to substitute any '********' placeholder with
the current in-memory value before writing to disk.  Non-sensitive
fields and genuinely new values are unaffected.

Fixes #995
2026-02-28 11:40:25 +11:00
Estrella Pan
e1b90c9eec 3.2.4
3.2.4
3.2.4
2026-02-24 19:56:57 +01:00
Estrella Pan
ded24b10da fix(downloader): fix qBittorrent SSL connection and rename verification (#923)
- Decouple HTTPS scheme selection from TLS certificate verification:
  `verify=False` always, since self-signed certs are the norm for
  home-server/NAS/Docker qBittorrent setups
- Bump connect timeout from 3.1s to 5.0s for slow TLS handshakes
- Add actionable error messages when HTTPS connection fails
- Fix `continue` → `break` bug in torrents_rename_file verification loop
- Consolidate json imports to top-level
- Add 31 unit tests for QbDownloader constructor, auth, and error handling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:52:50 +01:00
Estrella Pan
fe1858f0e6 fix(webui): close EventSource and clear timers on component unmount
Prevent memory leaks by ensuring the search EventSource connection is
closed when the modal unmounts and setTimeout handles are cleared in
copy-to-clipboard flows across modal components.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:44:49 +01:00
Estrella Pan
ead16ba4cf feat(parser): add fallback episode parser for TITLE_RE failures (#876, #910, #773)
Add _fallback_parse() tried when TITLE_RE.match() returns None, using two
regex patterns to extract episode numbers from formats the main regex misses:
- digits before [ bracket (issues #876, #910)
- compound [02(57)] format (issue #773)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:12:24 +01:00
Estrella Pan
c261caa022 test(parser): add regression tests for issue #990
10 tests covering the full bug chain:
- raw_parser misparses leading number as episode
- TitleParser.raw_parser returns None for unparseable titles
- add_title_alias rejects None and empty string
- _get_aliases_list filters null values from JSON
- get_all_title_patterns skips None title_raw
- match_torrent and match_list handle corrupted data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 08:44:18 +01:00
Estrella Pan
c7206a351f fix(parser): prevent crash on titles starting with numbers (#990)
Titles like "29 岁单身冒险家的日常" cause the regex to match the leading
number as episode, leaving title_raw as None. This cascades into storing
null aliases and crashing match_torrent with TypeError.

- Fall back to title_jp when title_en and title_zh are both None
- Return None from raw_parser when no title can be extracted
- Reject None/empty aliases in add_title_alias
- Filter null values from parsed title_aliases JSON
- Skip None title_raw in get_all_title_patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 08:36:25 +01:00
Estrella Pan
b57d3c49ae feat(security): add security config UI and improve auth/MCP security
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:19:14 +01:00
Estrella Pan
a0bf878b7e feat(calendar): add drag-and-drop to assign unknown bangumi to weekdays
Allow users to drag bangumi cards from the "Unknown" section into weekday
columns in the calendar view. Manual assignments are locked so calendar
refresh from Bangumi.tv doesn't overwrite them. A reset button lets users
unlock and send cards back to Unknown.

Backend:
- Add weekday_locked field to Bangumi model (migration v9)
- Add PATCH /api/v1/bangumi/{id}/weekday endpoint
- Skip locked items in refresh_calendar()

Frontend:
- Add vuedraggable for smooth drag-and-drop
- Pin indicator and unpin button on manually-assigned cards
- Drop zone highlighting during drag
- i18n strings for drag/pin/unpin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 14:21:00 +01:00
Estrella Pan
ba61194d3d Merge pull request #972 from EstrellaXD/3.2-dev
3.2.3
3.2.3
2026-02-23 12:57:06 +01:00
Estrella Pan
326d31dd0f Merge origin/main into 3.2-dev (resolve version conflict)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:55:18 +01:00
Estrella Pan
b1497aa6b1 fix(test): invalidate module-level bangumi cache between tests
The BangumiDatabase.search_all() uses a module-level TTL cache that
persists across tests using different in-memory SQLite databases.
This caused test_migrate_preserves_existing_data and test_migrate_idempotent
to return stale cached results (1 bangumi instead of 2).

Add an autouse fixture in conftest.py to clear the cache before and after
each test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:11:28 +01:00
Estrella Pan
eefe85db4b chore: bump version to 3.2.3 and update changelog for release
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:06:30 +01:00
Estrella Pan
adf44d140a fix(renamer,rss): preserve episode 0 specials and handle invalid filter regex
- Skip episode offset for episode 0 (specials/OVAs) to prevent overwriting
  regular episodes (fixes #977)
- Catch re.PatternError in RSS filter compilation and fall back to literal
  matching when user filter contains invalid regex chars (fixes #974)
- Remove Aria2 and Transmission from README supported downloaders list
  (addresses #987)
- Add regression tests for issues #974, #976, #977, #986

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:03:59 +01:00
Estrella Pan
e82e6ab128 fix(ui): fix auth routing, i18n init, and component lifecycle issues
- useAuth: replace watcher with explicit router.replace on login/logout
- useMyI18n: create single i18n instance at module level (avoid dupes)
- usePasskey: detect WebAuthn support synchronously (no onMounted)
- main.ts: import i18n from hook module instead of calling composable
- ab-add-rss: hoist useApi composables outside functions to avoid
  recreating them on each call
- calendar: prevent duplicate refreshes when already refreshing
- downloader: guard interval polling against stale activation state
- router: only mark setupChecked on successful status check
- log store: stop SSE log updates on logout
- i18n: add missing "edit" translation key (en + zh-CN)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:46:56 +01:00
Estrella Pan
52580d08c8 fix(downloader): improve client interfaces and renamer reliability
- Aria2: add stub methods for full duck-typing compatibility
- MockDownloader: add verify parameter to rename_file signature
- DownloadClient: raise ConnectionError on auth failure
- Path: fallback bangumi_name from torrent_name when path is flat
- Renamer: remove unused check_pool and dead compare_ep_version
- Pass torrent_name to _path_to_bangumi for better name resolution
- Remove check_pool unit test (feature removed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:46:44 +01:00
Estrella Pan
41298f2f8e fix(backend): improve database migrations, parsers, and network handling
Database:
- Add error handling and per-step version tracking in migrations
- Enable SQLite foreign keys via PRAGMA on connect
- Fix SQLAlchemy .is_(None) usage, add session.merge() for detached
- Batch commit for semantic alias merges
- Quote table/field names in fill-null-defaults SQL
- Guard against empty user data in migration

Parsers:
- TMDB: bounded LRU cache (512), asyncio.gather for parallel season
  fetches, fix season regex \d -> \d+, null-safe year, fix id shadowing
- Raw parser: re.escape() for group/prefix regex, None guard on match
- OpenAI: handle Pydantic model_dump, catch ValueError

Network:
- Null-safe get_html() return
- Error handling per RSS item in mikan parser
- Progressive retry delays (5/15/45/120/300s) with specific exceptions
- Platform detection via sys.platform instead of path heuristic
- Move filter cache to instance variable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:46:35 +01:00
Estrella Pan
ec4aca5aba fix(core): improve program lifecycle and background task management
- Use per-task stop events instead of shared stop_event to prevent
  stopping one task from killing all others
- Track running state via _tasks_started flag instead of stop_event
- Add error handling in RSS, rename, scan, and calendar loops
- Make restart() resilient to stop failures (catch and continue)
- Cache downloader status check with 60s TTL
- Fix _startup_done set before start() completes (race condition)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:46:22 +01:00
Estrella Pan
c7c709fa66 fix(security): harden auth, JWT, WebAuthn, and API endpoints
- Persist JWT secret to config/.jwt_secret (survives restarts)
- Change active_user from list to dict with timestamps
- Extract username from cookie token instead of list index
- Add SSRF protection (_validate_url) for setup test endpoints
- Mask sensitive config fields (password, api_key, token, secret)
- Add auth guards to notification test endpoints
- Fix path traversal in /posters endpoint using resolved path check
- Add CORS middleware with empty allow_origins
- WebAuthn: add challenge TTL (300s), max capacity (100), cleanup
- Remove hardcoded default password from User model
- Use timezone-aware datetime in passkey models
- Adapt unit tests for active_user dict and cookie-based auth

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:46:12 +01:00
Estrella Pan
339166508b test(e2e): add comprehensive E2E integration test suite
67 tests across 11 phases exercising the full AutoBangumi workflow
against Docker infrastructure (qBittorrent + mock RSS server).
Covers setup wizard, auth, config, RSS CRUD, bangumi, downloader,
program lifecycle, log, search, notification, and credential updates
with both happy paths and error conditions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:44:03 +01:00
Estrella Pan
6cbe7090fe fix(database): clean up torrent records on bangumi deletion
When a bangumi was deleted, its associated Torrent records remained in
the database. This prevented re-downloading the same torrents if the
user re-added the anime, because check_new() deduplicates by URL and
would filter out the orphaned records.

Now delete_rule() removes Torrent records before deleting the Bangumi,
so re-adding the same anime correctly treats those torrents as new.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:45:58 +01:00
Estrella Pan
9d4bd48ce5 test(parser): expand coverage for raw, torrent, and path parsers
Add 13 new test cases across three parser test files:
- raw_parser: Chinese 第二季, 2160p resolution, bracketed Season N, multi-group with Chinese punctuation, English-only title
- torrent_parser: EP format, tc/zh-tw subtitle, no-language subtitle (ValidationError), multi-level path, [NNvN] version suffix
- path_parser: season=2/no-offset, large positive offset, offset yielding exactly Season 1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 20:48:53 +01:00
Estrella Pan
fb2dd17c0c feat(mcp): add MCP server for LLM tool integration via SSE
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.2.3-beta.5
2026-02-22 16:42:39 +01:00
Estrella Pan
ba263e0f69 Merge branch 'claude/inspiring-williams' into 3.2-dev
fix(ui): align notification settings with project design system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:44:22 +01:00
Estrella Pan
b570073000 fix(ui): align notification settings with project design system
Replace non-existent ab-dialog with ab-popup for proper modal behavior,
use ab-button/ab-label components and consistent spacing/styles matching
other settings panels (search-provider, proxy).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:44:11 +01:00
Estrella Pan
a88e01d3f5 chore: bump version to 3.2.3-beta.4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.2.3-beta.4
2026-02-22 14:11:34 +01:00
Estrella Pan
5f604e94fd perf(logging): optimize logging with rotation, async I/O, and lazy formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:10:56 +01:00
Estrella Pan
c173454a67 chore: bump version to 3.2.3-beta.3
fix: Episode 0 incorrectly renamed to E01 (#977)
fix: NoneType error in match_list when title_raw is null (#976)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.2.3-beta.3
2026-01-30 13:13:15 +01:00
Estrella Pan
48bf570697 feat(notification): redesign system to support multiple providers
- Add NotificationProvider base class with send() and test() methods
- Add NotificationManager for handling multiple providers simultaneously
- Add new providers: Discord, Gotify, Pushover, generic Webhook
- Migrate existing providers (Telegram, Bark, Server Chan, WeChat Work) to new architecture
- Add API endpoints for testing providers (/notification/test, /notification/test-config)
- Auto-migrate legacy single-provider configs to new multi-provider format
- Update WebUI with card-based multi-provider settings UI
- Add test button for each provider in settings
- Generic webhook supports template variables: {{title}}, {{season}}, {{episode}}, {{poster_url}}

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 20:58:42 +01:00
Estrella Pan
5eb21bfcfa chore: bump version to 3.2.3-beta.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.2.3-beta.2
2026-01-28 20:27:39 +01:00
Estrella Pan
07093dda8d fix(parser): handle torrent names without brackets in get_group
Fixes IndexError when parsing torrent names that don't follow the
standard [Group] format. Now returns empty string instead of crashing.

Fixes #973

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 20:25:13 +01:00
EstrellaXD
99c8764484 perf: optimize renamer with batch database queries and reduced blocking
- Add batch offset lookup to reduce N database connections to 1-3 per cycle
- Add search_by_qb_hashes() and search_ids() for batch queries
- Throttle pending rename cache cleanup to once per minute max
- Use exponential backoff for rename verification (0.1s->0.2s->0.4s)
- Skip verification for subtitle renames to reduce latency

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 13:55:20 +01:00
Estrella Pan
f4a83d10f8 chore: bump version to 3.2.3-beta.1 3.2.3-beta.1 2026-01-28 08:21:50 +01:00
Estrella Pan
dfe66d279c docs: add Japanese documentation (#970)
Add complete Japanese translation for all documentation pages including:
- Home and about pages
- Deployment guides (Docker CLI, Docker Compose, DSM, Local)
- Configuration pages (RSS, Downloader, Parser, Notifier, Manager, Proxy, Experimental)
- Feature documentation (RSS Management, Bangumi, Calendar, Rename, Search)
- FAQ and troubleshooting
- API reference
- Changelogs (2.6, 3.0, 3.1, 3.2)
- Developer guide

Also updates VitePress config to add Japanese locale with full sidebar navigation.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 21:06:38 +01:00
Estrella Pan
789c02f7f4 fix(docs): convert all relative image paths to absolute paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 21:05:05 +01:00
Estrella Pan
d691cb6d80 fix(docs): use absolute paths for images in VitePress
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 21:02:27 +01:00
Estrella Pan
b33ec01363 fix: improve rename reliability and add torrent tagging API
- Fix qBittorrent rename verification (verify file actually renamed)
- Add pending rename cooldown to prevent spam when rename delayed
- Add torrent tagging API for accurate offset lookup
- Add auto calendar refresh every 24 hours
- Fix frontend error handling (don't logout on server errors)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 20:54:04 +01:00
Estrella Pan
7596d041b9 fix(docs): use absolute paths for images (#967)
* fix(docs): use absolute paths for images in public folder

Relative paths (../image/) don't work on Vercel since the image/
folder at docs root is not tracked in git. Only public/image/ is
tracked. Using absolute paths (/image/) correctly references the
public folder assets.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: update README image paths to public folder

The images are tracked at docs/public/image/, not docs/image/.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 11:52:50 +01:00