Skip to content

Conversation

@s0up4200
Copy link
Collaborator

No description provided.

… state

- Remove empty ItemPath rejection in RefreshItem handler to allow
  refreshing all feeds with empty path
- Preserve original RSS auto-downloading preference in ReprocessRSSRules
  by fetching state before toggle and restoring if it was disabled
- Fix addRSSFeed return type to include undefined for empty responses
When adding a feed to a folder, if the initial GetRSSItems call fails,
the before/after diff would treat all feeds as "new" and potentially
move a random existing feed. Now we track whether we have a valid
baseline and skip the diff comparison entirely if not, falling through
to the "could not identify feed" warning path.
- Remove duplicate parseRSSInstanceID, use existing parseInstanceID
- Use SetRSSAutoDownloadingEnabledCtx for proper context propagation
- Add error handling callbacks to enable RSS/auto-download buttons
- Update go-qbittorrent dependency with new Ctx variants
Document the /api/instances/{instanceID}/rss/events endpoint for
Server-Sent Events streaming of real-time RSS feed updates.
- Add sync.Once to rssSSEClient to ensure done channel is closed only once
- Copy clients slice while holding lock in broadcast to prevent race
  during iteration after lock release
…terval feature

- Introduced `SupportsSetRSSFeedURL` capability in the API response.
- Updated the RSS feed handling to allow setting the feed URL without a refresh interval.
- Removed the refresh interval parameter from the AddRSSFeed API and related frontend hooks.
- Updated OpenAPI documentation to reflect the changes in the RSS feed endpoints.
- Add search field to filter articles by title/description
- Add collapsible descriptions with clickable URLs
- Route download button through AddTorrentDialog
- Auto-expand parent folders when feed is selected on page load
- Add Save button to RSS settings (instead of auto-save on input)
- Strip HTML tags and decode entities in descriptions
- Use CSS grid for proper text truncation with action buttons
Add ability to automatically delete torrents when seeding goals are
reached (ratio or seeding time limit). Supports two delete modes:
- delete: removes torrent entry, keeps files
- deleteWithFiles: removes torrent entry and data files

Deletion only triggers when torrent is completed and has reached either
the configured ratio limit or seeding time limit.
Add new delete mode "deleteWithFilesPreserveCrossSeeds" that safely
deletes torrents and files only when no cross-seed is detected sharing
the same data. When a cross-seed is found (matching ContentPath), only
the torrent entry is removed while files are preserved.

- Add detectCrossSeeds() function using ContentPath comparison
- Add normalizePath() helper for consistent path matching
- Update deletion logic to route cross-seed mode to appropriate action
- Add 4th option to TrackerRulesPanel dropdown
- Update badge display to show "XS safe" for cross-seed mode
Add ability to automatically delete torrents that are no longer registered
with the tracker. Uses existing 60-second cached UnregisteredSet from
SyncManager.

- Add delete_unregistered column to tracker_rules table
- Add DeleteUnregistered field to model, handler, and types
- Add unregistered deletion logic to service (reuses delete modes)
- Add checkbox and badge to TrackerRulesPanel
- Include torrent name, hash, and specific reason in all deletion logs
- Log ratio/seeding time values that triggered deletion
- Add filesKept boolean for clear indication of file fate
- Consolidate cross-seed detection into single log message
- Use user-friendly summary: "removed N torrents (files kept)" vs "with files"
Previously torrents were marked in lastDeleted map before BulkAction,
blocking retry for 5 minutes even if deletion failed.

- Move deletion timestamp to after successful BulkAction
- Add hashes to failure logs for debugging
…ents

- Add queuedForDeletion set to skip torrents already queued by ratio/seeding
  limits when processing unregistered torrents
- Update DeleteMode comments to include deleteWithFilesPreserveCrossSeeds
- Move "Delete unregistered" checkbox before delete mode selector
- Disable checkbox when no delete mode is selected
- Add tooltip explaining why checkbox is disabled
- Clear deleteUnregistered when switching to "Don't delete"
- Clarify that "Don't delete" just pauses torrents
Use AlertDialog for delete confirmation, consistent with rest of codebase.
…tion

- Introduced a new option to apply rules to all trackers, allowing users to select a single pattern ("*") for broader matching.
- Updated validation to require at least one tracker or the 'Apply to all' option to be enabled.
- Adjusted the TrackerRulesPanel to include a toggle for the new feature, improving user experience in tracker management.
- Add 'Speed limits' and 'Seeding limits & auto-delete' sections
- Add OR separator between ratio and seeding time fields
- Make dialog scrollable with fixed header/footer
- Move Enabled toggle to footer alongside Cancel/Save buttons
- Constrain dialog height to 90dvh for smaller screens
… categories and tags

- Refactor TrackerRule and TrackerRulePayload to replace single category and tag fields with arrays for categories and tags.
- Implement cleanStringSlice function to handle trimming and filtering of category and tag inputs.
- Update database interactions to accommodate new array structure for categories and tags.
- Modify TrackerRulesPanel to support multi-select for categories and tags, enhancing user experience in rule management.
Add tagMatchMode field to tracker rules allowing users to choose whether
torrents must match ANY (default) or ALL of the specified tags. Categories
continue to use ANY matching since torrents can only have one category.

- Add TagMatchModeAny/TagMatchModeAll constants to reduce string literals
- Add tag_match_mode column via migration 037
- Update selectRule() to handle both matching modes
- Add input validation for tagMatchMode in Create/Update handlers
- Add frontend toggle (shown when 2+ tags selected)
- Auto-reset tagMatchMode to "any" when tags drop below 2
- Update RuleSummary to display "(any)" or "(all)" for multiple tags
Add database-backed activity logging for tracker rules that persists
through restarts. Records deletions (ratio/seeding/unregistered) and
errors (delete/limit failures) with tracker domain, rule info, and
detailed metadata.

- Add tracker_rule_activity table with migration
- Add TrackerRuleActivityStore with Create, ListByInstance, DeleteOlderThan, Prune
- Record activity on successful/failed deletions and limit changes
- Add API endpoints for listing and clearing activity
- Add TrackerRulesActivityOverview component on Services page
- Auto-prune entries older than 7 days (configurable)
- Include tracker domain in activity records for filtering
…vior

Reduce MaxBatchHashes from 150 to 50 to match qBittorrent's
max_concurrent_http_announces default. This ensures each batch completes
tracker announces in a single wave (~2s) rather than multiple waves,
reducing timeout risk with reverse proxies while maintaining the same
total processing time.

Add documentation explaining that libtorrent automatically sends stopped
announces with final stats when torrents are deleted, so no manual
pause/reannounce step is needed. Works identically for v1 and v2 torrents.
- Add deleteMode validation in Create/Update handlers
- Log JSON decode errors for debugging
- Return 503 when service unavailable in ApplyNow
- Log activity store errors instead of discarding
- Add cleanupStaleEntries to prevent memory growth in lastDeleted map
- Fix "Delete all" to actually delete all activity (days=0)
Add comprehensive tests for the trackerrules service covering:
- matchesTracker: pattern matching (wildcard, exact, suffix, glob, multi-pattern)
- shouldDeleteTorrent: deletion logic (progress, mode, limits, ratio, seeding time)
- detectCrossSeeds: cross-seed detection with path normalization
- selectRule: rule selection (enabled, tracker, category, tag modes)
- limitHashBatch: batch splitting edge cases
- normalizePath: path normalization
- torrentHasTag: tag matching

92 test cases covering the high-risk decision logic areas.
… labels

- Add tracker customization support (icons and display names)
- Change outcome badge from 'success' to 'Removed' for clarity
- Rename failed action labels to avoid redundancy:
  - 'Delete failed' → 'Delete' + 'Failed'
  - 'Limit failed' → 'Set limits' + 'Failed'
- Update description to 'History of torrents removed by tracker rules'
Only show event.reason for failures where it contains the actual error
message. For successes, the action badge and details line already
provide all necessary information without the redundant text.
Add pkg/redact package to centralize redaction of sensitive query
parameters (apikey, api_key, passkey, token, password) from URLs
and error messages. Also handles userinfo passwords and proxy path
segments containing API keys.

Apply redaction to all identified leak points:
- pkg/gojackett: HTTP errors and enclosure URLs
- pkg/prowlarr: request errors
- internal/services/jackett: fetchCaps, Download, service logs
- internal/api/handlers: jackett discovery, torrent URLs
- internal/proxy: middleware, handler, retry transport
- internal/metrics: basic auth credentials

Fixes #839
- Split isRetryableError into smaller helper functions to reduce
  cognitive complexity
- Rename max parameter to maxBackoff to avoid shadowing builtin
- Use range over int (Go 1.22+) for backoff calculation loop
- Remove deprecated netErr.Temporary() call
- Add nolint:wrapcheck directive for RoundTrip (transport errors
  should not be wrapped)
- Use testify assertions in redact package tests
Add season/episode parsing to cross-seed matching to avoid incorrectly
linking season packs with individual episodes. Implements parseSeasonEpisodeInfo
helper that extracts SxxEyy patterns and blocks incompatible matches:
- Season packs won't match individual episodes
- Different seasons won't match
- Multi-episode torrents require exact episode set match

Also tightens save_path matchType to require both path AND base filename
match, preventing misleading labels when only directories match.
Prevents season pack cross-seeds from matching against single-episode
torrents when FindIndividualEpisodes is enabled, avoiding incorrect
matches and episode-style renames on pack torrents.

Centralizes TV episode/season-pack detection and the forbidden-pair
predicate to keep behavior consistent across apply, search, webhook
checks, and alignment.

Adds coverage for the forbidden pairing and uses a shared reject-reason
constant.
…e defaults

Previously, resolution and language were only compared when both releases
had explicit values, allowing false matches like FRENCH.WEB matching
MULTi.1080p.WEB.

Changes:
- Resolution: now requires match, with exception for SD (480p/576p) vs empty
  since many SD releases omit explicit resolution tags
- Language: now requires match, with exception for empty vs ENGLISH since
  most English releases omit language tags entirely

Fixes #688
…erage

- Replace empty if body with inverted guard for SD resolution fallback
- Add test cases for 576p and SD resolution matching
- Add bidirectional test case (576p source vs empty candidate)
Add opt-in PUID/PGID/UMASK support for the Docker image via
docker/entrypoint.sh. When PUID and PGID are set, the container
creates the user/group, chown -Rs /config, then runs qui as that
UID/GID (via su-exec).

- Add docker/entrypoint.sh with user/group creation and privilege drop
- Install su-exec in Dockerfile and ci.Dockerfile
- Update docker-compose.yml with PUID/PGID/UMASK documentation
- Add Permissions section to README.md with examples

Motivation: avoid root-owned /config artifacts and ensure directories
and files created by hardlink-mode cross-seeding inherit expected
ownership.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 25, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch soup-dev-builds

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@s0up4200 s0up4200 changed the title feat(rss): add native rss support dev builds Dec 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants