Hosts and sponsors without a counter name no upload
"(www.Thunder-News.org) >XXX< <Sponsored by Secretusenet> - "ps-itb10b.r00"" has no counter to bound it, so a poster's uploads were one subject release (1,135 files). Without a counter the remainder drops www hosts and "Sponsored by X"; what's left names the release or the stem does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cdc1cdc0cc
commit
6d301fc668
3 files changed
+47
-2
No files matched your search
+25
-1
@@ -657,10 +657,17 @@ pub fn release_identity(poster: &str, subject: &str, name: &str) -> Release {
|
||||
let named = replace(&SIZE_AFTER_COUNTER, &named, "$1", true);
|
||||
// A per-file hex id in brackets ("… [1f1793f68d5321] [newzNZB] [01/22]").
|
||||
let named = replace(&HEX_ID, &named, " ", true);
|
||||
let remainder = subject_remainder(&named);
|
||||
// Counted without the file name: "shyla-shy-09-0195.jpg hardcore …" is no "9 of 195".
|
||||
let total = counter_total(&named);
|
||||
let file_total = total.as_ref().and_then(|t| t.parse::<i64>().ok());
|
||||
// Without a counter a host and a sponsor name no upload ("(www.Thunder-News.org) >XXX< <Sponsored by Secretusenet>").
|
||||
let remainder = subject_remainder(&named);
|
||||
let remainder = if total.is_none() {
|
||||
let bare = replace(&BOILERPLATE, &remainder, " ", true);
|
||||
js::trim(&js::collapse_spaces(&bare)).to_string()
|
||||
} else {
|
||||
remainder
|
||||
};
|
||||
// A document or comic is a release of its own.
|
||||
if test(&DOCUMENT, name) {
|
||||
let shown = replace(&DOCUMENT, &stem, "", false);
|
||||
@@ -749,6 +756,9 @@ static HEX_ID: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)\[[0-9a-f]{8,}\]"));
|
||||
static VIDEO: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)\.(mkv|mp4|avi|m4v|ts|wmv|mov)$"));
|
||||
static EPISODE: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)^(.+?)[ ._-]+S([0-9]{1,2})E[0-9]{1,3}"));
|
||||
static SIZE_AFTER_COUNTER: LazyLock<Regex> = LazyLock::new(|| re(r"(\[[0-9]+/[0-9]+\])SP*-SP*\[[0-9]+\]"));
|
||||
/// A host and a sponsor in a subject's remainder (BOILERPLATE in lib/release/identity.ts).
|
||||
static BOILERPLATE: LazyLock<Regex> =
|
||||
LazyLock::new(|| re(r"(?i)\(?\bwww(?: [A-Za-z0-9]+)*? (?:org|com|net|info|nl|de|eu|to|biz|us)\b\)?|<?\bsponsored by [A-Za-z0-9]+>?"));
|
||||
static HASHED: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)^[0-9a-f]{8,}(?:_[0-9a-f]{6,}){2,}(?:-[0-9a-z]+)?$"));
|
||||
static SCENE_TRACK: LazyLock<Regex> = LazyLock::new(|| re(r"^[0-9]{1,3}[-_ .]+(.+?)(?:_-_| - |-)"));
|
||||
static VOLUME_NUMBER: LazyLock<Regex> = LazyLock::new(|| re(r"^(.*[^0-9. ])[. ]([0-9]{1,5})\.?$"));
|
||||
@@ -1369,6 +1379,20 @@ mod image_set_tests {
|
||||
assert_eq!(wl("01 Time Machine.mp3").key, wl("02 Jimmy Dean Loved Marilyn.mp3").key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_and_sponsor_without_counter() {
|
||||
let tn = |tag: &str, n: &str| release_identity("p", &format!(r#"(www.Thunder-News.org) >{tag}< <Sponsored by Secretusenet> - "{n}" yEnc"#), n);
|
||||
assert_eq!(tn("XXX", "ps-itb10b.r00").key, tn("XXX", "ps-itb10b.par2").key);
|
||||
assert_ne!(tn("XXX", "ps-itb10b.r00").key, tn("XXX", "swe6-legsa.r00").key);
|
||||
assert_eq!(tn("XXX", "ps-itb10b.r00").source, "stem");
|
||||
let named = tn("For.Rent.XXX.720p.Bluray.x264-DPXXXHD", "dp-for.rent.720p.x264.r00");
|
||||
assert_eq!(named.source, "subject");
|
||||
assert_eq!(named.key, tn("For.Rent.XXX.720p.Bluray.x264-DPXXXHD", "dp-for.rent.720p.x264.par2").key);
|
||||
assert_eq!(named.name, ">For Rent XXX 720p Bluray x264 DPXXXHD<");
|
||||
let counted = release_identity("p", r#"(www.Thunder-News.org) >XXX< [01/20] - "ps-itb10b.r00" yEnc"#, "ps-itb10b.r00");
|
||||
assert_eq!(counted.source, "subject");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hashed_stems_volume_numbers_and_scene_tracks() {
|
||||
let u4e = |n: &str| release_identity("p", &format!(r#"Seit 1753 Tagen - usenet4ever.info - "{n}" yEnc"#), n);
|
||||
|
||||
@@ -131,6 +131,8 @@ function hash(...parts: (string | number | undefined)[]) {
|
||||
const DATE_LED = /^\d{1,2}[-._]\d{1,2}[-._](?:19|20)\d{2}(?!\d)/
|
||||
const VIDEO = /\.(mkv|mp4|avi|m4v|ts|wmv|mov)$/i
|
||||
const EPISODE = /^(.+?)[ ._-]+S(\d{1,2})E\d{1,3}/i
|
||||
/** A host and a sponsor in a subject's remainder (its dots and dashes spaces): "(www Thunder News org)", "<Sponsored by Secretusenet>". */
|
||||
const BOILERPLATE = /\(?\bwww(?: [A-Za-z0-9]+)*? (?:org|com|net|info|nl|de|eu|to|biz|us)\b\)?|<?\bsponsored by [A-Za-z0-9]+>?/gi
|
||||
const HASHED = /^[0-9a-f]{8,}(?:_[0-9a-f]{6,}){2,}(?:-[0-9a-z]+)?$/i
|
||||
const SCENE_TRACK = /^\d{1,3}[-_ .]+(.+?)(?:_-_| - |-)/
|
||||
const VOLUME_NUMBER = /^(.*[^\d. ])[. ](\d{1,5})\.?$/
|
||||
@@ -307,10 +309,15 @@ export function releaseIdentity(input: ReleaseInput): ReleaseIdentity | null {
|
||||
.replace(/(\[\d+\/\d+\])\s*-\s*\[\d+\]/g, '$1')
|
||||
// A per-file hex id in brackets ("[PRiVATE] Rosewood.S02E08… [1f1793f68d5321] [newzNZB] [01/22]": 32,101 single files).
|
||||
.replace(/\[[0-9a-f]{8,}\]/gi, ' ')
|
||||
const remainder = subjectRemainder(named)
|
||||
// Counted without the file name, as quoted names are: "shyla-shy-09-0195.jpg hardcore …" is no "9 of 195"
|
||||
// (each of 866 images was a release of its own; LOG.md 2026-10-12 (5)).
|
||||
const fileTotal = counterTotal(named)
|
||||
// Without a counter a host and a sponsor name no upload ("(www.Thunder-News.org) >XXX< <Sponsored by Secretusenet> -
|
||||
// "ps-itb10b.r00"": with no total to bound them, a poster's uploads were one release of 1,135 files; LOG.md 2026-10-12 (23)).
|
||||
const remainder =
|
||||
fileTotal === undefined
|
||||
? subjectRemainder(named).replace(BOILERPLATE, ' ').replace(/ {2,}/g, ' ').trim()
|
||||
: subjectRemainder(named)
|
||||
// A document or comic is a release of its own (collections post hundreds under one subject).
|
||||
if (DOCUMENT.test(input.name)) return { key: hash('stem', poster, stem), name: stem.replace(DOCUMENT, '') || stem, fileTotal, source: 'stem' }
|
||||
const image = IMAGE.test(input.name)
|
||||
|
||||
@@ -339,6 +339,20 @@ test.group('release / par2 names', () => {
|
||||
assert.equal(track('01', '01-2bm_mq-real_rap_(intro).mp3').name, '2bm_mq')
|
||||
})
|
||||
|
||||
test('a host and a sponsor without a counter name no upload', ({ assert }) => {
|
||||
const id = (subject: string, name: string) => releaseIdentity({ poster: 'p', subject, name, weak: false })!
|
||||
const tn = (tag: string, n: string) => id(`(www.Thunder-News.org) >${tag}< <Sponsored by Secretusenet> - "${n}" yEnc`, n)
|
||||
assert.equal(tn('XXX', 'ps-itb10b.r00').key, tn('XXX', 'ps-itb10b.par2').key)
|
||||
assert.notEqual(tn('XXX', 'ps-itb10b.r00').key, tn('XXX', 'swe6-legsa.r00').key)
|
||||
assert.equal(tn('XXX', 'ps-itb10b.r00').source, 'stem')
|
||||
const named = tn('For.Rent.XXX.720p.Bluray.x264-DPXXXHD', 'dp-for.rent.720p.x264.r00')
|
||||
assert.equal(named.source, 'subject')
|
||||
assert.equal(named.key, tn('For.Rent.XXX.720p.Bluray.x264-DPXXXHD', 'dp-for.rent.720p.x264.par2').key)
|
||||
assert.equal(named.name, '>For Rent XXX 720p Bluray x264 DPXXXHD<')
|
||||
// With a counter the subject stays as it was: the total bounds it.
|
||||
assert.equal(id('(www.Thunder-News.org) >XXX< [01/20] - "ps-itb10b.r00" yEnc', 'ps-itb10b.r00').source, 'subject')
|
||||
})
|
||||
|
||||
test('an image without words around it is keyed by its set', ({ assert }) => {
|
||||
const id = (name: string, counter: string) => releaseIdentity({ poster: 'p', subject: `##[ "${name}" (${counter})`, name, weak: false })!
|
||||
assert.equal(id('diana-040-001.jpg', '01/68').key, id('diana-040-002.jpg', '02/68').key)
|
||||
|
||||
Reference in new issue
Block a user