From 7def1a4dc560d1ec0e64acbf5b5b4acf640a05be Mon Sep 17 00:00:00 2001 From: Procuria Date: Fri, 10 Apr 2026 23:56:40 +0200 Subject: [PATCH] =?UTF-8?q?release:=20v0.6.7=20=E2=80=94=20diacritics,=20a?= =?UTF-8?q?postrophe,=20and=20AKA=20normalization=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 93 ++++++++++------------------------- modq-helper-darkpeers.user.js | 46 +++++++++++++++-- 2 files changed, 68 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91894a8..82320e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,79 +4,40 @@ All notable changes to the DarkPeers Mod Queue Helper will be documented in this The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [0.6.7] - 2026-04-10 + +### Fixed + +- **Diacritics in rename detection** — accented characters (É, â, û, ñ, ö, etc.) no longer cause false "possible rename" warnings. Titles like `Belle Époque` vs filename `Belle Epoque` are now correctly recognized as equivalent. Uses Unicode NFD normalization in the Jaccard word comparison. +- **Apostrophes in title comparison** — `Serpent's Path` now matches `Serpents Path`. All apostrophes (straight and curly) are stripped during word normalization. +- **Foreign-language filenames with AKA** — files using a foreign primary title with an AKA English title after the year (e.g. `La.voie.du.serpent.2024.AKA.Serpents.Path...`) now correctly match the English upload title. AKA is extracted from the full release name, not just the title portion. + ## [0.6.6] - 2026-04-10 ### Fixed -- **AKA title false rename warnings** — titles with "AKA Original-Title" (e.g. `Squid Game AKA Ojing-eo geim`) no longer trigger false "possible rename" warnings when the folder uses the short name. The AKA portion is stripped before title comparison. -- **Search button first-click** — rewrote integration rendering to use stable container divs, fixing the issue where the Search button only worked on the second click. -- **Search button idle message** — changed to "Idle — use the Search button above to check" for clarity. +- **Banned groups** — replaced Luminarr list (87 groups) with DarkPeers authoritative list (60 groups + EVO/HDT conditional exceptions). False positives for Kira, 4K4U, d3g, iVy eliminated. +- **Encode resolution** — removed fake "720p minimum" rule. DarkPeers allows all resolutions (360p–4320p). +- **Opus/FLAC** — removed fake mono/stereo restriction. No channel limits on DarkPeers. +- **Dual-Audio** — corrected to DarkPeers definition: any 2 languages = Dual-Audio, 3+ = MULTi. +- **Release group** — missing group tag is now a warning, not an error. +- **Atmos detection** — checks only the default audio track, not all tracks. +- **HDR validation** — no longer gated behind 2160p/4320p. Catches "HDR10" at any resolution. +- **SRRDB search** — scene-name normalization and fallback keyword search when exact match fails. +- **Prowlarr rename detection** — ignores release group differences in self-consistency checks. AKA titles no longer cause false rename warnings. +- **Corrective messages** — replaced Luminarr §section references with "Naming Guide" link. Fixed BBCode URL syntax. Removed `img.luminarr.me`. +- **Prowlarr match summaries** — dynamically lists only fields that actually match instead of hardcoded claims. ### Added -- **Auto-search toggle** — new "Auto-search on page load" checkbox in Prowlarr settings. When unchecked, SRRDB/Prowlarr only search when you click the Search button. No more automatic queries while browsing. - -### Changed - -- **Search button styling** — moved to left-aligned position below section header with subtle blue accent for better visibility. - -## [0.6.5] - 2026-04-10 - -### Fixed - -- **AKA title false rename warnings** — titles with "AKA Original-Title" (e.g. `Squid Game AKA Ojing-eo geim`) no longer trigger false "possible rename" warnings when the folder uses the short name (`Squid.Game`). The AKA portion is stripped before title comparison. - -### Added - -- **Auto-search toggle** — new "Auto-search on page load" checkbox in Prowlarr settings. When unchecked, SRRDB/Prowlarr only search when you click the Search button. No more automatic queries while browsing. - -## [0.6.4] - 2026-04-09 - -### Fixed - -- **Corrective message BBCode** — corrected Naming Guide link to proper `[url=…]…[/url]` BBCode syntax per bbcode.org spec. - -## [0.6.3] - 2026-04-09 - -### Fixed - -- **Corrective message BBCode** — incorrect fix (used `[url]…[/url]` without `=` attribute). - -## [0.6.2] - 2026-04-09 - -### Fixed - -- **Corrective message BBCode** — incorrect fix for the URL tag syntax (used `[url=…]` instead of `[url]…[/url]`). - -## [0.6.1] - 2026-04-09 - -### Added - -- **Prowlarr timeout setting** — search timeout is now configurable via Tampermonkey settings (default: 15000ms). Accessible in the Integrations fieldset alongside Prowlarr URL and API Key. - -## [0.6.0] - 2026-04-09 - -### Fixed - -- **Banned groups** — replaced Luminarr list (87 groups) with DarkPeers authoritative list (60 groups + EVO/HDT conditional exceptions). False positives for Kira, 4K4U, d3g, iVy eliminated. EVO allowed for WEB-DL, HDT allowed for REMUX. -- **Encode resolution** — removed fake "720p minimum" rule. DarkPeers allows all resolutions including 360p, 480i, 480p, 576i, 576p. -- **Opus/FLAC** — removed fake mono/stereo restriction. DarkPeers has no channel limit on Opus or FLAC. -- **Dual-Audio** — corrected to DarkPeers definition: any 2 languages = Dual-Audio, 3+ = MULTi. Removed incorrect English-origin restriction. -- **Release group** — missing group tag is now a warning, not an error. DarkPeers allows uploads without a group tag. -- **Atmos detection** — now checks only the default audio track, not all tracks. Eliminates false positives from Atmos on commentary/secondary tracks. -- **HDR validation** — no longer gated behind 2160p/4320p. Validates HDR tags whenever they appear in the title, catching "HDR10" (should be "HDR") at any resolution. -- **SRRDB search** — added scene-name normalization (strip colons/apostrophes, & → and) and fallback keyword search when exact match fails. -- **Prowlarr rename detection** — self-consistency checks now ignore release group differences between torrent title and folder/file names, reducing false rename warnings. -- **Corrective messages** — replaced Luminarr §section references with plain "Naming Guide" link to DarkPeers wiki. Removed `img.luminarr.me` from image hosts. - -### Added - -- **Ignored indexers** — new setting to exclude specific indexers from Prowlarr results (e.g. TorrentLeech). Comma-separated, case-insensitive. -- **Manual re-search** — "Re-search" button in External Integrations section header. Prevents unwanted auto-searches after page edits. Click to re-query SRRDB and Prowlarr on demand. -- **Expanded indexer view** — all matching indexers shown (no longer capped at 3). First 3 inline, rest in collapsible "+N more" section. -- **Torrent age** — relative age shown next to each alternative indexer ("3d ago", "2mo ago") when Prowlarr provides publish dates. -- **Dynamic match summaries** — Prowlarr summary now lists only fields that actually match instead of hardcoded "title, year, resolution, codecs all consistent". Mismatched fields are excluded from the claim. -- **Alternative hyperlinks** — "Also found on" indexers are now clickable links to the source tracker page when URL is available. +- **Auto-search toggle** — "Auto-search on page load" setting. When off, SRRDB/Prowlarr only run when you click Search. No more automatic queries while browsing. +- **Ignored indexers** — exclude specific indexers from Prowlarr results via settings. +- **Search / Re-search button** — on-demand integration search in the External Integrations section. +- **Expanded indexer view** — all matching indexers shown (no cap). Collapsible "+N more" for overflow. +- **Torrent age** — relative age shown next to each alternative indexer. +- **Alternative hyperlinks** — "Also found on" indexers are clickable links. +- **Prowlarr timeout setting** — configurable search timeout (default: 15000ms). +- **MCP read-only test harness** — safety-enforced browser verification framework for live-site testing. ## [0.5.0] - 2026-04-06 diff --git a/modq-helper-darkpeers.user.js b/modq-helper-darkpeers.user.js index 89a5408..2ac424f 100644 --- a/modq-helper-darkpeers.user.js +++ b/modq-helper-darkpeers.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name UNIT3D Mod Queue Helper — DarkPeers // @namespace https://gitea.computerliebe.org/Procuria/dp-modq-helper -// @version 0.6.6 +// @version 0.6.7 // @description Quality-gate checks for DarkPeers — extended moderation rules, title validation, SRRDB & Prowlarr integrations // @author TQG Contributors // @updateURL https://gitea.computerliebe.org/Procuria/dp-modq-helper/raw/branch/main/modq-helper-darkpeers.user.js @@ -3854,6 +3854,16 @@ const RenameDetector = { return name.replace(/\s+AKA\s+.*/i, "").trim(); }, + /** + * _stripDiacritics — Normalize accented characters to ASCII equivalents. + * É→E, â→a, û→u, ñ→n, ö→o, etc. Uses Unicode NFD decomposition + * followed by combining-mark removal. + */ + _stripDiacritics(str) { + if (!str) return str; + return str.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); + }, + /** Codec aliases for fuzzy matching */ _codecAliases: { "x264": "h.264", "h.264": "h.264", "avc": "h.264", @@ -3908,9 +3918,17 @@ const RenameDetector = { } const titleName = raw.slice(0, titleEnd).replace(/[.\-_]/g, " ").replace(/\s+/g, " ").trim(); + // Extract AKA title from the structural portion (after first token, e.g. after year). + // Only matches AKA that appears AFTER titleEnd — AKA in the title portion is + // handled by _stripAka on titleName instead. + const postTitle = normalized.slice(titleEnd); + const akaMatch = postTitle.match(/\bAKA\s+(.+?)(?=[\s.]+\d{3,4}p\b|[\s.]+(?:Blu-?ray|BluRay|WEB[-.]?DL|WEB[-.]?Rip|HDTV|Remux|REMUX|BDRip|BRRip|DVDRip)\b)/i); + const akaTitle = akaMatch ? akaMatch[1].replace(/[.\-_]/g, " ").replace(/\s+/g, " ").trim() : null; + return { raw: name, titleName, + akaTitle, elements, positions, group: fieldOf("group"), @@ -3929,8 +3947,9 @@ const RenameDetector = { */ _jaccardWords(a, b) { if (!a || !b) return 0; - const wordsA = new Set(a.toLowerCase().split(/\s+/).filter(Boolean)); - const wordsB = new Set(b.toLowerCase().split(/\s+/).filter(Boolean)); + const norm = s => this._stripDiacritics(s).toLowerCase().replace(/['\u2019]/g, ""); + const wordsA = new Set(norm(a).split(/\s+/).filter(Boolean)); + const wordsB = new Set(norm(b).split(/\s+/).filter(Boolean)); if (wordsA.size === 0 && wordsB.size === 0) return 1; if (wordsA.size === 0 || wordsB.size === 0) return 0; let intersection = 0; @@ -3963,7 +3982,15 @@ const RenameDetector = { const fieldScores = {}; // titleName — Jaccard similarity (strip AKA for fair comparison) - const titleScore = this._jaccardWords(this._stripAka(uploadTokens.titleName), this._stripAka(resultTokens.titleName)); + let titleScore = this._jaccardWords(this._stripAka(uploadTokens.titleName), this._stripAka(resultTokens.titleName)); + // AKA fallback: try mid-name AKA titles if primary comparison is weak + if (titleScore < 0.5) { + const akaTitleScores = [ + resultTokens.akaTitle ? this._jaccardWords(this._stripAka(uploadTokens.titleName), resultTokens.akaTitle) : 0, + uploadTokens.akaTitle ? this._jaccardWords(uploadTokens.akaTitle, this._stripAka(resultTokens.titleName)) : 0, + ]; + titleScore = Math.max(titleScore, ...akaTitleScores); + } fieldScores.titleName = titleScore; weightedSum += titleScore * weights.titleName; totalWeight += weights.titleName; @@ -4107,7 +4134,16 @@ const RenameDetector = { // Compare title name words — strip AKA portion (folders never include it) const titleA = this._stripAka(tokensA.titleName); const titleB = this._stripAka(tokensB.titleName); - const titleSim = this._jaccardWords(titleA, titleB); + let titleSim = this._jaccardWords(titleA, titleB); + // AKA fallback: one side may use the foreign title while the other has the + // English title in a mid-name AKA portion (e.g. "La.voie.du.serpent.2024.AKA.Serpents.Path...") + if (titleSim < 0.5) { + const akaSims = [ + tokensB.akaTitle ? this._jaccardWords(titleA, tokensB.akaTitle) : 0, + tokensA.akaTitle ? this._jaccardWords(tokensA.akaTitle, titleB) : 0, + ]; + titleSim = Math.max(titleSim, ...akaSims); + } if (titleSim < 0.5) return false; // Compare structural fields — must match if both present