Update to v0.6.8

This commit is contained in:
2026-09-25 17:46:48 +02:00
parent 7def1a4dc5
commit fc1fc283e6
2 changed files with 132 additions and 22 deletions
+57 -3
View File
@@ -1,7 +1,7 @@
// ==UserScript==
// @name UNIT3D Mod Queue Helper — DarkPeers
// @namespace https://gitea.computerliebe.org/Procuria/dp-modq-helper
// @version 0.6.7
// @version 0.6.8
// @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
@@ -4245,6 +4245,56 @@ ${e.violations.map(o=>" • "+o).join(`
Please review the [url=${this.RULES_URL}]Naming Guide[/url].`}return b}};
/* ========================================================================
* DARKPEERS SECTION: rows for dpk results and the title validator,
* plus the per-check toggles from Settings.
* ======================================================================== */
const DP_SECTION = [
["dpTitle", "Title Template"],
["nogroup", "NOGROUP"],
["bannedFilename", "Banned Group in Files"],
["extraneousFiles", "Extraneous Files"],
["categoryTypeMismatch", "Category / Type"],
["singleFileFolder", "Single File in Folder"],
["missingEpisodes", "Missing Episodes"],
["unknownLanguage", "Unknown Language"],
["suspicion", "Suspicion Heuristics"],
];
/** Replace every check switched off in Settings with an N/A result of the same shape. */
function applyCheckToggles(results, checks) {
if (!checks) return results;
for (const [key, on] of Object.entries(checks)) {
if (on === false && results[key]) {
results[key] = { status: "na", message: "Disabled in settings", details: null, checks: [], violations: [] };
}
}
return results;
}
/** DarkPeers rows to render: present, not N/A. */
function dpSectionRows(results) {
return DP_SECTION.filter(([k]) => results[k] && results[k].status !== "na");
}
/* Corrective message: include fails and warnings from the DarkPeers rows */
(function() {
const _collect = G.collectIssues, _beautify = G.beautify;
G.collectIssues = function(e) {
const n = _collect.call(this, e);
for (const [key, label] of (e._dpRows || [])) {
const v = e[key];
if (v && (v.status === "fail" || v.status === "warn")) n.push({ id: "dp_" + key, status: v.status, raw: v.message, label });
}
return n;
};
G.beautify = function(e) {
if (e.id && e.id.startsWith("dp_")) return { text: e.raw, rules: [] };
return _beautify.call(this, e);
};
})();
/* ========================================================================
* UI — Panel rendering, injection, and event handling
* Ported from the original U object.
@@ -4286,7 +4336,7 @@ const U={getStatusIcon(e){switch(e){case"pass":return'<i class="fas fa-check-cir
<strong>Banned Release Group Detected</strong>
<span>${e.message}</span>
</div>
</div>`:""},groupHeading(e){return`<div class="mh-group">${e}</div>`},sectionGroup(e,n,t){const s=t.map(f=>f.status).filter(f=>f!=="na"),a=s.filter(f=>f==="pass").length,o=s.length,c=a===o&&o>0,r=this.worstStatus(t.map(f=>f.status));return`
</div>`:""},groupHeading(e){return`<div class="mh-group">${e}</div>`},sectionGroup(e,n,t){const s=t.map(f=>f.status).filter(f=>f!=="na"&&f!=="advisory"),a=s.filter(f=>f==="pass").length,o=s.length,c=a===o&&o>0,r=this.worstStatus(t.map(f=>f.status));return`
<details class="mh-section" ${c?"":"open"}>
<summary class="mh-section__summary">
<span class="mh-chip mh-chip--${r==="na"?"pass":r}">${a}/${o} passed</span>
@@ -4294,7 +4344,7 @@ const U={getStatusIcon(e){switch(e){case"pass":return'<i class="fas fa-check-cir
<i class="fas fa-chevron-down mh-section__chevron"></i>
</summary>
<div class="mh-section__body">${n}</div>
</details>`},createPanel(e){const n=document.createElement("section");n.className="panelV2 mh-panel",n.id="mod-helper-panel";const s=[e.tmdbMatch,e.seasonEpisode,e.namingGuide,e.elementOrder,e.folderStructure,e.mediaInfo,e.audioTags,e.subtitleRequirement,e.screenshots,e.bannedGroup,e.encodeCompliance,e.upscaleDetection,e.containerFormat,e.packUniformity,e.resolutionTypeMatch].map(i=>i.status),a=this.worstStatus(s),o=s.filter(i=>i!=="na"),c=o.filter(i=>i==="pass").length,r=o.filter(i=>i==="warn").length,d=o.filter(i=>i==="fail").length,f=o.length;let A=[];if(d&&A.push(`<span class="mh-chip mh-chip--fail">${d} failed</span>`),r&&A.push(`<span class="mh-chip mh-chip--warn">${r} warning${r>1?"s":""}</span>`),A.push(`<span class="mh-chip mh-chip--pass">${c}/${f} passed</span>`),e.bannedGroup.tieredInfo){const i=e.bannedGroup.tieredInfo.join(", ");A.push(`<span class="mh-chip mh-chip--pass" title="${i}">TRaSH Tiered Group</span>`)}let T="";T+=this.buildBannedGroupAlert(e.bannedGroup);const b=[e.tmdbMatch,e.seasonEpisode,e.namingGuide,e.elementOrder,e.bannedGroup,e.screenshots];let u="";u+=this.buildSimple("tmdb","TMDB Title Match",e.tmdbMatch),e.seasonEpisode.status!=="na"&&(u+=this.buildSimple("season","Season / Episode Format",e.seasonEpisode));const D=e.bannedGroup.tieredInfo?`<span class="mh-badge mh-badge--info" title="${e.bannedGroup.tieredInfo.join(", ")}">TRaSH Tiered Group</span>`:"";u+=this.buildSimple("group","Release Group",e.bannedGroup,{alert:e.bannedGroup.alert,extraBadge:D}),u+=this.buildSimple("screenshots","Screenshots",e.screenshots),u+=this.buildElementOrder(e.elementOrder),u+=this.buildNamingGuide(e.namingGuide),T+=this.sectionGroup("Content & Naming",u,b);const x=[e.folderStructure,e.containerFormat,e.mediaInfo,e.audioTags,e.subtitleRequirement,e.encodeCompliance,e.packUniformity,e.upscaleDetection,e.resolutionTypeMatch];let p="";e.folderStructure.status!=="na"&&(p+=this.buildSimple("folder","Folder Structure",e.folderStructure)),e.containerFormat.status!=="na"&&(p+=this.buildSimple("container","Container Format",e.containerFormat)),p+=this.buildSimple("mediainfo","MediaInfo",e.mediaInfo),e.subtitleRequirement.status!=="na"&&(p+=this.buildSimple("subs","Subtitle Requirement",e.subtitleRequirement)),p+=this.buildSimple("upscale","Upscale Detection",e.upscaleDetection),p+=this.buildSimple("restype","Resolution Type",e.resolutionTypeMatch),p+=this.buildMultiCheck("audio","Audio Compliance",e.audioTags),e.encodeCompliance.status!=="na"&&(p+=this.buildMultiCheck("encode","Encode Compliance",e.encodeCompliance)),e.packUniformity.status!=="na"&&(p+=this.buildMultiCheck("pack","Pack Uniformity",e.packUniformity)),T+=this.sectionGroup("Technical",p,x);const y=G.collectIssues(e),C=G.buildMessage(y);let h="";if(C){const i=C.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");h=`
</details>`},createPanel(e){const n=document.createElement("section");n.className="panelV2 mh-panel",n.id="mod-helper-panel";const s=[e.tmdbMatch,e.seasonEpisode,e.namingGuide,e.elementOrder,e.folderStructure,e.mediaInfo,e.audioTags,e.subtitleRequirement,e.screenshots,e.bannedGroup,e.encodeCompliance,e.upscaleDetection,e.containerFormat,e.packUniformity,e.resolutionTypeMatch,...(e._dpRows||[]).map(([k])=>e[k])].map(i=>i.status),a=this.worstStatus(s),o=s.filter(i=>i!=="na"&&i!=="advisory"),c=o.filter(i=>i==="pass").length,r=o.filter(i=>i==="warn").length,d=o.filter(i=>i==="fail").length,f=o.length;let A=[];if(d&&A.push(`<span class="mh-chip mh-chip--fail">${d} failed</span>`),r&&A.push(`<span class="mh-chip mh-chip--warn">${r} warning${r>1?"s":""}</span>`),A.push(`<span class="mh-chip mh-chip--pass">${c}/${f} passed</span>`),e.bannedGroup.tieredInfo){const i=e.bannedGroup.tieredInfo.join(", ");A.push(`<span class="mh-chip mh-chip--pass" title="${i}">TRaSH Tiered Group</span>`)}let T="";T+=this.buildBannedGroupAlert(e.bannedGroup);const b=[e.tmdbMatch,e.seasonEpisode,e.namingGuide,e.elementOrder,e.bannedGroup,e.screenshots];let u="";u+=this.buildSimple("tmdb","TMDB Title Match",e.tmdbMatch),e.seasonEpisode.status!=="na"&&(u+=this.buildSimple("season","Season / Episode Format",e.seasonEpisode));const D=e.bannedGroup.tieredInfo?`<span class="mh-badge mh-badge--info" title="${e.bannedGroup.tieredInfo.join(", ")}">TRaSH Tiered Group</span>`:"";u+=this.buildSimple("group","Release Group",e.bannedGroup,{alert:e.bannedGroup.alert,extraBadge:D}),u+=this.buildSimple("screenshots","Screenshots",e.screenshots),u+=this.buildElementOrder(e.elementOrder),u+=this.buildNamingGuide(e.namingGuide),T+=this.sectionGroup("Content & Naming",u,b);const x=[e.folderStructure,e.containerFormat,e.mediaInfo,e.audioTags,e.subtitleRequirement,e.encodeCompliance,e.packUniformity,e.upscaleDetection,e.resolutionTypeMatch];let p="";e.folderStructure.status!=="na"&&(p+=this.buildSimple("folder","Folder Structure",e.folderStructure)),e.containerFormat.status!=="na"&&(p+=this.buildSimple("container","Container Format",e.containerFormat)),p+=this.buildSimple("mediainfo","MediaInfo",e.mediaInfo),e.subtitleRequirement.status!=="na"&&(p+=this.buildSimple("subs","Subtitle Requirement",e.subtitleRequirement)),p+=this.buildSimple("upscale","Upscale Detection",e.upscaleDetection),p+=this.buildSimple("restype","Resolution Type",e.resolutionTypeMatch),p+=this.buildMultiCheck("audio","Audio Compliance",e.audioTags),e.encodeCompliance.status!=="na"&&(p+=this.buildMultiCheck("encode","Encode Compliance",e.encodeCompliance)),e.packUniformity.status!=="na"&&(p+=this.buildMultiCheck("pack","Pack Uniformity",e.packUniformity)),T+=this.sectionGroup("Technical",p,x);if(e._dpRows&&e._dpRows.length){const dr=e._dpRows;let dh="";for(const [dk,dl] of dr){const v=e[dk];dh+=Array.isArray(v.checks)&&v.checks.length>1?this.buildMultiCheck("dp-"+dk,dl,v):this.buildSimple("dp-"+dk,dl,v)}T+=this.sectionGroup("DarkPeers Rules",dh,dr.map(([k])=>e[k]))}const y=G.collectIssues(e),C=G.buildMessage(y);let h="";if(C){const i=C.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");h=`
<div class="mh-message-block">
<div class="mh-message-block__header">
<i class="fas fa-clipboard-list mh-message-block__icon"></i>
@@ -5080,6 +5130,10 @@ function main() {
results.dpTitle = TitleValidator.validate(data.torrentName, data.category, data.type, data.mediaInfoText);
}
// Settings toggles, then the DarkPeers rows for the panel and the message
applyCheckToggles(results, Settings.load().checks);
results._dpRows = dpSectionRows(results);
// Inject CSS via GM_addStyle
if (typeof GM_addStyle === "function") {
GM_addStyle(Z);