Skip to content

refactor(crossseed): hardcode ignore patterns for file matching - #915

Merged
s0up4200 merged 9 commits into
developfrom
refactor/hardcode-cross-seed-ignore-patterns
Jan 2, 2026
Merged

refactor(crossseed): hardcode ignore patterns for file matching#915
s0up4200 merged 9 commits into
developfrom
refactor/hardcode-cross-seed-ignore-patterns

Conversation

@s0up4200

@s0up4200 s0up4200 commented Jan 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Replace configurable "Allowed extra files" setting with hardcoded ignore patterns
  • Align with cross-seed.org's approach for consistency
  • Simplify user experience by removing confusing configuration option

Hardcoded extensions: .nfo, .srr, .srt, .sub, .idx, .ass, .ssa, .sup, .vtt, .txt

Hardcoded path keywords: sample, !sample, proof, extras, bonus, trailer, featurette

Changes

  • Add ignore_patterns.go with hardcoded extension and keyword lists
  • Update shouldIgnoreFile to use hardcoded patterns instead of user-configurable ones
  • Remove ignorePatterns field from settings model, API handlers, and service layer
  • Add database migration to drop ignore_patterns column
  • Remove "Allowed extra files" textarea from CrossSeedPage UI
  • Update documentation (README.md, CROSS_SEEDING.md)
  • Update OpenAPI spec
  • Fix related tests to reflect new behavior

Test plan

  • Build compiles successfully
  • All affected tests pass
  • OpenAPI spec validates
  • Manual test: cross-seed matching correctly ignores hardcoded patterns
  • Manual test: UI no longer shows "Allowed extra files" field

Summary by CodeRabbit

  • Documentation

    • Clarified extra-file handling and recheck wording; documented piece-boundary safety and reflink as a safer alternative.
  • Changes

    • Removed user-configurable ignore-patterns — matching now uses built-in defaults and corresponding UI/API options removed.
    • Added statuses: "Size mismatch" and "Skipped - unsafe pieces".
    • Improved per-instance feedback when applying cross-seed selections.
  • Migration

    • Database schema updated to remove stored ignore-patterns.

✏️ Tip: You can customize this high-level summary in your review settings.

Replace the configurable "Allowed extra files" setting with hardcoded
lists of file extensions and path keywords to ignore during cross-seed
matching. This aligns with cross-seed.org's approach and simplifies
the user experience.

Hardcoded extensions: .nfo, .srr, .srt, .sub, .idx, .ass, .ssa, .sup,
.vtt, .txt

Hardcoded path keywords: sample, !sample, proof, extras, bonus,
trailer, featurette

Changes:
- Add ignore_patterns.go with hardcoded lists
- Update shouldIgnoreFile to use hardcoded patterns
- Remove ignorePatterns from settings model and API
- Add migration to drop ignore_patterns column
- Remove "Allowed extra files" UI from CrossSeedPage
- Update documentation and OpenAPI spec
- Fix related tests to reflect new behavior
@coderabbitai

coderabbitai Bot commented Jan 1, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR removes configurable cross‑seed ignore patterns, replaces them with hardcoded default ignore lists, drops the DB column and struct field, and updates matching, service payloads, API, tests, docs, OpenAPI/types, and frontend UI/state to stop exposing ignorePatterns.

Changes

Cohort / File(s) Summary
Documentation
README.md, docs/CROSS_SEEDING.md
Removed "Allowed Extra Files" and reworded recheck/alignment text to reference hardcoded ignore behavior and reflink/safety notes.
Database & Models
internal/database/migrations/048_drop_ignore_patterns_column.sql, internal/models/crossseed.go, internal/models/crossseed_test.go
Dropped ignore_patterns column; removed IgnorePatterns field from CrossSeedAutomationSettings; removed persistence/encoding of ignore patterns and updated tests.
Hardcoded Ignore Lists
internal/services/crossseed/ignore_patterns.go
Added DefaultIgnoredExtensions and DefaultIgnoredPathKeywords as static ignore filters.
Matching & Filtering Logic
internal/services/crossseed/matching.go, internal/services/crossseed/align.go, internal/services/crossseed/layout.go, internal/services/crossseed/ignore_patterns.go
Replaced pattern-based ignore logic with hardcoded filters; removed ignorePatterns parameters from shouldIgnoreFile, classifyTorrentLayout, getMatchType* and hasContentFileSizeMismatch; updated call sites.
Service Surface & Payloads
internal/services/crossseed/service.go, internal/services/crossseed/models.go
Removed IgnorePatterns from SearchRunOptions, CrossSeedRequest, FindCandidatesRequest, AutobrrApplyRequest and from propagation across cross‑seed flows; adjusted signatures (e.g., findBestCandidateMatch).
API Handlers & Tests
internal/api/handlers/crossseed.go, internal/api/handlers/crossseed_patch_test.go
Removed IgnorePatterns from request/patch types and apply/merge logic; tests updated to omit ignore‑pattern assertions.
Service Tests
internal/services/crossseed/*_test.go
Removed ignorePatterns initializations and assertions; adapted test data/names to reflect hardcoded ignore behavior and updated function signatures.
OpenAPI & Frontend Types
internal/web/swagger/openapi.yaml, web/src/types/index.ts
Removed ignorePatterns from CrossSeedAutomationSettings and corresponding patch schema/types.
Frontend UI & Hooks
web/src/pages/CrossSeedPage.tsx, web/src/hooks/useCrossSeedSearch.tsx, web/src/components/torrents/CrossSeedDialog.tsx
Removed global ignore‑pattern UI/state/validation and payload inclusion; improved aggregated apply‑result feedback; added two new instance status mappings.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

refactor, cross-seed, web, documentation, tests, backend, api

Poem

🐇
I hopped through code to clear the tracks,
Hid the patterns, left tidy stacks.
Defaults bloom where wild rules fled,
Docs and tests now snuggle bed.
Nibble of change — a carrot-fed. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing configurable ignore patterns with hardcoded ones in cross-seed file matching logic.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/hardcode-cross-seed-ignore-patterns

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 613944f and fee8608.

📒 Files selected for processing (1)
  • web/src/pages/CrossSeedPage.tsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:209-212
Timestamp: 2025-11-28T20:32:30.126Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The cross-seed recheck-resume worker intentionally runs for the process lifetime and keys pending entries by hash only. This is acceptable under the current constraint that background seeded-search runs operate on a single instance at a time; graceful shutdown and instanceID|hash keying are deferred by design.
📚 Learning: 2025-12-03T18:11:08.682Z
Learnt from: finevan
Repo: autobrr/qui PR: 677
File: web/src/components/torrents/AddTorrentDialog.tsx:496-504
Timestamp: 2025-12-03T18:11:08.682Z
Learning: In the AddTorrentDialog component (web/src/components/torrents/AddTorrentDialog.tsx), temporary path settings (useDownloadPath/downloadPath) should be applied per-torrent rather than updating global instance preferences. The UI/UX is designed to suggest that these options apply to the individual torrent being added.

Applied to files:

  • web/src/pages/CrossSeedPage.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Build Docker images (linux/amd64)
  • GitHub Check: Build Docker images (linux/amd64/v2)
  • GitHub Check: Build Docker images (linux/arm/v6)
  • GitHub Check: Build Docker images (linux/arm64)
  • GitHub Check: Build Docker images (linux/arm/v7)
  • GitHub Check: Build Docker images (linux/amd64/v3)
  • GitHub Check: Build distribution binaries
🔇 Additional comments (3)
web/src/pages/CrossSeedPage.tsx (3)

2297-2316: LGTM!

The safety check toggle and its description are clear. The guidance to consider reflink mode as an alternative is helpful for users who need to handle extra files safely.


2603-2611: LGTM!

The save button's disabled state correctly simplifies to only depend on the mutation pending state, now that the ignorePatterns validation has been removed per the PR objective.


81-108: Clean removal of ignorePatterns from the settings interface.

The GlobalCrossSeedSettings interface no longer includes the ignorePatterns field, aligning with the backend changes that now use hardcoded ignore patterns. The remaining fields are well-organized with clear grouping comments.


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
internal/models/crossseed.go (1)

296-363: Migration file exists, but IgnorePatterns field removal is incomplete.

While the migration file 048_drop_ignore_patterns_column.sql exists and the SQL query correctly excludes the ignore_patterns column, the refactoring is incomplete. The IgnorePatterns field still exists and is actively used in:

  • internal/services/crossseed/models.go: Lines 26–27, 138–139, 382 (struct definitions)
  • internal/services/crossseed/service.go: Lines 462, 2290, 2375–2376, 2637, 2695, 6131–6132 (active usage)

Remove the IgnorePatterns field from all model structs and update service methods to eliminate the remaining references.

web/src/pages/CrossSeedPage.tsx (4)

79-79: Critical: Remove ignorePatterns field from GlobalCrossSeedSettings interface.

The ignorePatterns field should have been removed as part of this PR's transition to hardcoded ignore patterns. The backend has already removed this field from CrossSeedAutomationSettings (internal/models/crossseed.go), and the API no longer accepts or returns it.

🔎 Proposed fix
   runExternalProgramId?: number | null
-  ignorePatterns: string
   // Source-specific tagging

130-130: Critical: Remove ignorePatterns from DEFAULT_GLOBAL_SETTINGS.

This default value references the removed field and will cause type errors once the interface is corrected.

🔎 Proposed fix
   runExternalProgramId: null,
-  ignorePatterns: "",
   // Source-specific tagging defaults

171-173: Critical: Remove unused normalizeIgnorePatterns function.

This function is no longer needed since ignore patterns are now hardcoded in the backend (internal/services/crossseed/ignore_patterns.go). The function references the removed ignorePatterns field.

🔎 Proposed fix
-function normalizeIgnorePatterns(patterns: string): string[] {
-  return parseList(patterns.replace(/\r/g, ""))
-}
-

709-856: Critical: Remove all ignorePatterns references from settings initialization and patch building.

Multiple locations still reference the removed ignorePatterns field:

  1. Lines 719-721: Settings initialization converts settings.ignorePatterns array to string
  2. Line 796: Default fallback references settings.ignorePatterns
  3. Line 808: Joins ignorePatterns for display
  4. Line 835: Calls normalizeIgnorePatterns(globalSource.ignorePatterns) in patch payload

All of these should be removed since ignore patterns are now hardcoded in the backend.

🔎 Proposed fix
       customCategory: settings.customCategory ?? "",
       runExternalProgramId: settings.runExternalProgramId ?? null,
-      ignorePatterns: Array.isArray(settings.ignorePatterns)
-        ? settings.ignorePatterns.join("\n")
-        : "",
       // Source-specific tagging

And in buildGlobalPatch:

       customCategory: settings.customCategory ?? "",
       runExternalProgramId: settings.runExternalProgramId ?? null,
-      ignorePatterns: ignorePatterns.length > 0 ? ignorePatterns.join(", ") : "",
       rssAutomationTags: settings.rssAutomationTags ?? ["cross-seed"],

And remove from the returned patch object:

       customCategory: globalSource.customCategory,
       runExternalProgramId: globalSource.runExternalProgramId,
-      ignorePatterns: normalizeIgnorePatterns(globalSource.ignorePatterns),
       // Source-specific tagging
🧹 Nitpick comments (2)
internal/services/crossseed/matching.go (1)

1049-1053: Consider deprecating the patterns parameter.

The function documentation states that the patterns parameter is kept for backwards compatibility but is ignored. This could be confusing for callers. Consider one of the following approaches:

  1. Remove the parameter entirely (breaking change but clearer)
  2. Add a deprecation notice to the function documentation
  3. Log a warning if a non-empty patterns slice is passed
🔎 Option 1: Remove the parameter
-// shouldIgnoreFile checks if a file should be ignored during matching.
-// Uses hardcoded lists of extensions and path keywords to filter out scene
-// metadata files, subtitles, samples, and other non-content files.
-// The patterns parameter is kept for backwards compatibility but is ignored.
-func shouldIgnoreFile(filename string, _ []string, normalizer *stringutils.Normalizer[string, string]) bool {
+// shouldIgnoreFile checks if a file should be ignored during matching.
+// Uses hardcoded lists of extensions and path keywords to filter out scene
+// metadata files, subtitles, samples, and other non-content files.
+func shouldIgnoreFile(filename string, normalizer *stringutils.Normalizer[string, string]) bool {

Then update all callers to remove the patterns argument.

internal/services/crossseed/service.go (1)

2747-2782: Safety skip messages are clearer; just ensure UI label parity

The updated messages for skipped_unsafe_pieces and skipped_recheck more explicitly point users at the relevant toggles (“Piece boundary safety check” and “Skip recheck” under Cross‑Seed settings). Behavior is unchanged and the guidance is clearer; just double‑check the exact UI labels match these strings to avoid minor UX confusion.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b5079b and 48a8549.

📒 Files selected for processing (18)
  • README.md
  • docs/CROSS_SEEDING.md
  • internal/api/handlers/crossseed.go
  • internal/api/handlers/crossseed_patch_test.go
  • internal/database/migrations/048_drop_ignore_patterns_column.sql
  • internal/models/crossseed.go
  • internal/models/crossseed_test.go
  • internal/services/crossseed/align_test.go
  • internal/services/crossseed/autobrr_apply_test.go
  • internal/services/crossseed/crossseed_test.go
  • internal/services/crossseed/find_individual_episodes_test.go
  • internal/services/crossseed/ignore_patterns.go
  • internal/services/crossseed/matching.go
  • internal/services/crossseed/service.go
  • internal/web/swagger/openapi.yaml
  • web/src/components/torrents/CrossSeedDialog.tsx
  • web/src/hooks/useCrossSeedSearch.tsx
  • web/src/pages/CrossSeedPage.tsx
💤 Files with no reviewable changes (3)
  • internal/services/crossseed/autobrr_apply_test.go
  • internal/services/crossseed/crossseed_test.go
  • internal/web/swagger/openapi.yaml
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:209-212
Timestamp: 2025-11-28T20:32:30.126Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The cross-seed recheck-resume worker intentionally runs for the process lifetime and keys pending entries by hash only. This is acceptable under the current constraint that background seeded-search runs operate on a single instance at a time; graceful shutdown and instanceID|hash keying are deferred by design.
📚 Learning: 2025-11-06T11:59:21.390Z
Learnt from: Audionut
Repo: autobrr/qui PR: 553
File: web/src/components/torrents/TorrentTableOptimized.tsx:1510-1515
Timestamp: 2025-11-06T11:59:21.390Z
Learning: In the qui project, the API layer in web/src/lib/api.ts normalizes backend snake_case responses to camelCase for frontend consumption. For CrossSeed search results, the backend's download_url field is transformed to downloadUrl in the searchCrossSeedTorrent method, so frontend code should always use the camelCase variant (result.downloadUrl).

Applied to files:

  • web/src/hooks/useCrossSeedSearch.tsx
  • web/src/components/torrents/CrossSeedDialog.tsx
📚 Learning: 2025-11-28T20:32:30.126Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:209-212
Timestamp: 2025-11-28T20:32:30.126Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The cross-seed recheck-resume worker intentionally runs for the process lifetime and keys pending entries by hash only. This is acceptable under the current constraint that background seeded-search runs operate on a single instance at a time; graceful shutdown and instanceID|hash keying are deferred by design.

Applied to files:

  • web/src/hooks/useCrossSeedSearch.tsx
  • internal/services/crossseed/ignore_patterns.go
  • internal/services/crossseed/find_individual_episodes_test.go
  • internal/models/crossseed_test.go
  • internal/models/crossseed.go
  • internal/api/handlers/crossseed_patch_test.go
  • docs/CROSS_SEEDING.md
  • internal/services/crossseed/service.go
📚 Learning: 2025-11-28T22:21:20.730Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:2415-2457
Timestamp: 2025-11-28T22:21:20.730Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The determineSavePath function intentionally includes a contentLayout string parameter for future/content-layout branching and API consistency. Its presence is by design even if unused in the current body; do not flag as an issue in reviews.

Applied to files:

  • internal/services/crossseed/ignore_patterns.go
  • internal/services/crossseed/service.go
📚 Learning: 2025-12-28T18:44:10.496Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 876
File: internal/logstream/hub_test.go:188-192
Timestamp: 2025-12-28T18:44:10.496Z
Learning: In Go 1.25 (Aug 2025), use wg.Go(func()) to spawn a goroutine and automate the Add/Done lifecycle. Replace manual patterns like wg.Add(1); go func(){ defer wg.Done(); ... }() with wg.Go(func(){ ... }). Ensure the codebase builds with Go 1.25+ and apply this in relevant Go files (e.g., internal/logstream/hub_test.go). If targeting older Go versions, maintain the existing pattern.

Applied to files:

  • internal/services/crossseed/ignore_patterns.go
  • internal/services/crossseed/find_individual_episodes_test.go
  • internal/models/crossseed_test.go
  • internal/models/crossseed.go
  • internal/api/handlers/crossseed_patch_test.go
  • internal/api/handlers/crossseed.go
  • internal/services/crossseed/service.go
  • internal/services/crossseed/matching.go
  • internal/services/crossseed/align_test.go
📚 Learning: 2025-12-03T18:11:08.682Z
Learnt from: finevan
Repo: autobrr/qui PR: 677
File: web/src/components/torrents/AddTorrentDialog.tsx:496-504
Timestamp: 2025-12-03T18:11:08.682Z
Learning: In the AddTorrentDialog component (web/src/components/torrents/AddTorrentDialog.tsx), temporary path settings (useDownloadPath/downloadPath) should be applied per-torrent rather than updating global instance preferences. The UI/UX is designed to suggest that these options apply to the individual torrent being added.

Applied to files:

  • web/src/pages/CrossSeedPage.tsx
  • web/src/components/torrents/CrossSeedDialog.tsx
📚 Learning: 2025-12-19T07:24:42.043Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 825
File: internal/models/crossseed.go:68-68
Timestamp: 2025-12-19T07:24:42.043Z
Learning: In the autobrr/qui repository, SQLite migrations should use DEFAULT 0 for boolean column defaults instead of DEFAULT FALSE. This ensures consistency with SQLite typing and avoids potential confusion, even though both are functionally equivalent for SQLite. Apply this rule to all SQL migration files (e.g., migrations/*.sql and any SQL in subdirectories).

Applied to files:

  • internal/database/migrations/048_drop_ignore_patterns_column.sql
📚 Learning: 2025-11-06T12:11:04.963Z
Learnt from: Audionut
Repo: autobrr/qui PR: 553
File: internal/services/crossseed/service.go:1045-1082
Timestamp: 2025-11-06T12:11:04.963Z
Learning: The autobrr/qui project uses a custom go-qbittorrent client library (github.com/autobrr/go-qbittorrent) that supports both "paused" and "stopped" parameters when adding torrents via the options map. Both parameters should be set together when controlling torrent start state, as seen in internal/services/crossseed/service.go and throughout the codebase.

Applied to files:

  • docs/CROSS_SEEDING.md
  • internal/services/crossseed/service.go
📚 Learning: 2025-11-27T15:33:39.007Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/jackett/service.go:309-330
Timestamp: 2025-11-27T15:33:39.007Z
Learning: In internal/services/jackett/service.go, synchronous execution paths (test executors, interactive searches with explicit indexer selection, and scheduler-unavailable fallback) intentionally pass jobID=0 to result callbacks. This is acceptable because outcome tracking via ReportIndexerOutcome is only used for async cross-seed operations that always use the scheduler and receive unique jobIDs. Interactive searches and tests do not use outcome tracking.

Applied to files:

  • internal/services/crossseed/service.go
🧬 Code graph analysis (3)
internal/services/crossseed/find_individual_episodes_test.go (2)
internal/models/crossseed.go (1)
  • CrossSeedAutomationSettings (20-76)
web/src/types/index.ts (1)
  • CrossSeedAutomationSettings (1645-1689)
internal/api/handlers/crossseed.go (1)
web/src/types/index.ts (1)
  • Category (664-667)
internal/services/crossseed/matching.go (2)
pkg/stringutils/normalize.go (1)
  • Normalizer (19-22)
internal/services/crossseed/ignore_patterns.go (2)
  • DefaultIgnoredExtensions (11-27)
  • DefaultIgnoredPathKeywords (32-40)
🔇 Additional comments (19)
internal/models/crossseed_test.go (1)

78-104: LGTM!

The test correctly reflects the removal of the IgnorePatterns field from CrossSeedAutomationSettings. The round-trip test still validates all other fields comprehensively.

web/src/hooks/useCrossSeedSearch.tsx (2)

81-85: LGTM!

The condensed calculation is more concise while maintaining clarity. The ternary operator and chained operations keep the logic readable.


406-431: Excellent UX improvement!

The aggregated feedback provides clear, actionable information about cross-seed application outcomes. The logic correctly handles all scenarios: all successes, mixed results, all failures, and no additions. The fallback for results without instanceResults ensures backward compatibility.

internal/services/crossseed/align_test.go (3)

712-723: LGTM!

The test case correctly validates that non-hardcoded extensions (like .zip) are NOT filtered and will cause a content mismatch. This is a good complement to the tests that verify hardcoded patterns ARE filtered.


765-776: LGTM!

The test case correctly validates that hardcoded extensions (.nfo, .srt) are automatically filtered without requiring explicit ignorePatterns. The test name clearly communicates the new behavior.


806-817: LGTM!

The test case correctly validates that hardcoded path keywords (like sample) are automatically filtered. The change from Screens to Sample appropriately reflects the new hardcoded behavior.

README.md (1)

462-462: LGTM!

The simplified wording correctly reflects the removal of configurable ignore patterns. The phrase "samples, etc." is clear and concise without requiring users to understand pattern matching syntax.

internal/database/migrations/048_drop_ignore_patterns_column.sql (1)

1-7: LGTM!

The migration cleanly removes the ignore_patterns column, aligning with the PR's objective to hardcode these values. The comment clearly documents the rationale.

Note: This migration uses DROP COLUMN, which requires SQLite 3.35.0+ (March 2021). Given the project's modern stack, this should not be an issue for most deployments.

internal/models/crossseed.go (1)

509-617: LGTM! UpsertSettings correctly updated.

The UpsertSettings method has been properly updated to exclude ignore_patterns from both the INSERT and UPDATE operations. The placeholder count (34) correctly matches the number of fields being inserted.

internal/api/handlers/crossseed_patch_test.go (1)

13-97: LGTM! Test correctly updated.

The test has been properly updated to remove IgnorePatterns from both the initial state and the patch request. The remaining field assertions ensure that other settings continue to work correctly with the patch merge logic.

internal/services/crossseed/find_individual_episodes_test.go (1)

121-121: Verify TypeScript type definition consistency.

The IgnorePatterns field has been removed from the Go model, but the TypeScript type definition in web/src/types/index.ts (lines 1644-1688) still includes ignorePatterns: string[]. This mismatch will cause type errors when the API returns settings without this field.

internal/services/crossseed/matching.go (1)

1053-1071: Implementation correctly uses hardcoded ignore lists.

The new implementation efficiently checks file extensions and path keywords without glob pattern overhead. Both DefaultIgnoredExtensions and DefaultIgnoredPathKeywords are properly defined in ignore_patterns.go, and the use of normalized filenames ensures case-insensitive matching. All callers pass compatible arguments.

web/src/components/torrents/CrossSeedDialog.tsx (1)

552-561: Status mappings verified. Both "rejected" and "skipped_unsafe_pieces" are returned by the backend service in appropriate scenarios. The frontend mappings are correct: "rejected" maps to "Size mismatch" (content file size mismatch detection), and "skipped_unsafe_pieces" maps to "Skipped - unsafe pieces" (piece boundary safety violation).

internal/api/handlers/crossseed.go (1)

31-294: LGTM! IgnorePatterns successfully removed from API handlers.

The removal of IgnorePatterns from the request/patch structs, validation logic, and update handlers is complete and correct. The API layer now properly omits all references to the deprecated field, aligning with the backend model changes.

docs/CROSS_SEEDING.md (1)

155-156: LGTM! Documentation accurately reflects hardcoded ignore behavior.

The updated wording correctly reflects that extra files (NFO, SRT, samples, etc.) are now handled uniformly via hardcoded patterns rather than user-configurable settings. The clarification that piece-boundary checks apply to "all extra files" removes ambiguity about which files are subject to these rules.

Also applies to: 172-173

internal/services/crossseed/ignore_patterns.go (1)

1-40: Remove cross-seed.org standards verification claim; these are autobrr's own curated defaults.

The patterns in this file are autobrr's own defaults, not from cross-seed.org (which ships with empty defaults and is fully user-configurable). The review premise about verifying alignment with "cross-seed.org standards" is incorrect—there are no such standards in cross-seed.org documentation.

The mutability concern is theoretical; the slices are never modified in the codebase (only read-only access in matching.go), so this is not a practical issue. If improved as a matter of Go best practices, consider the getter function approach, but it's not required for correctness.

Likely an incorrect or invalid review comment.

internal/services/crossseed/service.go (3)

1150-1162: Completion search now uses dedicated tags + inheritSourceTags

Using CompletionSearchTags for TagsOverride and wiring InheritSourceTags through SearchRunOptions is consistent with how seeded search handles tags and keeps state copying defensive (append([]string(nil), ...)). No issues spotted here.


1835-1853: RSS automation CrossSeedRequest wiring looks correct

RSSAutomationTags, InheritSourceTags, and SkipIfExists are now explicitly set on the CrossSeedRequest, matching the intended behavior for automated RSS runs while keeping the struct literal defensively copied. This aligns with the new hardcoded ignore-pattern model and doesn’t introduce correctness issues.


2520-2533: AutobrrApply tag/paused behavior remains coherent

Forwarding tags, inheritSourceTags, and req.StartPaused directly into CrossSeedRequest keeps webhook-driven applies consistent with other call sites. Given processCrossSeedCandidate already defaults StartPaused and merges tags via buildCrossSeedTags, this wiring looks sound.

Remove leftover ignorePatterns field from interfaces, defaults, and
state management now that ignore patterns are hardcoded in the backend.
@s0up4200 s0up4200 added this to the v1.12.0 milestone Jan 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
docs/CROSS_SEEDING.md (1)

155-156: Document the hardcoded ignore patterns explicitly.

The PR replaces the user-configurable "Allowed extra files" setting with hardcoded ignore patterns, but the documentation doesn't explain this change. Users who previously customized these patterns need to know:

  1. The setting has been removed from the UI
  2. Ignore patterns are now hardcoded and align with cross-seed.org defaults
  3. What the specific hardcoded patterns are

Consider adding a subsection or note that explicitly lists the hardcoded patterns, for example:

#### Ignored extra files

qui automatically ignores common extra files when matching torrents. The following patterns are hardcoded to align with cross-seed.org behavior:

**Extensions:** `.nfo`, `.srr`, `.srt`, `.sub`, `.idx`, `.ass`, `.ssa`, `.sup`, `.vtt`, `.txt`

**Path keywords:** `sample`, `!sample`, `proof`, `extras`, `bonus`, `trailer`, `featurette`

These patterns are no longer user-configurable (previously available as "Allowed extra files" in the UI).
internal/services/crossseed/service.go (2)

2751-2751: User‑facing messages align with setting names; consider slightly clearer wording

The new messages correctly reference the UI toggles (“Piece boundary safety check” and “Skip recheck”), which should reduce confusion.

If you want to be maximally explicit, you might tweak the copy to describe the action rather than the control name, e.g.:

  • “Uncheck ‘Piece boundary safety check’ in Cross‑Seed settings to allow.”
  • “Uncheck ‘Skip recheck’ in Cross‑Seed settings to allow.”

Pure UX nit, behavior is fine as‑is.

Also applies to: 2782-2782


6135-6136: Leftover propagation of IgnorePatterns from seeded search into CrossSeedRequest

executeCrossSeedSearchAttempt still threads state.opts.IgnorePatterns into request.IgnorePatterns. Given this PR’s goal to move to hard‑coded ignore behavior and remove ignore pattern settings from the service/API layer, this path is likely now either unused or no‑op:

  • SearchRunOptions.IgnorePatterns remains in the struct.
  • There’s no evidence in this file of IgnorePatterns being set from any remaining config/UI.
  • If shouldIgnoreFile now relies solely on hard‑coded defaults, passing IgnorePatterns is misleading and may cause confusion for future maintainers.

Suggested follow‑up:

  • Either remove IgnorePatterns from SearchRunOptions and stop populating CrossSeedRequest.IgnorePatterns entirely, or
  • Clearly document that per‑run ignore patterns are no longer supported and this field is intentionally ignored, then clean it up in a later pass.

No immediate correctness issue, but cleaning this up would better match the PR intent and reduce dead configuration surface.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1f670c and ca36084.

📒 Files selected for processing (7)
  • README.md
  • docs/CROSS_SEEDING.md
  • internal/api/handlers/crossseed.go
  • internal/services/crossseed/autobrr_apply_test.go
  • internal/services/crossseed/service.go
  • internal/web/swagger/openapi.yaml
  • web/src/pages/CrossSeedPage.tsx
💤 Files with no reviewable changes (2)
  • internal/web/swagger/openapi.yaml
  • internal/services/crossseed/autobrr_apply_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:209-212
Timestamp: 2025-11-28T20:32:30.126Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The cross-seed recheck-resume worker intentionally runs for the process lifetime and keys pending entries by hash only. This is acceptable under the current constraint that background seeded-search runs operate on a single instance at a time; graceful shutdown and instanceID|hash keying are deferred by design.
📚 Learning: 2025-12-28T18:44:10.496Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 876
File: internal/logstream/hub_test.go:188-192
Timestamp: 2025-12-28T18:44:10.496Z
Learning: In Go 1.25 (Aug 2025), use wg.Go(func()) to spawn a goroutine and automate the Add/Done lifecycle. Replace manual patterns like wg.Add(1); go func(){ defer wg.Done(); ... }() with wg.Go(func(){ ... }). Ensure the codebase builds with Go 1.25+ and apply this in relevant Go files (e.g., internal/logstream/hub_test.go). If targeting older Go versions, maintain the existing pattern.

Applied to files:

  • internal/api/handlers/crossseed.go
  • internal/services/crossseed/service.go
📚 Learning: 2025-12-03T18:11:08.682Z
Learnt from: finevan
Repo: autobrr/qui PR: 677
File: web/src/components/torrents/AddTorrentDialog.tsx:496-504
Timestamp: 2025-12-03T18:11:08.682Z
Learning: In the AddTorrentDialog component (web/src/components/torrents/AddTorrentDialog.tsx), temporary path settings (useDownloadPath/downloadPath) should be applied per-torrent rather than updating global instance preferences. The UI/UX is designed to suggest that these options apply to the individual torrent being added.

Applied to files:

  • web/src/pages/CrossSeedPage.tsx
📚 Learning: 2025-11-28T20:32:30.126Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:209-212
Timestamp: 2025-11-28T20:32:30.126Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The cross-seed recheck-resume worker intentionally runs for the process lifetime and keys pending entries by hash only. This is acceptable under the current constraint that background seeded-search runs operate on a single instance at a time; graceful shutdown and instanceID|hash keying are deferred by design.

Applied to files:

  • internal/services/crossseed/service.go
📚 Learning: 2025-11-28T22:21:20.730Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:2415-2457
Timestamp: 2025-11-28T22:21:20.730Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The determineSavePath function intentionally includes a contentLayout string parameter for future/content-layout branching and API consistency. Its presence is by design even if unused in the current body; do not flag as an issue in reviews.

Applied to files:

  • internal/services/crossseed/service.go
📚 Learning: 2025-11-06T12:11:04.963Z
Learnt from: Audionut
Repo: autobrr/qui PR: 553
File: internal/services/crossseed/service.go:1045-1082
Timestamp: 2025-11-06T12:11:04.963Z
Learning: The autobrr/qui project uses a custom go-qbittorrent client library (github.com/autobrr/go-qbittorrent) that supports both "paused" and "stopped" parameters when adding torrents via the options map. Both parameters should be set together when controlling torrent start state, as seen in internal/services/crossseed/service.go and throughout the codebase.

Applied to files:

  • internal/services/crossseed/service.go
  • docs/CROSS_SEEDING.md
📚 Learning: 2025-12-11T08:40:01.329Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 746
File: internal/services/reannounce/service.go:480-481
Timestamp: 2025-12-11T08:40:01.329Z
Learning: In autobrr/qui's internal/services/reannounce/service.go, the hasHealthyTracker, getProblematicTrackers, and getHealthyTrackers functions intentionally match qbrr's lenient tracker health logic (skip unregistered trackers and check if any other tracker is healthy) rather than go-qbittorrent's strict isTrackerStatusOK logic (which treats unregistered as an immediate failure). For multi-tracker torrents, if one tracker is working, reannouncing won't help. The duplication of the health check logic across these three functions is acceptable as it's a simple one-liner, and extracting it would add unnecessary complexity.

Applied to files:

  • docs/CROSS_SEEDING.md
🧬 Code graph analysis (1)
internal/api/handlers/crossseed.go (1)
web/src/types/index.ts (1)
  • Category (664-667)
🔇 Additional comments (1)
internal/services/crossseed/service.go (1)

1159-1161: Consistent use of source‑specific tag settings across flows looks good

These changes wire CompletionSearchTags, RSSAutomationTags, and WebhookTags into completion, RSS automation, and Autobrr apply respectively, still copying slices defensively and preserving InheritSourceTags/StartPaused semantics. This is consistent with the rest of the service and with how seeded search uses SeededSearchTags. No functional issues spotted here.

Also applies to: 1839-1842, 2524-2526

@s0up4200
s0up4200 changed the base branch from main to develop January 2, 2026 07:21

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
internal/services/crossseed/layout.go (1)

46-75: Largest‑file classification with hardcoded ignores and extended archive detection looks sound

classifyTorrentLayout now:

  • Skips files via shouldIgnoreFile(f.Name, normalizer) and selects the largest remaining path, then
  • Classifies that path using isArchiveFilename, which correctly handles multi‑suffix archives (.tar.gz, .tar.xz, .tar.bz2, .tar) before falling back to the archiveExtensions map for RAR parts, ZIP, 7z, etc.

This keeps layout classification aligned with the new hardcoded ignore behavior and improves archive coverage. If this ever shows up hot in profiles, you could hoist archiveSuffixes to a package‑level var to avoid re‑allocating the slice on each call, but it’s fine as‑is.

Also applies to: 77-98

internal/services/crossseed/service.go (2)

2693-2850: Candidate selection & safety messaging look consistent with new matching / safety model

  • Using findBestCandidateMatch(ctx, candidate, sourceRelease, sourceFiles, candidateFilesByHash, tolerancePercent) keeps all file‑level and tolerance logic centralized and matches the new signature that no longer depends on user‑supplied ignore patterns.
  • Passing s.stringNormalizer into hasContentFileSizeMismatch(sourceFiles, candidateFiles, s.stringNormalizer) is appropriate and keeps normalization consistent with the rest of the service.
  • The piece‑boundary safety block explicitly ignores ignore patterns when deciding if extra files are unsafe (HasUnsafeIgnoredExtras), which is the right call: safety should not be bypassed by “ignored” extensions/paths.
  • The updated messages:
    • "Skipped: extra files share pieces with content. Disable 'Piece boundary safety check' in Cross-Seed settings to allow"
    • "Skipped: requires recheck. Disable 'Skip recheck' in Cross-Seed settings to allow"
      are coherent with the corresponding boolean flags (SkipPieceBoundarySafetyCheck, SkipRecheck), assuming the UI labels match those phrases.

No functional issues spotted in this region.

If you want, you could consider slightly rephrasing the messages to avoid the double‑negative around “Disable Skip recheck” (e.g., “Uncheck ‘Skip recheck’…”), but that’s purely UX polish.


3656-3755: findBestCandidateMatch correctly delegates to getMatchTypeWithReason; semantics look sound

  • The new findBestCandidateMatch signature without ignore‑pattern parameters makes sense now that ignore handling is centralized elsewhere.
  • Calling getMatchTypeWithReason(candidateRelease, sourceRelease, files, sourceFiles, tolerancePercent) matches the comment: we’re checking whether the existing torrent’s files (files) are contained within the new torrent’s files (sourceFiles), which is the intended direction for apply‑time validation.
  • Using matchTypePriority to accept only "exact", "partial-in-pack", and "size" (others treated as priority 0) is a good guardrail to avoid accidentally acting on weaker layout‑only match types.
  • The tie‑breaker (prefer root‑folder layouts, then higher file count) is consistent with earlier dedup behavior and should pick more robust representatives.

Everything here is internally consistent with the surrounding code and PR intent.

If you later need finer cancellation behavior during heavy candidate scans, you could thread ctx into the inner loop (e.g., check ctx.Err() every N iterations), but it’s not necessary for this refactor.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6473de and 613944f.

📒 Files selected for processing (15)
  • README.md
  • internal/api/handlers/crossseed.go
  • internal/models/crossseed.go
  • internal/services/crossseed/align.go
  • internal/services/crossseed/align_test.go
  • internal/services/crossseed/crossseed_test.go
  • internal/services/crossseed/layout.go
  • internal/services/crossseed/layout_test.go
  • internal/services/crossseed/matching.go
  • internal/services/crossseed/matching_hdr_test.go
  • internal/services/crossseed/matching_layout_test.go
  • internal/services/crossseed/models.go
  • internal/services/crossseed/service.go
  • internal/web/swagger/openapi.yaml
  • web/src/pages/CrossSeedPage.tsx
💤 Files with no reviewable changes (1)
  • internal/web/swagger/openapi.yaml
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/api/handlers/crossseed.go
  • README.md
  • internal/services/crossseed/crossseed_test.go
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:209-212
Timestamp: 2025-11-28T20:32:30.126Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The cross-seed recheck-resume worker intentionally runs for the process lifetime and keys pending entries by hash only. This is acceptable under the current constraint that background seeded-search runs operate on a single instance at a time; graceful shutdown and instanceID|hash keying are deferred by design.
📚 Learning: 2025-11-28T20:32:30.126Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:209-212
Timestamp: 2025-11-28T20:32:30.126Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The cross-seed recheck-resume worker intentionally runs for the process lifetime and keys pending entries by hash only. This is acceptable under the current constraint that background seeded-search runs operate on a single instance at a time; graceful shutdown and instanceID|hash keying are deferred by design.

Applied to files:

  • internal/models/crossseed.go
  • internal/services/crossseed/models.go
  • internal/services/crossseed/matching_layout_test.go
  • internal/services/crossseed/service.go
📚 Learning: 2025-11-28T22:21:20.730Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:2415-2457
Timestamp: 2025-11-28T22:21:20.730Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The determineSavePath function intentionally includes a contentLayout string parameter for future/content-layout branching and API consistency. Its presence is by design even if unused in the current body; do not flag as an issue in reviews.

Applied to files:

  • internal/models/crossseed.go
  • internal/services/crossseed/layout.go
  • internal/services/crossseed/align.go
  • internal/services/crossseed/models.go
  • internal/services/crossseed/layout_test.go
  • internal/services/crossseed/matching_layout_test.go
  • internal/services/crossseed/matching.go
  • internal/services/crossseed/service.go
📚 Learning: 2025-12-28T18:44:10.496Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 876
File: internal/logstream/hub_test.go:188-192
Timestamp: 2025-12-28T18:44:10.496Z
Learning: In Go 1.25 (Aug 2025), use wg.Go(func()) to spawn a goroutine and automate the Add/Done lifecycle. Replace manual patterns like wg.Add(1); go func(){ defer wg.Done(); ... }() with wg.Go(func(){ ... }). Ensure the codebase builds with Go 1.25+ and apply this in relevant Go files (e.g., internal/logstream/hub_test.go). If targeting older Go versions, maintain the existing pattern.

Applied to files:

  • internal/models/crossseed.go
  • internal/services/crossseed/layout.go
  • internal/services/crossseed/align.go
  • internal/services/crossseed/models.go
  • internal/services/crossseed/layout_test.go
  • internal/services/crossseed/matching_layout_test.go
  • internal/services/crossseed/align_test.go
  • internal/services/crossseed/matching.go
  • internal/services/crossseed/service.go
  • internal/services/crossseed/matching_hdr_test.go
📚 Learning: 2025-11-21T21:11:50.633Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 625
File: internal/qbittorrent/sync_manager.go:1112-1123
Timestamp: 2025-11-21T21:11:50.633Z
Learning: In internal/qbittorrent/sync_manager.go, the GetCachedFilesBatch interface documentation (around line 39-40) should specify "uppercase hex" instead of "lowercase hex" to match the actual normalization practice used throughout the codebase (e.g., normalizeHash in internal/services/crossseed/service.go uses strings.ToUpper, and hash filtering uses uppercase).

Applied to files:

  • internal/services/crossseed/layout.go
📚 Learning: 2025-11-06T12:11:04.963Z
Learnt from: Audionut
Repo: autobrr/qui PR: 553
File: internal/services/crossseed/service.go:1045-1082
Timestamp: 2025-11-06T12:11:04.963Z
Learning: The autobrr/qui project uses a custom go-qbittorrent client library (github.com/autobrr/go-qbittorrent) that supports both "paused" and "stopped" parameters when adding torrents via the options map. Both parameters should be set together when controlling torrent start state, as seen in internal/services/crossseed/service.go and throughout the codebase.

Applied to files:

  • internal/services/crossseed/models.go
📚 Learning: 2025-11-25T22:46:03.762Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 632
File: internal/backups/service.go:1401-1404
Timestamp: 2025-11-25T22:46:03.762Z
Learning: In qui's backup service (internal/backups/service.go), background torrent downloads initiated during manifest import intentionally use a fire-and-forget pattern with the shared service context (s.ctx). Per-run cancellation is not needed, as orphaned downloads completing after run deletion are considered harmless and acceptable. This design prioritizes simplicity over per-run lifecycle management for background downloads.

Applied to files:

  • internal/services/crossseed/matching_layout_test.go
📚 Learning: 2025-12-03T18:11:08.682Z
Learnt from: finevan
Repo: autobrr/qui PR: 677
File: web/src/components/torrents/AddTorrentDialog.tsx:496-504
Timestamp: 2025-12-03T18:11:08.682Z
Learning: In the AddTorrentDialog component (web/src/components/torrents/AddTorrentDialog.tsx), temporary path settings (useDownloadPath/downloadPath) should be applied per-torrent rather than updating global instance preferences. The UI/UX is designed to suggest that these options apply to the individual torrent being added.

Applied to files:

  • web/src/pages/CrossSeedPage.tsx
🧬 Code graph analysis (5)
internal/services/crossseed/layout.go (1)
pkg/stringutils/normalize.go (1)
  • Normalizer (19-22)
internal/services/crossseed/align.go (1)
pkg/stringutils/normalize.go (1)
  • Normalizer (19-22)
internal/services/crossseed/models.go (1)
web/src/types/index.ts (1)
  • Category (664-667)
internal/services/crossseed/layout_test.go (2)
internal/services/crossseed/layout.go (2)
  • TorrentLayout (18-18)
  • LayoutUnknown (21-21)
pkg/stringutils/normalize.go (1)
  • NewDefaultNormalizer (35-37)
internal/services/crossseed/matching.go (2)
pkg/stringutils/normalize.go (1)
  • Normalizer (19-22)
internal/services/crossseed/ignore_patterns.go (2)
  • DefaultIgnoredExtensions (11-27)
  • DefaultIgnoredPathKeywords (32-40)
🔇 Additional comments (16)
internal/services/crossseed/models.go (3)

20-76: Struct shape and defaults align with API after ignorePatterns removal

The updated CrossSeedAutomationSettings (including TargetInstanceIDs []int with a default of []int{} in DefaultCrossSeedAutomationSettings) looks consistent with the API intent and avoids null vs [] ambiguity on the wire. No stray ignorePatterns fields remain here.

Also applies to: 90-133


295-385: Settings load path correctly drops ignore_patterns while keeping instance/indexer IDs JSON-backed

GetSettings now selects target_instance_ids / target_indexer_ids into instancesJSON / indexersJSON and decodes them via decodeIntSlice, with clean handling of NULL/empty as []. The removed ignore_patterns column is no longer referenced, which matches the migration, and the rest of the scan order stays consistent.


509-563: Upsert column list, placeholders, and Exec args stay in sync post‑refactor

The INSERT/ON CONFLICT block now omits ignore_patterns and includes target_instance_ids / target_indexer_ids with matching instanceJSON / indexerJSON arguments. Column count, ? placeholders, and ExecContext arguments line up correctly, so the migration to drop ignore_patterns won’t break persistence.

Also applies to: 566-611

internal/services/crossseed/align_test.go (1)

651-920: Content‑mismatch tests correctly capture hardcoded ignore semantics

The updated TestHasContentFileSizeMismatch table now:

  • Treats .nfo / .srt and sample path variants as ignored (no mismatch), including the “all ignored files” case.
  • Confirms non‑ignored extras like .zip still trigger mismatches and that mismatched sizes are surfaced via expectedFiles.
  • Uses the new hasContentFileSizeMismatch(sourceFiles, candidateFiles, normalizer) signature without any per‑request ignorePatterns.

This gives good coverage of the new hardcoded ignore lists and path‑keyword handling.

web/src/pages/CrossSeedPage.tsx (2)

80-159: Global settings/frontend shape correctly updated to drop ignorePatterns

GlobalCrossSeedSettings, DEFAULT_GLOBAL_SETTINGS, the globalSettings initialization useEffect, and buildGlobalPatch all line up after removing ignorePatterns. The remaining fields (category mode booleans, customCategory, tagging, skip* flags, webhook source filters, external program) are passed through consistently, so the frontend patch payload still fully represents the server’s global cross‑seed settings without leaking the old ignorePatterns knob.

Also applies to: 782-817, 868-931


2604-2610: Save global button wiring remains correct after refactor

The “Save global cross-seed settings” button still delegates to handleSaveGlobal and is disabled while patchSettingsMutation is pending, preventing double‑submits. No residual dependency on ignorePatterns is present in this flow.

internal/services/crossseed/layout_test.go (1)

15-52: Layout classification tests updated appropriately for hardcoded ignores

TestClassifyTorrentLayout now exercises:

  • mkv + sidecar .nfoLayoutFiles,
  • classic multi‑part RAR + .sfvLayoutArchives,
  • .tar.gzLayoutArchives via the new multi‑suffix handling,
  • only ignored sidecar files (.txt, .nfo) → LayoutUnknown.

The test’s use of classifyTorrentLayout(tt.files, stringutils.NewDefaultNormalizer()) matches the new signature, and expectations align with the intended archive vs file layout heuristic.

Also applies to: 54-57

internal/services/crossseed/matching_layout_test.go (2)

18-39: Layout‑aware match selection tests correctly exercise new signatures

The updated calls:

  • svc.getMatchType(&sourceRelease, &candidateRelease, sourceFiles, archiveFiles) and friends, and
  • svc.findBestCandidateMatch(ctx, candidate, &sourceRelease, sourceFiles, filesByHash, 5.0)

all reflect the new APIs without ignorePatterns. The tests still assert:

  • mkv vs rar candidates don’t match, but archive↔archive and file↔file do,
  • findBestCandidateMatch prefers the mkv candidate over rar when the source is mkv,
  • tie‑breaking prefers the top‑level‑folder layout when match type is identical, and
  • a season‑pack source correctly rejects a single‑episode candidate with rejectReasonSeasonPackFromEpisode.

These are good regression checks for the new hardcoded‑ignore + layout‑compatibility flow.

Also applies to: 41-114, 116-149


236-255: Title/release‑key fallback tests remain valid without ignorePatterns parameter

The getMatchTypeFromTitle tests now pass only candidateFiles and still cover:

  • Fallback to a permissive "partial-in-pack" when both releases are episodic and parsing yields no usable keys (random_data_file.bin),
  • Requiring matching release keys for non‑episodic content (mismatched years yield no match; matching years give "partial-in-pack"),
  • Game scene RAR releases matching on title/group alone ("release-match"), and
  • Filename‑based fallback to "size" matches for single‑file torrents with equivalent base names.

These updated call sites match the refactored signature and keep the intended matching semantics well covered.

Also applies to: 258-285, 287-313, 315-350, 352-371

internal/services/crossseed/align.go (1)

580-618: LGTM! Signature correctly updated to use hardcoded ignore patterns.

The removal of the ignorePatterns parameter and the updated shouldIgnoreFile calls align with the PR objective of centralizing ignore logic to hardcoded defaults.

internal/services/crossseed/matching_hdr_test.go (1)

182-182: LGTM! Test correctly updated for new signature.

The test call properly reflects the removal of the ignorePatterns parameter from getMatchType.

internal/services/crossseed/matching.go (4)

501-608: LGTM! Function signature correctly updated.

The removal of ignorePatterns from getMatchTypeFromTitle and the updated shouldIgnoreFile call at Line 505 correctly delegate filtering to the hardcoded ignore logic.


619-746: LGTM! Function signature correctly updated.

The removal of ignorePatterns from getMatchTypeWithReason is correct. The shouldIgnoreFile calls at Lines 650 and 670 properly use the new signature with just the normalizer.


814-934: LGTM! Function signature correctly updated.

The removal of ignorePatterns from getMatchType aligns with the PR objective. The filtering logic at Lines 843 and 864 correctly uses the refactored shouldIgnoreFile.


1049-1070: LGTM! Refactor correctly implements hardcoded ignore logic.

The rewritten shouldIgnoreFile function now uses DefaultIgnoredExtensions and DefaultIgnoredPathKeywords from the hardcoded lists, replacing the previous pattern-based approach. The implementation is straightforward:

  • Extension matching (Lines 1056-1060): Uses strings.HasSuffix to check file extensions.
  • Keyword matching (Lines 1063-1067): Uses strings.Contains to check path keywords.

The keyword matching with Contains could theoretically match partial words (e.g., "sampleton" containing "sample"), but this is acceptable given:

  1. Scene releases rarely use such naming
  2. The PR intentionally simplifies the logic
  3. The hardcoded lists come from cross-seed.org best practices
internal/services/crossseed/service.go (1)

2350-2367: getMatchTypeFromTitle call now cleanly aligns with updated matching API

The updated call signature (getMatchTypeFromTitle(req.TorrentName, torrent.Name, targetRelease, candidateRelease, candidateFiles)) matches the revised matching API and correctly passes the parsed releases plus the candidate’s files for file‑level verification. Behavior is consistent with the new hardcoded ignore patterns; nothing to fix here.

@s0up4200
s0up4200 merged commit 02a68e5 into develop Jan 2, 2026
12 checks passed
@s0up4200
s0up4200 deleted the refactor/hardcode-cross-seed-ignore-patterns branch January 2, 2026 09:21
alexlebens pushed a commit to alexlebens/infrastructure that referenced this pull request Jan 4, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.11.0` → `v1.12.0` |

---

### Release Notes

<details>
<summary>autobrr/qui (ghcr.io/autobrr/qui)</summary>

### [`v1.12.0`](https://github.com/autobrr/qui/releases/tag/v1.12.0)

[Compare Source](autobrr/qui@v1.11.0...v1.12.0)

#### Changelog

##### New Features

- [`202e950`](autobrr/qui@202e950): feat(automations): Add `free_space` condition ([#&#8203;1061](autobrr/qui#1061)) ([@&#8203;Barcode-eng](https://github.com/Barcode-eng))
- [`3b106d6`](autobrr/qui@3b106d6): feat(automations): make conditions optional for non-delete rules and add drag reorder ([#&#8203;939](autobrr/qui#939)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`0684d75`](autobrr/qui@0684d75): feat(config): Add QUI\_\_OIDC\_CLIENT\_SECRET\_FILE env var ([#&#8203;841](autobrr/qui#841)) ([@&#8203;PedDavid](https://github.com/PedDavid))
- [`dac0173`](autobrr/qui@dac0173): feat(config): allow disabling tracker icon fetching ([#&#8203;823](autobrr/qui#823)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`dc10bad`](autobrr/qui@dc10bad): feat(crossseed): add cancel run and opt-in errored torrent recovery ([#&#8203;918](autobrr/qui#918)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cd1fcc9`](autobrr/qui@cd1fcc9): feat(crossseed): add custom category option for cross-seeds ([#&#8203;907](autobrr/qui#907)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d189fe9`](autobrr/qui@d189fe9): feat(crossseed): add indexerName to webhook apply + fix category mode defaults ([#&#8203;916](autobrr/qui#916)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`03a147e`](autobrr/qui@03a147e): feat(crossseed): add option to skip recheck-required matches ([#&#8203;825](autobrr/qui#825)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`edae00a`](autobrr/qui@edae00a): feat(crossseed): add optional hardlink mode for cross-seeding ([#&#8203;849](autobrr/qui#849)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`0938436`](autobrr/qui@0938436): feat(crossseed): add source aliasing for WEB/WEB-DL/WEBRip precheck matching ([#&#8203;874](autobrr/qui#874)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`65f6129`](autobrr/qui@65f6129): feat(crossseed): show failure reasons, prune runs, and add cache cleanup ([#&#8203;923](autobrr/qui#923)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e10fba8`](autobrr/qui@e10fba8): feat(details): torrent details panel improvements ([#&#8203;884](autobrr/qui#884)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`6921140`](autobrr/qui@6921140): feat(docs): add Docusaurus documentation site ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`6a5a66c`](autobrr/qui@6a5a66c): feat(docs): add Icon and webUI variables to the Unraid install guide ([#&#8203;942](autobrr/qui#942)) ([@&#8203;BaukeZwart](https://github.com/BaukeZwart))
- [`281fce7`](autobrr/qui@281fce7): feat(docs): add local search plugin ([#&#8203;1076](autobrr/qui#1076)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`566de08`](autobrr/qui@566de08): feat(docs): add qui logo, update readme, remove v4 flag ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`b83ac5a`](autobrr/qui@b83ac5a): feat(docs): apply minimal.css theme to Docusaurus ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`fe6a6df`](autobrr/qui@fe6a6df): feat(docs): improve documentation pages and add support page ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`62a7ad5`](autobrr/qui@62a7ad5): feat(docs): use qui favicon ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`5d124c0`](autobrr/qui@5d124c0): feat(orphan): add auto cleanup mode ([#&#8203;897](autobrr/qui#897)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`3172ad9`](autobrr/qui@3172ad9): feat(settings): add log settings + live log stream ([#&#8203;876](autobrr/qui#876)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`3c1b34b`](autobrr/qui@3c1b34b): feat(torrents): add "torrent introuvable" to unregistered status ([#&#8203;836](autobrr/qui#836)) ([@&#8203;kephasdev](https://github.com/kephasdev))
- [`afe4d39`](autobrr/qui@afe4d39): feat(torrents): add tracker URL editing for single torrents ([#&#8203;848](autobrr/qui#848)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`76dedd7`](autobrr/qui@76dedd7): feat(torrents): update GeneralTabHorizontal to display limits and improve layout ([#&#8203;1078](autobrr/qui#1078)) ([@&#8203;martylukyy](https://github.com/martylukyy))
- [`6831c24`](autobrr/qui@6831c24): feat(ui): unify payment options into single dialog ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`4dcdf7f`](autobrr/qui@4dcdf7f): feat(web): add local file access indicator to instance cards ([#&#8203;911](autobrr/qui#911)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a560e5e`](autobrr/qui@a560e5e): feat(web): compact torrent details panel ([#&#8203;833](autobrr/qui#833)) ([@&#8203;martylukyy](https://github.com/martylukyy))
- [`557e7bd`](autobrr/qui@557e7bd): feat: add issue/discussion template ([#&#8203;945](autobrr/qui#945)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`8b93719`](autobrr/qui@8b93719): feat: add workflow automation system with category actions, orphan scanner, and hardlink detection ([#&#8203;818](autobrr/qui#818)) ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Bug Fixes

- [`b85ad6b`](autobrr/qui@b85ad6b): fix(automations): allow delete rules to match incomplete torrents ([#&#8203;926](autobrr/qui#926)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`ae06200`](autobrr/qui@ae06200): fix(automations): make tags field condition operators tag-aware ([#&#8203;908](autobrr/qui#908)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`ace0101`](autobrr/qui@ace0101): fix(crossseed): detect folder mismatch for bare file to folder cross-seeds ([#&#8203;846](autobrr/qui#846)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`1cc1243`](autobrr/qui@1cc1243): fix(crossseed): enforce resolution and language matching with sensible defaults ([#&#8203;855](autobrr/qui#855)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cefb9cd`](autobrr/qui@cefb9cd): fix(crossseed): execute external program reliably after injection ([#&#8203;1083](autobrr/qui#1083)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`867e2da`](autobrr/qui@867e2da): fix(crossseed): improve matching with size validation and relaxed audio checks ([#&#8203;845](autobrr/qui#845)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`4b5079b`](autobrr/qui@4b5079b): fix(crossseed): persist custom category settings in PATCH handler ([#&#8203;913](autobrr/qui#913)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cfbbc1f`](autobrr/qui@cfbbc1f): fix(crossseed): prevent season packs matching episodes ([#&#8203;854](autobrr/qui#854)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c7c1706`](autobrr/qui@c7c1706): fix(crossseed): reconcile interrupted runs on startup ([#&#8203;1084](autobrr/qui#1084)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`7d633bd`](autobrr/qui@7d633bd): fix(crossseed): use ContentPath for manually-managed single-file torrents ([#&#8203;832](autobrr/qui#832)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d5db761`](autobrr/qui@d5db761): fix(database): include arr\_instances in string pool cleanup + remove auto-recovery ([#&#8203;898](autobrr/qui#898)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c73ec6f`](autobrr/qui@c73ec6f): fix(database): prevent race between stmt cache access and db close ([#&#8203;840](autobrr/qui#840)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a40b872`](autobrr/qui@a40b872): fix(db): drop legacy hardlink columns from cross\_seed\_settings ([#&#8203;912](autobrr/qui#912)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e400af3`](autobrr/qui@e400af3): fix(db): recover wedged SQLite writer + stop cross-seed tight loop ([#&#8203;890](autobrr/qui#890)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`90e15b4`](autobrr/qui@90e15b4): fix(deps): update rls to recognize IP as iPlayer ([#&#8203;922](autobrr/qui#922)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`8e81b9f`](autobrr/qui@8e81b9f): fix(proxy): honor TLSSkipVerify for proxied requests ([#&#8203;1051](autobrr/qui#1051)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`eb2bee0`](autobrr/qui@eb2bee0): fix(security): redact sensitive URL parameters in logs ([#&#8203;853](autobrr/qui#853)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`40982bc`](autobrr/qui@40982bc): fix(themes): prevent reset on license errors, improve switch performance ([#&#8203;844](autobrr/qui#844)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a8a32f7`](autobrr/qui@a8a32f7): fix(ui): incomplete torrents aren't "Completed: 1969-12-31" ([#&#8203;851](autobrr/qui#851)) ([@&#8203;finevan](https://github.com/finevan))
- [`5908bba`](autobrr/qui@5908bba): fix(ui): preserve category collapse state when toggling incognito mode ([#&#8203;834](autobrr/qui#834)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`25c847e`](autobrr/qui@25c847e): fix(ui): torrents with no creation metadata don't display 1969 ([#&#8203;873](autobrr/qui#873)) ([@&#8203;finevan](https://github.com/finevan))
- [`6403b6a`](autobrr/qui@6403b6a): fix(web): column filter status now matches all states in category ([#&#8203;880](autobrr/qui#880)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`eafc4e7`](autobrr/qui@eafc4e7): fix(web): make delete cross-seed check rely on content\_path matches ([#&#8203;1080](autobrr/qui#1080)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d57c749`](autobrr/qui@d57c749): fix(web): only show selection checkbox on normal view ([#&#8203;830](autobrr/qui#830)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`60338f6`](autobrr/qui@60338f6): fix(web): optimize TorrentDetailsPanel for mobile view and make tabs scrollable horizontally ([#&#8203;1066](autobrr/qui#1066)) ([@&#8203;martylukyy](https://github.com/martylukyy))
- [`aedab87`](autobrr/qui@aedab87): fix(web): speed limit input reformatting during typing ([#&#8203;881](autobrr/qui#881)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`df7f3e0`](autobrr/qui@df7f3e0): fix(web): truncate file progress percentage instead of rounding ([#&#8203;919](autobrr/qui#919)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2fadd01`](autobrr/qui@2fadd01): fix(web): update eslint config for flat config compatibility ([#&#8203;879](autobrr/qui#879)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`721cedd`](autobrr/qui@721cedd): fix(web): use fixed heights for mobile torrent cards ([#&#8203;812](autobrr/qui#812)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`a7db605`](autobrr/qui@a7db605): fix: remove pnpm-workspace.yaml breaking CI ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c0ddc0a`](autobrr/qui@c0ddc0a): fix: use prefix matching for allowed bash commands ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Other Changes

- [`fff52ce`](autobrr/qui@fff52ce): chore(ci): disable reviewer ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`7ef2a38`](autobrr/qui@7ef2a38): chore(ci): fix automated triage and deduplication workflows ([#&#8203;1057](autobrr/qui#1057)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d84910b`](autobrr/qui@d84910b): chore(docs): move Tailwind to documentation workspace only ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`37ebe05`](autobrr/qui@37ebe05): chore(docs): move netlify.toml to documentation directory ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e25de38`](autobrr/qui@e25de38): chore(docs): remove disclaimer ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c59b809`](autobrr/qui@c59b809): chore(docs): update support sections ([#&#8203;1063](autobrr/qui#1063)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`b723523`](autobrr/qui@b723523): chore(tests): remove dead tests and optimize slow test cases ([#&#8203;842](autobrr/qui#842)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`662a1c6`](autobrr/qui@662a1c6): chore(workflows): update runners from 4vcpu to 2vcpu for all jobs ([#&#8203;859](autobrr/qui#859)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`46f2a1c`](autobrr/qui@46f2a1c): chore: clean up repo root by moving Docker, scripts, and community docs ([#&#8203;1054](autobrr/qui#1054)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2f27c0d`](autobrr/qui@2f27c0d): chore: remove old issue templates ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`04f361a`](autobrr/qui@04f361a): ci(triage): add labeling for feature-requests-ideas discussions ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f249c69`](autobrr/qui@f249c69): ci(triage): remove needs-triage label after applying labels ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`bdda1de`](autobrr/qui@bdda1de): ci(workflows): add self-dispatch workaround for discussion events ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a9732a2`](autobrr/qui@a9732a2): ci(workflows): increase max-turns to 25 for Claude workflows ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d7d830d`](autobrr/qui@d7d830d): docs(README): add Buy Me a Coffee link ([#&#8203;863](autobrr/qui#863)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`266d92e`](autobrr/qui@266d92e): docs(readme): Clarify ignore pattern ([#&#8203;878](autobrr/qui#878)) ([@&#8203;quorn23](https://github.com/quorn23))
- [`9586084`](autobrr/qui@9586084): docs(readme): add banner linking to stable docs ([#&#8203;925](autobrr/qui#925)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e36a621`](autobrr/qui@e36a621): docs(readme): use markdown link for Polar URL ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`9394676`](autobrr/qui@9394676): docs: add frontmatter titles and descriptions, remove marketing language ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`ba9d45e`](autobrr/qui@ba9d45e): docs: add local filesystem access snippet and swizzle Details component ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`4329edd`](autobrr/qui@4329edd): docs: disclaimer about unreleased features ([#&#8203;943](autobrr/qui#943)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`735d065`](autobrr/qui@735d065): docs: improve external programs, orphan scan, reverse proxy, tracker icons documentation ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`78faef2`](autobrr/qui@78faef2): docs: remove premature tip and fix stat command ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`eaad3bf`](autobrr/qui@eaad3bf): docs: update social card image in Docusaurus configuration ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`02a68e5`](autobrr/qui@02a68e5): refactor(crossseed): hardcode ignore patterns for file matching ([#&#8203;915](autobrr/qui#915)) ([@&#8203;s0up4200](https://github.com/s0up4200))

**Full Changelog**: <autobrr/qui@v1.11.0...v1.12.0>

#### Docker images

- `docker pull ghcr.io/autobrr/qui:v1.12.0`
- `docker pull ghcr.io/autobrr/qui:latest`

#### What to do next?

- Join our [Discord server](https://discord.autobrr.com/qui)

Thank you for using qui!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi42OS4yIiwidXBkYXRlZEluVmVyIjoiNDIuNjkuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW1hZ2UiXX0=-->

Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/3060
Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net>
Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant