fix(crossseed): normalize hdr aliases - #1572
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds HDR-aware extraction and normalization to the release parser and updates cross-seed matching to compare HDR sets using HDR-specific normalization (resolving HDR10+ vs HDR10). Tests added/expanded to cover HDR10+/DV and HDR10+/HDR10 alias and format edge cases. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant Parser as Release Parser
participant Enricher as HDR Enricher
participant Normalizer as HDR Normalizer
participant Matcher as Cross-seed Matcher
Client->>Parser: submit release name / parse request
Parser->>Enricher: enrichReleaseHDR(release)
Enricher->>Enricher: scan raw name with hdrTagMatchers
Enricher->>Normalizer: normalizeHDRTags(extractedTags)
Normalizer->>Normalizer: normalizeHDRVariant, dedupe (remove HDR10 when HDR10+ present)
Normalizer-->>Enricher: normalized HDR set
Enricher-->>Parser: release with enriched HDR tags
Parser->>Matcher: FindCandidates(source, candidates)
Matcher->>Normalizer: joinNormalizedHDRSlice(sourceHDR, candidateHDR)
Normalizer-->>Matcher: comparison result
Matcher-->>Client: match / no-match decision
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@pkg/releases/parser.go`:
- Around line 86-91: enrichReleaseHDR currently calls shouldScanRawHDR and then
runs hdrTagMatchers against the full rawName, which lets terminal
scene-group/site tokens (e.g., "-DV") be picked up; update enrichReleaseHDR to
strip the parsed trailing Group/Site token from rawName before running the
hdrTagMatchers loop (use the same parsing logic used elsewhere to identify the
trailing group/site token), and ensure shouldScanRawHDR still gates video-shaped
releases but the matcher scan uses the truncated name; apply the same change to
the other scan locations referenced (the code block around the other hdr scan
loop) so no trailing group/site token is included when matching HDR tags.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 6c419aac-321a-4bd2-aebb-c06d2736df4f
📒 Files selected for processing (5)
internal/services/crossseed/crossseed_test.gointernal/services/crossseed/matching.gointernal/services/crossseed/matching_hdr_test.gopkg/releases/parser.gopkg/releases/parser_test.go
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@pkg/releases/parser.go`:
- Around line 154-166: trimTrailingGroupOrSite currently trims release.Group and
release.Site only once each, leaving a leftover trailing token if removing one
token exposes another (e.g., "...-GROUP-SITE" becomes "...-GROUP"); update
trimTrailingGroupOrSite to repeatedly call trimTrailingParsedToken for the
tokens release.Group and release.Site until trimmed no longer changes (use a
loop that tracks previous value), ensuring you reference the existing function
trimTrailingParsedToken and the variables release.Group, release.Site and
trimmed so trailing tokens are removed until the suffix stabilizes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 6c340a55-978c-4fe4-b214-f7a9766f75e4
📒 Files selected for processing (2)
pkg/releases/parser.gopkg/releases/parser_test.go
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@pkg/releases/parser.go`:
- Around line 177-199: trimTrailingParsedToken currently only strips tokens that
sit at the literal end of rawName, so filenames with an extension (e.g.,
Movie.2024.2160p.BluRay.x265-DV.mkv) keep trailing group/site tokens before the
extension; update trimTrailingParsedToken to also match the token when followed
by an optional file extension (e.g., allow patterns that permit `(\.[^./\\]+)?$`
after the quoted token) and then trim the matched portion the same way, update
the regex patterns used in trimTrailingParsedToken to accept an optional
trailing extension, and add a regression unit test case that asserts a filename
like `Movie.2024.2160p.BluRay.x265-DV.mkv` yields the expected trimmed result
without preserving `DV`.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 22c88f8a-2a89-4d30-8a1d-e51b6a271fb1
📒 Files selected for processing (2)
pkg/releases/parser.gopkg/releases/parser_test.go
There was a problem hiding this comment.
🧹 Nitpick comments (1)
pkg/releases/parser.go (1)
126-151: Preservenilwhen normalization finds no HDR tags.
normalizeHDRTagsnow returns a non-nil empty slice for non-HDR releases, soenrichReleaseHDRchanges the zero-value behavior fromnilto[]. If any caller serializes or comparesrelease.HDR, that is a visible behavior change unrelated to the alias fix.Suggested adjustment
func normalizeHDRTags(tags []string) []string { seen := make(map[string]struct{}, len(tags)) hasHDR10Plus := false @@ if hasHDR10Plus { delete(seen, "HDR10") } + + if len(seen) == 0 { + return nil + } normalized := make([]string, 0, len(seen)) for tag := range seen { normalized = append(normalized, tag) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/releases/parser.go` around lines 126 - 151, normalizeHDRTags currently returns a non-nil empty slice when no canonical HDR tags are found, changing zero-value behavior of fields like release.HDR; modify normalizeHDRTags so it returns nil when there are no normalized tags (e.g., avoid allocating normalized until you know seen is non-empty or return nil if len(seen)==0), keeping the existing canonicalization, HDR10+ handling, and sorting logic intact; ensure callers such as enrichReleaseHDR that assign to release.HDR still observe nil when no tags are present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@pkg/releases/parser.go`:
- Around line 126-151: normalizeHDRTags currently returns a non-nil empty slice
when no canonical HDR tags are found, changing zero-value behavior of fields
like release.HDR; modify normalizeHDRTags so it returns nil when there are no
normalized tags (e.g., avoid allocating normalized until you know seen is
non-empty or return nil if len(seen)==0), keeping the existing canonicalization,
HDR10+ handling, and sorting logic intact; ensure callers such as
enrichReleaseHDR that assign to release.HDR still observe nil when no tags are
present.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 3aa54119-517d-4e06-8ff5-1326f1379673
📒 Files selected for processing (2)
pkg/releases/parser.gopkg/releases/parser_test.go
There was a problem hiding this comment.
🧹 Nitpick comments (1)
pkg/releases/parser.go (1)
196-200: Regex compilation inside loop may impact performance on cache misses.
regexp.MustCompileis called for each pattern per invocation, andtrimTrailingParsedTokenis called iteratively fromtrimTrailingGroupOrSite. While the Parser-level cache mitigates repeated parsing of the same release names, high-throughput scenarios with many unique names could see overhead.Consider caching compiled regexes per token or using string operations for simple suffix matching where feasible.
♻️ Potential optimization using string-based matching for simple cases
func trimTrailingParsedToken(rawName, token string) string { token = strings.TrimSpace(token) if rawName == "" || token == "" { return rawName } + // Fast path: check if token appears near end before regex + lowerName := strings.ToLower(rawName) + lowerToken := strings.ToLower(token) + if !strings.Contains(lowerName[max(0, len(lowerName)-len(token)-10):], lowerToken) { + return rawName + } + quoted := regexp.QuoteMeta(token)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/releases/parser.go` around lines 196 - 200, The loop in trimTrailingParsedToken repeatedly calls regexp.MustCompile(pattern) for each pattern causing unnecessary compilation overhead; modify trimTrailingParsedToken so regexes are precompiled and cached (e.g., a map[string]*regexp.Regexp at parser level or package init) and reused across invocations, and where patterns are simple suffixes replace the regex with faster string operations (strings.HasSuffix/TrimSuffix) to avoid regex overhead; ensure the change updates any callers such as trimTrailingGroupOrSite to use the cached/precompiled regexes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@pkg/releases/parser.go`:
- Around line 196-200: The loop in trimTrailingParsedToken repeatedly calls
regexp.MustCompile(pattern) for each pattern causing unnecessary compilation
overhead; modify trimTrailingParsedToken so regexes are precompiled and cached
(e.g., a map[string]*regexp.Regexp at parser level or package init) and reused
across invocations, and where patterns are simple suffixes replace the regex
with faster string operations (strings.HasSuffix/TrimSuffix) to avoid regex
overhead; ensure the change updates any callers such as trimTrailingGroupOrSite
to use the cached/precompiled regexes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 548c89ac-cba6-4969-9d1d-0fa3aaa2f314
📒 Files selected for processing (2)
pkg/releases/parser.gopkg/releases/parser_test.go
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.14.1` → `v1.15.0` | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/2) for more information. --- ### Release Notes <details> <summary>autobrr/qui (ghcr.io/autobrr/qui)</summary> ### [`v1.15.0`](https://github.com/autobrr/qui/releases/tag/v1.15.0) [Compare Source](autobrr/qui@v1.14.1...v1.15.0) #### Changelog ##### Breaking change CORS is disabled by default; enable by setting QUI\_\_CORS\_ALLOWED\_ORIGINS with explicit origins (http(s)://host\[:port]). See <https://getqui.com/docs/advanced/sso-proxy-cors> ##### New Features - [`93786a2`](autobrr/qui@93786a2): feat(automations): add configurable processing priority/sorting ([#​1235](autobrr/qui#1235)) ([@​Oscariremma](https://github.com/Oscariremma)) - [`45eaf1f`](autobrr/qui@45eaf1f): feat(database): add postgres and sqlite migration CLI ([#​1530](autobrr/qui#1530)) ([@​s0up4200](https://github.com/s0up4200)) - [`430f5d1`](autobrr/qui@430f5d1): feat(torrents): mediaInfo dialog ([#​1537](autobrr/qui#1537)) ([@​s0up4200](https://github.com/s0up4200)) - [`8eb8903`](autobrr/qui@8eb8903): feat(web): Add persistence to unified instance filter in sidebar ([#​1560](autobrr/qui#1560)) ([@​drtaru](https://github.com/drtaru)) - [`7aadde7`](autobrr/qui@7aadde7): feat(web): add path autocomplete to set location dialog ([#​1432](autobrr/qui#1432)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`077f32c`](autobrr/qui@077f32c): feat: add mediainfo api endpoint ([#​1545](autobrr/qui#1545)) ([@​Audionut](https://github.com/Audionut)) - [`99cf695`](autobrr/qui@99cf695): feat: endpoint to trigger directory scans from external tools ([#​1559](autobrr/qui#1559)) ([@​s0up4200](https://github.com/s0up4200)) - [`8956f9b`](autobrr/qui@8956f9b): feat: unify bulk tag editor ([#​1571](autobrr/qui#1571)) ([@​s0up4200](https://github.com/s0up4200)) ##### Bug Fixes - [`552d617`](autobrr/qui@552d617): fix(api): align add torrent OpenAPI field ([#​1617](autobrr/qui#1617)) ([@​s0up4200](https://github.com/s0up4200)) - [`424f7a0`](autobrr/qui@424f7a0): fix(api): restrict CORS to explicit allowlist ([#​1551](autobrr/qui#1551)) ([@​s0up4200](https://github.com/s0up4200)) - [`38991d8`](autobrr/qui@38991d8): fix(auth): allow loopback health probes ([#​1621](autobrr/qui#1621)) ([@​s0up4200](https://github.com/s0up4200)) - [`4ae88c9`](autobrr/qui@4ae88c9): fix(automations): align include-cross-seeds category apply ([#​1517](autobrr/qui#1517)) ([@​s0up4200](https://github.com/s0up4200)) - [`6a127a8`](autobrr/qui@6a127a8): fix(automations): scope skipWithin to only deleted action ([#​1538](autobrr/qui#1538)) ([@​jabloink](https://github.com/jabloink)) - [`c776189`](autobrr/qui@c776189): fix(crossseed): avoid completion timeout misses on non-Gazelle torrents ([#​1536](autobrr/qui#1536)) ([@​s0up4200](https://github.com/s0up4200)) - [`b1338a7`](autobrr/qui@b1338a7): fix(crossseed): handle missing webhook collection tags ([#​1610](autobrr/qui#1610)) ([@​s0up4200](https://github.com/s0up4200)) - [`eacbb68`](autobrr/qui@eacbb68): fix(crossseed): normalize hdr aliases ([#​1572](autobrr/qui#1572)) ([@​s0up4200](https://github.com/s0up4200)) - [`537ad46`](autobrr/qui@537ad46): fix(crossseed): queue completion searches and retry rate-limit waits ([#​1523](autobrr/qui#1523)) ([@​s0up4200](https://github.com/s0up4200)) - [`4fc550f`](autobrr/qui@4fc550f): fix(crossseed): use autobrr indexer ids for webhooks ([#​1614](autobrr/qui#1614)) ([@​s0up4200](https://github.com/s0up4200)) - [`08029ad`](autobrr/qui@08029ad): fix(crossseed): valid partial matches being rejected ([#​1291](autobrr/qui#1291)) ([@​rybertm](https://github.com/rybertm)) - [`77eedd9`](autobrr/qui@77eedd9): fix(database): avoid postgres temp-table statement caching ([#​1581](autobrr/qui#1581)) ([@​s0up4200](https://github.com/s0up4200)) - [`25daa17`](autobrr/qui@25daa17): fix(dirscan): honor canceled queued webhook runs ([#​1612](autobrr/qui#1612)) ([@​s0up4200](https://github.com/s0up4200)) - [`56995f1`](autobrr/qui@56995f1): fix(dirscan): queue webhook scans and tighten age filtering ([#​1603](autobrr/qui#1603)) ([@​s0up4200](https://github.com/s0up4200)) - [`444d07b`](autobrr/qui@444d07b): fix(dirscan): select concrete hardlink base dir ([#​1606](autobrr/qui#1606)) ([@​s0up4200](https://github.com/s0up4200)) - [`c35bea0`](autobrr/qui@c35bea0): fix(instances): improve settings dialog scrolling ([#​1569](autobrr/qui#1569)) ([@​nuxencs](https://github.com/nuxencs)) - [`dc501a0`](autobrr/qui@dc501a0): fix(proxy): reauth qbit passthrough requests ([#​1582](autobrr/qui#1582)) ([@​s0up4200](https://github.com/s0up4200)) - [`7950d1d`](autobrr/qui@7950d1d): fix(proxy): search endpoint handling ([#​1524](autobrr/qui#1524)) ([@​Audionut](https://github.com/Audionut)) - [`1076eea`](autobrr/qui@1076eea): fix(qbit): prune empty managed dirs after delete\_with\_files ([#​1604](autobrr/qui#1604)) ([@​s0up4200](https://github.com/s0up4200)) - [`5a3114b`](autobrr/qui@5a3114b): fix(qbittorrent): stop reboot torrent\_completed spam ([#​1515](autobrr/qui#1515)) ([@​s0up4200](https://github.com/s0up4200)) - [`1d02e6c`](autobrr/qui@1d02e6c): fix(settings): contain settings tab scrolling ([#​1567](autobrr/qui#1567)) ([@​nuxencs](https://github.com/nuxencs)) - [`f5d69f3`](autobrr/qui@f5d69f3): fix(settings): smoother gradient ([#​1570](autobrr/qui#1570)) ([@​nuxencs](https://github.com/nuxencs)) - [`1c0c3bc`](autobrr/qui@1c0c3bc): fix(torrents): copy MediaInfo summary without brackets ([#​1540](autobrr/qui#1540)) ([@​s0up4200](https://github.com/s0up4200)) - [`3ec913a`](autobrr/qui@3ec913a): fix(web): auto-append slash on path autocomplete selection ([#​1431](autobrr/qui#1431)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`aa2f3da`](autobrr/qui@aa2f3da): fix(web): check field.state.value type in AddTorrentDialog ([#​1613](autobrr/qui#1613)) ([@​s0up4200](https://github.com/s0up4200)) - [`1abfc5e`](autobrr/qui@1abfc5e): fix(web): handle SSO proxy redirect to /index.html ([#​1600](autobrr/qui#1600)) ([@​s0up4200](https://github.com/s0up4200)) - [`1991f90`](autobrr/qui@1991f90): fix(web): warn before enabling reannounce ([#​1583](autobrr/qui#1583)) ([@​s0up4200](https://github.com/s0up4200)) ##### Other Changes - [`4069492`](autobrr/qui@4069492): chore(deps): bump the github group with 3 updates ([#​1535](autobrr/qui#1535)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`a02e9e8`](autobrr/qui@a02e9e8): chore(deps): bump the github group with 7 updates ([#​1558](autobrr/qui#1558)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`8713667`](autobrr/qui@8713667): chore(deps): bump the golang group with 15 updates ([#​1543](autobrr/qui#1543)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`420607e`](autobrr/qui@420607e): chore(go,ci): adopt go fix, bump to 1.26, and speed up PR checks ([#​1480](autobrr/qui#1480)) ([@​s0up4200](https://github.com/s0up4200)) - [`0d0df45`](autobrr/qui@0d0df45): docs: add password reset section to CLI commands ([#​1598](autobrr/qui#1598)) ([@​s0up4200](https://github.com/s0up4200)) - [`9ef56a2`](autobrr/qui@9ef56a2): refactor(makefile): windows support ([#​1546](autobrr/qui#1546)) ([@​Audionut](https://github.com/Audionut)) - [`7899cc8`](autobrr/qui@7899cc8): refactor(reflinking): add windows ReFS filesystem support ([#​1576](autobrr/qui#1576)) ([@​Audionut](https://github.com/Audionut)) - [`51d34ab`](autobrr/qui@51d34ab): refactor(releases): share hdr normalization helpers ([#​1586](autobrr/qui#1586)) ([@​s0up4200](https://github.com/s0up4200)) - [`c7f4e3d`](autobrr/qui@c7f4e3d): refactor(web): tighten unified scope navigation ([#​1618](autobrr/qui#1618)) ([@​s0up4200](https://github.com/s0up4200)) - [`4b05177`](autobrr/qui@4b05177): test(handlers): cover tag baseline field requests ([@​s0up4200](https://github.com/s0up4200)) **Full Changelog**: <autobrr/qui@v1.14.1...v1.15.0> #### Docker images - `docker pull ghcr.io/autobrr/qui:v1.15.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:eyJjcmVhdGVkSW5WZXIiOiI0My41OS4yIiwidXBkYXRlZEluVmVyIjoiNDMuNTkuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW1hZ2UiXX0=--> Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/4884 Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net> Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
… ) (#12) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.14.1` → `v1.19.0` | --- ### Release Notes <details> <summary>autobrr/qui (ghcr.io/autobrr/qui)</summary> ### [`v1.19.0`](https://github.com/autobrr/qui/releases/tag/v1.19.0) [Compare Source](autobrr/qui@v1.18.0...v1.19.0) ##### Changelog ##### New Features - [`e26bd6b`](autobrr/qui@e26bd6b): feat(actions): include web-dist in release artifacts ([#​1801](autobrr/qui#1801)) ([@​turtletowerz](https://github.com/turtletowerz)) - [`2fabce1`](autobrr/qui@2fabce1): feat(automations): add export to instance action ([#​1736](autobrr/qui#1736)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`3fca808`](autobrr/qui@3fca808): feat(instances): api key authentication ([#​1854](autobrr/qui#1854)) ([@​martylukyy](https://github.com/martylukyy)) - [`4ab1a75`](autobrr/qui@4ab1a75): feat(qbittorrent): show process uptime ([#​1849](autobrr/qui#1849)) ([@​s0up4200](https://github.com/s0up4200)) - [`292ef70`](autobrr/qui@292ef70): feat(torrents): hide filter icon when not active or hovering over ([#​1869](autobrr/qui#1869)) ([@​martylukyy](https://github.com/martylukyy)) - [`3c5cf3b`](autobrr/qui@3c5cf3b): feat(torrents): implement auto-fit width for columns on double-click ([#​1867](autobrr/qui#1867)) ([@​martylukyy](https://github.com/martylukyy)) - [`5a9c538`](autobrr/qui@5a9c538): feat(torrents): set comment ([#​1928](autobrr/qui#1928)) ([@​martylukyy](https://github.com/martylukyy)) - [`754f642`](autobrr/qui@754f642): feat(torrents): support new share limit parameters ([#​1872](autobrr/qui#1872)) ([@​martylukyy](https://github.com/martylukyy)) - [`06a5fb6`](autobrr/qui@06a5fb6): feat(torrents): update AddTorrent methods for qbit 5.2.x support ([#​1902](autobrr/qui#1902)) ([@​zze0s](https://github.com/zze0s)) - [`45e3adc`](autobrr/qui@45e3adc): feat: add support for monitored folders ([#​1847](autobrr/qui#1847)) ([@​martylukyy](https://github.com/martylukyy)) ##### Bug Fixes - [`77c7ae8`](autobrr/qui@77c7ae8): fix(automations): discard add torrent response ([#​1904](autobrr/qui#1904)) ([@​s0up4200](https://github.com/s0up4200)) - [`7a368f1`](autobrr/qui@7a368f1): fix(ci): repair docs and release builds ([#​1932](autobrr/qui#1932)) ([@​s0up4200](https://github.com/s0up4200)) - [`8bd114e`](autobrr/qui@8bd114e): fix(crossseed): normalize empty qbit metadata ([#​1887](autobrr/qui#1887)) ([@​s0up4200](https://github.com/s0up4200)) - [`92d66f9`](autobrr/qui@92d66f9): fix(crossseed): reuse shared string normalizer to stop goroutine leak ([#​1909](autobrr/qui#1909)) ([@​s0up4200](https://github.com/s0up4200)) - [`3c5d32a`](autobrr/qui@3c5d32a): fix(crossseed): run external programs after link-mode injection ([#​1874](autobrr/qui#1874)) ([@​s0up4200](https://github.com/s0up4200)) - [`b02d2a9`](autobrr/qui@b02d2a9): fix(qbittorrent): handle forced subcategories ([#​1863](autobrr/qui#1863)) ([@​s0up4200](https://github.com/s0up4200)) - [`83cdb01`](autobrr/qui@83cdb01): fix(qbittorrent): handle new tracker statuses ([#​1879](autobrr/qui#1879)) ([@​s0up4200](https://github.com/s0up4200)) - [`b358ab4`](autobrr/qui@b358ab4): fix(rss): mirror torrentParams to legacy flat fields for qBit < 5.0 compat ([#​1846](autobrr/qui#1846)) ([@​frrad](https://github.com/frrad)) - [`5bcf648`](autobrr/qui@5bcf648): fix(seasonpacker): windows path handling ([#​1910](autobrr/qui#1910)) ([@​Audionut](https://github.com/Audionut)) - [`7de10c4`](autobrr/qui@7de10c4): fix(torrents): clear filters in unified-view empty state ([#​1898](autobrr/qui#1898)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`38f7bd3`](autobrr/qui@38f7bd3): fix(web): Show collapsed folders when searching torrent contents ([#​1850](autobrr/qui#1850)) ([@​ewenjo](https://github.com/ewenjo)) - [`d70d0bb`](autobrr/qui@d70d0bb): fix(web): keep showing torrent column filter icons on touch devices ([#​1881](autobrr/qui#1881)) ([@​martylukyy](https://github.com/martylukyy)) - [`cecbad7`](autobrr/qui@cecbad7): fix(web): select-all bulk actions delete more torrents than visible when filters are stacked ([#​1926](autobrr/qui#1926)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`780c4aa`](autobrr/qui@780c4aa): fix(web): sidebar element collisions ([#​1876](autobrr/qui#1876)) ([@​martylukyy](https://github.com/martylukyy)) - [`b621973`](autobrr/qui@b621973): fix(web): use unique keys for duplicate search results ([#​1886](autobrr/qui#1886)) ([@​GtwoK](https://github.com/GtwoK)) ##### Other Changes - [`ffda071`](autobrr/qui@ffda071): chore(deps): bump [@​babel/plugin-transform-modules-systemjs](https://github.com/babel/plugin-transform-modules-systemjs) from 7.28.5 to 7.29.4 in /documentation ([#​1889](autobrr/qui#1889)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`89ab1c8`](autobrr/qui@89ab1c8): chore(deps): bump [@​babel/plugin-transform-modules-systemjs](https://github.com/babel/plugin-transform-modules-systemjs) from 7.29.0 to 7.29.4 in /web ([#​1888](autobrr/qui#1888)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`c420bb2`](autobrr/qui@c420bb2): chore(deps): bump follow-redirects from 1.15.11 to 1.16.0 in /documentation ([#​1903](autobrr/qui#1903)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`28e4bf9`](autobrr/qui@28e4bf9): chore(deps): bump the github group with 2 updates ([#​1894](autobrr/qui#1894)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`9b241de`](autobrr/qui@9b241de): chore(deps): bump the github group with 3 updates ([#​1861](autobrr/qui#1861)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`4872577`](autobrr/qui@4872577): chore(deps): bump webpack-dev-server from 5.2.2 to 5.2.4 in /documentation ([#​1908](autobrr/qui#1908)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`3e3ec8b`](autobrr/qui@3e3ec8b): chore(deps): bump ws from 8.18.3 to 8.20.1 in /documentation ([#​1907](autobrr/qui#1907)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`25cf511`](autobrr/qui@25cf511): chore(web): migrate to pnpm 11 ([#​1883](autobrr/qui#1883)) ([@​martylukyy](https://github.com/martylukyy)) - [`4b6dce1`](autobrr/qui@4b6dce1): docs: add shared agent instructions symlink ([#​1911](autobrr/qui#1911)) ([@​Audionut](https://github.com/Audionut)) - [`97df42c`](autobrr/qui@97df42c): other(docs): resolve 5 Dependabot security alerts on Docs Site ([#​1906](autobrr/qui#1906)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`5068a4d`](autobrr/qui@5068a4d): refactor(crossseed): gather all results for matching and refine TV based searching ([#​1871](autobrr/qui#1871)) ([@​Audionut](https://github.com/Audionut)) - [`9d3e245`](autobrr/qui@9d3e245): refactor(crossseed): improve anime/AKA handling ([#​1882](autobrr/qui#1882)) ([@​Audionut](https://github.com/Audionut)) - [`6f2b94c`](autobrr/qui@6f2b94c): refactor(torrents): drop unused rename props from TorrentContextMenu ([#​1900](autobrr/qui#1900)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`3ec0605`](autobrr/qui@3ec0605): refactor(web): clean up 180 multiline-ternary warnings repo-wide ([#​1905](autobrr/qui#1905)) ([@​nitrobass24](https://github.com/nitrobass24)) **Full Changelog**: <autobrr/qui@v1.18.0...v1.19.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.19.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! ### [`v1.18.0`](https://github.com/autobrr/qui/releases/tag/v1.18.0) [Compare Source](autobrr/qui@v1.17.0...v1.18.0) ##### Changelog ##### New Features - [`b708bc8`](autobrr/qui@b708bc8): feat(automations): add UPLOADED\_OVER\_SIZE condition field ([#​1830](autobrr/qui#1830)) ([@​com6056](https://github.com/com6056)) - [`565731e`](autobrr/qui@565731e): feat(automations): cross-instance HARDLINK\_SCOPE\_CROSS ([#​1810](autobrr/qui#1810)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`a284860`](autobrr/qui@a284860): feat(dirscan): add webhook download client filters ([#​1751](autobrr/qui#1751)) ([@​s0up4200](https://github.com/s0up4200)) - [`fd54124`](autobrr/qui@fd54124): feat(web): Add option to copy magnet link from the context menu ([#​1835](autobrr/qui#1835)) ([@​pietrocaselani](https://github.com/pietrocaselani)) ##### Bug Fixes - [`ea33304`](autobrr/qui@ea33304): fix(crossseed): broaden TV/movie torznab categories and skip year on TV ([#​1822](autobrr/qui#1822)) ([@​imSp4rky](https://github.com/imSp4rky)) - [`3c3f944`](autobrr/qui@3c3f944): fix(license): unblock stale polar license migration ([#​1799](autobrr/qui#1799)) ([@​s0up4200](https://github.com/s0up4200)) - [`941cf42`](autobrr/qui@941cf42): fix(qbit): stop serving stale maindata to the status bar ([#​1785](autobrr/qui#1785)) ([@​Zariel](https://github.com/Zariel)) - [`ca7590a`](autobrr/qui@ca7590a): fix(rss): populate legacy assignedCategory for qBittorrent < 5.0 comp… ([#​1836](autobrr/qui#1836)) ([@​frrad](https://github.com/frrad)) - [`278441a`](autobrr/qui@278441a): fix(settings): explain disabled API keys ([#​1826](autobrr/qui#1826)) ([@​s0up4200](https://github.com/s0up4200)) - [`0f4eb52`](autobrr/qui@0f4eb52): fix(web): remove deprecated tsconfig baseUrl ([#​1840](autobrr/qui#1840)) ([@​s0up4200](https://github.com/s0up4200)) ##### Other Changes - [`c6dbf9a`](autobrr/qui@c6dbf9a): chore(deps): bump postcss from 8.5.6 to 8.5.10 in /documentation ([#​1837](autobrr/qui#1837)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`053c171`](autobrr/qui@053c171): chore(deps): bump the github group across 1 directory with 3 updates ([#​1834](autobrr/qui#1834)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`4cbedac`](autobrr/qui@4cbedac): chore(deps): bump the golang group with 15 updates ([#​1832](autobrr/qui#1832)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`dd661e8`](autobrr/qui@dd661e8): chore(deps): bump the npm group in /web with 20 updates ([#​1833](autobrr/qui#1833)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`82029d6`](autobrr/qui@82029d6): chore(deps): update go-qbittorrent for new qbt 5.2.x webAPI version ([#​1841](autobrr/qui#1841)) ([@​martylukyy](https://github.com/martylukyy)) - [`6b5b82e`](autobrr/qui@6b5b82e): refactor(time): use seconds and cleanup ([#​1823](autobrr/qui#1823)) ([@​Audionut](https://github.com/Audionut)) - [`f5cb0c1`](autobrr/qui@f5cb0c1): refactor: O(n²) cross-seed lookups in automations preview and execution paths ([#​1829](autobrr/qui#1829)) ([@​nitrobass24](https://github.com/nitrobass24)) **Full Changelog**: <autobrr/qui@v1.17.0...v1.18.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.18.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! ### [`v1.17.0`](https://github.com/autobrr/qui/releases/tag/v1.17.0) [Compare Source](autobrr/qui@v1.16.1...v1.17.0) ##### Changelog ##### Bug Fixes - [`52c5e73`](autobrr/qui@52c5e73): fix(automations): clarify cross-seed condition labels ([#​1763](autobrr/qui#1763)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`70e0032`](autobrr/qui@70e0032): fix(crossseed): skip link-mode category path warnings ([#​1753](autobrr/qui#1753)) ([@​s0up4200](https://github.com/s0up4200)) - [`85df3e7`](autobrr/qui@85df3e7): fix(orphanscan): align content path root detection ([#​1771](autobrr/qui#1771)) ([@​s0up4200](https://github.com/s0up4200)) - [`117d617`](autobrr/qui@117d617): fix(orphanscan): ignore qBittorrent incomplete files ([#​1761](autobrr/qui#1761)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`388415e`](autobrr/qui@388415e): fix(web): fix add torrent/magnet urls ([#​1762](autobrr/qui#1762)) ([@​nitrobass24](https://github.com/nitrobass24)) ##### Other Changes - [`845599a`](autobrr/qui@845599a): chore(ci): speed up CI pipeline (9.3 min → 4.3 min for PRs) ([#​1750](autobrr/qui#1750)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`2b09cf3`](autobrr/qui@2b09cf3): chore: trim embedded web assets and Docker build context ([#​1723](autobrr/qui#1723)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`5262f7c`](autobrr/qui@5262f7c): docs: add migration PR guidance ([#​1748](autobrr/qui#1748)) ([@​s0up4200](https://github.com/s0up4200)) - [`65c7046`](autobrr/qui@65c7046): refactor(search): table & cards cleanup ([#​1768](autobrr/qui#1768)) ([@​nuxencs](https://github.com/nuxencs)) **Full Changelog**: <autobrr/qui@v1.16.1...v1.17.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.17.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! ### [`v1.16.1`](https://github.com/autobrr/qui/releases/tag/v1.16.1) [Compare Source](autobrr/qui@v1.16.0...v1.16.1) ##### Changelog ##### Bug Fixes - [`e177ad9`](autobrr/qui@e177ad9): fix(auth): harden OIDC PKCE flow ([#​1746](autobrr/qui#1746)) ([@​s0up4200](https://github.com/s0up4200)) - [`393e2b7`](autobrr/qui@393e2b7): fix(dirscan): tighten flexible matching and improve diagnostics ([#​1742](autobrr/qui#1742)) ([@​s0up4200](https://github.com/s0up4200)) **Full Changelog**: <autobrr/qui@v1.16.0...v1.16.1> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.16.1` - `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! ### [`v1.16.0`](https://github.com/autobrr/qui/releases/tag/v1.16.0) [Compare Source](autobrr/qui@v1.15.0...v1.16.0) ##### Changelog ##### Highlights - Automations got a major upgrade: rules can now match across instances, use system time, control AutoTMM, and opt out of notifications per workflow. - Cross-seed is more reliable during state changes. Completion searches now wait for torrents to finish checking or moving, disabled instances are skipped cleanly, and hardlink/reflink save-path handling is more accurate. - Dir Scan works better with real media libraries, with improved partial season-pack handling in link-tree mode, support for downloading missing files when needed, and better progress retention across restarts. - Managing torrents in the unified view is smoother, with more accurate tracker health, quicker instance-level actions, and more stable category and tag editing dialogs. - OIDC and backups both got practical quality-of-life improvements: OIDC now supports PKCE, backup settings can be applied across instances, and backup export handling is safer for tricky torrent layouts. ##### New Features - [`2b92c7b`](autobrr/qui@2b92c7b): feat(auth): add PKCE support to OIDC implementation ([#​1737](autobrr/qui#1737)) ([@​oynqr](https://github.com/oynqr)) - [`ba3d5d9`](autobrr/qui@ba3d5d9): feat(automations): add AutoTMM condition and action ([#​1698](autobrr/qui#1698)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`702e808`](autobrr/qui@702e808): feat(automations): add system time to query builder ([#​1677](autobrr/qui#1677)) ([@​wastaken7](https://github.com/wastaken7)) - [`e6493b3`](autobrr/qui@e6493b3): feat(automations): allow disable of notifications ([#​1652](autobrr/qui#1652)) ([@​heathlarsen](https://github.com/heathlarsen)) - [`565ac2d`](autobrr/qui@565ac2d): feat(automations): cross instance condition ([#​1648](autobrr/qui#1648)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`7e12a02`](autobrr/qui@7e12a02): feat(update): verify self-updates with signed release checksums ([#​1665](autobrr/qui#1665)) ([@​s0up4200](https://github.com/s0up4200)) - [`3778c7b`](autobrr/qui@3778c7b): feat(web): Add action buttons to unified instance. ([#​1637](autobrr/qui#1637)) ([@​drtaru](https://github.com/drtaru)) - [`bf9eaba`](autobrr/qui@bf9eaba): feat(web): Clarify dashboard quick links ([#​1636](autobrr/qui#1636)) ([@​drtaru](https://github.com/drtaru)) - [`b930530`](autobrr/qui@b930530): feat(web): add "Save changes to all instances" button to backup settings ([#​1651](autobrr/qui#1651)) ([@​drtaru](https://github.com/drtaru)) - [`5975c34`](autobrr/qui@5975c34): feat(web): add Discord perk section to license manager ([#​1656](autobrr/qui#1656)) ([@​s0up4200](https://github.com/s0up4200)) - [`d8ad0d6`](autobrr/qui@d8ad0d6): feat(web): unify tab styling and animations ([#​1632](autobrr/qui#1632)) ([@​nuxencs](https://github.com/nuxencs)) ##### Bug Fixes - [`44596b9`](autobrr/qui@44596b9): fix(automations): add AutoTMM to condition validation ([#​1726](autobrr/qui#1726)) ([@​s0up4200](https://github.com/s0up4200)) - [`8f757b2`](autobrr/qui@8f757b2): fix(automations): hardlink signature grouping ([#​1670](autobrr/qui#1670)) ([@​aulterego](https://github.com/aulterego)) - [`d242f0c`](autobrr/qui@d242f0c): fix(automations): include AutoManagement in delete standalone check ([#​1731](autobrr/qui#1731)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`744bdb8`](autobrr/qui@744bdb8): fix(backups): adaptive export throttle ([#​1630](autobrr/qui#1630)) ([@​s0up4200](https://github.com/s0up4200)) - [`d1dbb81`](autobrr/qui@d1dbb81): fix(backups): gate bulk save on resolved instance capabilities ([#​1682](autobrr/qui#1682)) ([@​s0up4200](https://github.com/s0up4200)) - [`2eea961`](autobrr/qui@2eea961): fix(backups): skip live export for hybrid torrents ([#​1669](autobrr/qui#1669)) ([@​s0up4200](https://github.com/s0up4200)) - [`2cac32d`](autobrr/qui@2cac32d): fix(crossseed): skip disabled instances ([#​1635](autobrr/qui#1635)) ([@​s0up4200](https://github.com/s0up4200)) - [`ebbba8e`](autobrr/qui@ebbba8e): fix(crossseed): tone down async cache reuse log ([#​1686](autobrr/qui#1686)) ([@​s0up4200](https://github.com/s0up4200)) - [`fd382b7`](autobrr/qui@fd382b7): fix(dirscan): link plan size tolerance + partial season pack injection in link tree mode ([#​1695](autobrr/qui#1695)) ([@​s0up4200](https://github.com/s0up4200)) - [`5131092`](autobrr/qui@5131092): fix(dirscan): retain recent runs and clarify restart behavior ([#​1564](autobrr/qui#1564)) ([@​s0up4200](https://github.com/s0up4200)) - [`3fbcc7a`](autobrr/qui@3fbcc7a): fix(openapi): document dirscan downloadMissingFiles ([#​1727](autobrr/qui#1727)) ([@​s0up4200](https://github.com/s0up4200)) - [`d16fee2`](autobrr/qui@d16fee2): fix(orphanscan): use content\_path to prevent false positives when Auto TMM changes save\_path ([#​1712](autobrr/qui#1712)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`e74bf02`](autobrr/qui@e74bf02): fix(qbittorrent): avoid tracker health URL false positives ([#​1738](autobrr/qui#1738)) ([@​s0up4200](https://github.com/s0up4200)) - [`632fc54`](autobrr/qui@632fc54): fix(torrents): honor tracker health in unified view ([#​1668](autobrr/qui#1668)) ([@​s0up4200](https://github.com/s0up4200)) - [`76fddc4`](autobrr/qui@76fddc4): fix(torrents): stabilize tag and category dialogs ([#​1638](autobrr/qui#1638)) ([@​s0up4200](https://github.com/s0up4200)) - [`c758b6d`](autobrr/qui@c758b6d): fix(torrents): validate creator output path ([#​1739](autobrr/qui#1739)) ([@​s0up4200](https://github.com/s0up4200)) - [`6c23f0e`](autobrr/qui@6c23f0e): fix(web): cross-seed warning in unified view ([#​1692](autobrr/qui#1692)) ([@​s0up4200](https://github.com/s0up4200)) - [`57822c0`](autobrr/qui@57822c0): fix(web): improve duplicate torrent state and check another field.state.value type in AddTorrentDialog ([#​1679](autobrr/qui#1679)) ([@​keatonhasse](https://github.com/keatonhasse)) - [`246c8f6`](autobrr/qui@246c8f6): fix(web): migrate vite chunk splitting config ([@​s0up4200](https://github.com/s0up4200)) ##### Other Changes - [`263b0bd`](autobrr/qui@263b0bd): build(deps): add cooldown to dependabot config ([#​1691](autobrr/qui#1691)) ([@​s0up4200](https://github.com/s0up4200)) - [`a394157`](autobrr/qui@a394157): chore(deps): bump github.com/go-jose/go-jose/v4 from 4.1.3 to 4.1.4 ([#​1713](autobrr/qui#1713)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`10612a7`](autobrr/qui@10612a7): chore(deps): bump golang.org/x/image from 0.36.0 to 0.38.0 ([#​1685](autobrr/qui#1685)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`16019dd`](autobrr/qui@16019dd): chore(deps): bump pnpm/action-setup from 4 to 5 in the github group ([#​1634](autobrr/qui#1634)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`fbb25fc`](autobrr/qui@fbb25fc): chore(deps): bump the golang group with 11 updates ([#​1693](autobrr/qui#1693)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`cbb9594`](autobrr/qui@cbb9594): chore(deps): bump the golang group with 3 updates ([#​1701](autobrr/qui#1701)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`805ab74`](autobrr/qui@805ab74): chore(deps): bump the npm group in /web with 25 updates ([#​1694](autobrr/qui#1694)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`e3f839c`](autobrr/qui@e3f839c): chore(deps): bump the npm group in /web with 5 updates ([#​1702](autobrr/qui#1702)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`b076ad4`](autobrr/qui@b076ad4): docs(dirscan): clarify re-identification after torrent removal ([#​1720](autobrr/qui#1720)) ([@​s0up4200](https://github.com/s0up4200)) - [`340f343`](autobrr/qui@340f343): docs: add license management page with deactivation guide ([#​1706](autobrr/qui#1706)) ([@​s0up4200](https://github.com/s0up4200)) - [`5d148be`](autobrr/qui@5d148be): docs: fix link in issue triage template ([@​s0up4200](https://github.com/s0up4200)) - [`0b64237`](autobrr/qui@0b64237): docs: update release follow-up docs ([#​1741](autobrr/qui#1741)) ([@​s0up4200](https://github.com/s0up4200)) **Full Changelog**: <autobrr/qui@v1.15.0...v1.16.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.16.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! ### [`v1.15.0`](https://github.com/autobrr/qui/releases/tag/v1.15.0) [Compare Source](autobrr/qui@v1.14.1...v1.15.0) ##### Changelog ##### Breaking change CORS is disabled by default; enable by setting QUI\_\_CORS\_ALLOWED\_ORIGINS with explicit origins (http(s)://host\[:port]). See <https://getqui.com/docs/advanced/sso-proxy-cors> ##### New Features - [`93786a2`](autobrr/qui@93786a2): feat(automations): add configurable processing priority/sorting ([#​1235](autobrr/qui#1235)) ([@​Oscariremma](https://github.com/Oscariremma)) - [`45eaf1f`](autobrr/qui@45eaf1f): feat(database): add postgres and sqlite migration CLI ([#​1530](autobrr/qui#1530)) ([@​s0up4200](https://github.com/s0up4200)) - [`430f5d1`](autobrr/qui@430f5d1): feat(torrents): mediaInfo dialog ([#​1537](autobrr/qui#1537)) ([@​s0up4200](https://github.com/s0up4200)) - [`8eb8903`](autobrr/qui@8eb8903): feat(web): Add persistence to unified instance filter in sidebar ([#​1560](autobrr/qui#1560)) ([@​drtaru](https://github.com/drtaru)) - [`7aadde7`](autobrr/qui@7aadde7): feat(web): add path autocomplete to set location dialog ([#​1432](autobrr/qui#1432)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`077f32c`](autobrr/qui@077f32c): feat: add mediainfo api endpoint ([#​1545](autobrr/qui#1545)) ([@​Audionut](https://github.com/Audionut)) - [`99cf695`](autobrr/qui@99cf695): feat: endpoint to trigger directory scans from external tools ([#​1559](autobrr/qui#1559)) ([@​s0up4200](https://github.com/s0up4200)) - [`8956f9b`](autobrr/qui@8956f9b): feat: unify bulk tag editor ([#​1571](autobrr/qui#1571)) ([@​s0up4200](https://github.com/s0up4200)) ##### Bug Fixes - [`552d617`](autobrr/qui@552d617): fix(api): align add torrent OpenAPI field ([#​1617](autobrr/qui#1617)) ([@​s0up4200](https://github.com/s0up4200)) - [`424f7a0`](autobrr/qui@424f7a0): fix(api): restrict CORS to explicit allowlist ([#​1551](autobrr/qui#1551)) ([@​s0up4200](https://github.com/s0up4200)) - [`38991d8`](autobrr/qui@38991d8): fix(auth): allow loopback health probes ([#​1621](autobrr/qui#1621)) ([@​s0up4200](https://github.com/s0up4200)) - [`4ae88c9`](autobrr/qui@4ae88c9): fix(automations): align include-cross-seeds category apply ([#​1517](autobrr/qui#1517)) ([@​s0up4200](https://github.com/s0up4200)) - [`6a127a8`](autobrr/qui@6a127a8): fix(automations): scope skipWithin to only deleted action ([#​1538](autobrr/qui#1538)) ([@​jabloink](https://github.com/jabloink)) - [`c776189`](autobrr/qui@c776189): fix(crossseed): avoid completion timeout misses on non-Gazelle torrents ([#​1536](autobrr/qui#1536)) ([@​s0up4200](https://github.com/s0up4200)) - [`b1338a7`](autobrr/qui@b1338a7): fix(crossseed): handle missing webhook collection tags ([#​1610](autobrr/qui#1610)) ([@​s0up4200](https://github.com/s0up4200)) - [`eacbb68`](autobrr/qui@eacbb68): fix(crossseed): normalize hdr aliases ([#​1572](autobrr/qui#1572)) ([@​s0up4200](https://github.com/s0up4200)) - [`537ad46`](autobrr/qui@537ad46): fix(crossseed): queue completion searches and retry rate-limit waits ([#​1523](autobrr/qui#1523)) ([@​s0up4200](https://github.com/s0up4200)) - [`4fc550f`](autobrr/qui@4fc550f): fix(crossseed): use autobrr indexer ids for webhooks ([#​1614](autobrr/qui#1614)) ([@​s0up4200](https://github.com/s0up4200)) - [`08029ad`](autobrr/qui@08029ad): fix(crossseed): valid partial matches being rejected ([#​1291](autobrr/qui#1291)) ([@​rybertm](https://github.com/rybertm)) - [`77eedd9`](autobrr/qui@77eedd9): fix(database): avoid postgres temp-table statement caching ([#​1581](autobrr/qui#1581)) ([@​s0up4200](https://github.com/s0up4200)) - [`25daa17`](autobrr/qui@25daa17): fix(dirscan): honor canceled queued webhook runs ([#​1612](autobrr/qui#1612)) ([@​s0up4200](https://github.com/s0up4200)) - [`56995f1`](autobrr/qui@56995f1): fix(dirscan): queue webhook scans and tighten age filtering ([#​1603](autobrr/qui#1603)) ([@​s0up4200](https://github.com/s0up4200)) - [`444d07b`](autobrr/qui@444d07b): fix(dirscan): select concrete hardlink base dir ([#​1606](autobrr/qui#1606)) ([@​s0up4200](https://github.com/s0up4200)) - [`c35bea0`](autobrr/qui@c35bea0): fix(instances): improve settings dialog scrolling ([#​1569](autobrr/qui#1569)) ([@​nuxencs](https://github.com/nuxencs)) - [`dc501a0`](autobrr/qui@dc501a0): fix(proxy): reauth qbit passthrough requests ([#​1582](autobrr/qui#1582)) ([@​s0up4200](https://github.com/s0up4200)) - [`7950d1d`](autobrr/qui@7950d1d): fix(proxy): search endpoint handling ([#​1524](autobrr/qui#1524)) ([@​Audionut](https://github.com/Audionut)) - [`1076eea`](autobrr/qui@1076eea): fix(qbit): prune empty managed dirs after delete\_with\_files ([#​1604](autobrr/qui#1604)) ([@​s0up4200](https://github.com/s0up4200)) - [`5a3114b`](autobrr/qui@5a3114b): fix(qbittorrent): stop reboot torrent\_completed spam ([#​1515](autobrr/qui#1515)) ([@​s0up4200](https://github.com/s0up4200)) - [`1d02e6c`](autobrr/qui@1d02e6c): fix(settings): contain settings tab scrolling ([#​1567](autobrr/qui#1567)) ([@​nuxencs](https://github.com/nuxencs)) - [`f5d69f3`](autobrr/qui@f5d69f3): fix(settings): smoother gradient ([#​1570](autobrr/qui#1570)) ([@​nuxencs](https://github.com/nuxencs)) - [`1c0c3bc`](autobrr/qui@1c0c3bc): fix(torrents): copy MediaInfo summary without brackets ([#​1540](autobrr/qui#1540)) ([@​s0up4200](https://github.com/s0up4200)) - [`3ec913a`](autobrr/qui@3ec913a): fix(web): auto-append slash on path autocomplete selection ([#​1431](autobrr/qui#1431)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`aa2f3da`](autobrr/qui@aa2f3da): fix(web): check field.state.value type in AddTorrentDialog ([#​1613](autobrr/qui#1613)) ([@​s0up4200](https://github.com/s0up4200)) - [`1abfc5e`](autobrr/qui@1abfc5e): fix(web): handle SSO proxy redirect to /index.html ([#​1600](autobrr/qui#1600)) ([@​s0up4200](https://github.com/s0up4200)) - [`1991f90`](autobrr/qui@1991f90): fix(web): warn before enabling reannounce ([#​1583](autobrr/qui#1583)) ([@​s0up4200](https://github.com/s0up4200)) ##### Other Changes - [`4069492`](autobrr/qui@4069492): chore(deps): bump the github group with 3 updates ([#​1535](autobrr/qui#1535)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`a02e9e8`](autobrr/qui@a02e9e8): chore(deps): bump the github group with 7 updates ([#​1558](autobrr/qui#1558)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`8713667`](autobrr/qui@8713667): chore(deps): bump the golang group with 15 updates ([#​1543](autobrr/qui#1543)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`420607e`](autobrr/qui@420607e): chore(go,ci): adopt go fix, bump to 1.26, and speed up PR checks ([#​1480](autobrr/qui#1480)) ([@​s0up4200](https://github.com/s0up4200)) - [`0d0df45`](autobrr/qui@0d0df45): docs: add password reset section to CLI commands ([#​1598](autobrr/qui#1598)) ([@​s0up4200](https://github.com/s0up4200)) - [`9ef56a2`](autobrr/qui@9ef56a2): refactor(makefile): windows support ([#​1546](autobrr/qui#1546)) ([@​Audionut](https://github.com/Audionut)) - [`7899cc8`](autobrr/qui@7899cc8): refactor(reflinking): add windows ReFS filesystem support ([#​1576](autobrr/qui#1576)) ([@​Audionut](https://github.com/Audionut)) - [`51d34ab`](autobrr/qui@51d34ab): refactor(releases): share hdr normalization helpers ([#​1586](autobrr/qui#1586)) ([@​s0up4200](https://github.com/s0up4200)) - [`c7f4e3d`](autobrr/qui@c7f4e3d): refactor(web): tighten unified scope navigation ([#​1618](autobrr/qui#1618)) ([@​s0up4200](https://github.com/s0up4200)) - [`4b05177`](autobrr/qui@4b05177): test(handlers): cover tag baseline field requests ([@​s0up4200](https://github.com/s0up4200)) **Full Changelog**: <autobrr/qui@v1.14.1...v1.15.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.15.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**: (in timezone Europe/London) - 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 these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTUuMSIsInVwZGF0ZWRJblZlciI6IjQzLjE5NS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL21pbm9yIl19--> Reviewed-on: https://forgejo.hayden.moe/hayden/phoebe/pulls/12
Description:
Normalize HDR aliases in cross-seed parsing and matching so HDR10+, HDR10P, and separated HDR10 PLUS forms compare consistently across /check, /apply, and shared candidate discovery. Tighten raw-name HDR enrichment to avoid false positives from scene groups like -DV, and add regressions for the End of Watch repro plus HDR alias edge cases.
ref: #1277
Summary by CodeRabbit
New Features
Tests