A quoted name that runs on into a title; .xNNN/.zNNN volumes
"lois 1258 Billy Joel - Extremes.part01.rar lois 1258 Billy Joel - Extremes ",
"GrooveCoverage.part26.rarGrooveCoveragebestof", "Goga Sekulic.part134.rar -
Goga Sekulic - …": the stem kept the title, and each part was a release of its
own (lois, CPP, DieViper, Maveri, tigra: ~2,400 files). runOn cuts the name
after its archive extension when a space, a dash or the name's own start
follows. And three-digit .x/.z volumes ("Reply 987986177631730.x004"),
not .x264/.x265.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1c8da1dd12
commit
0c5ede99dd
4 files changed
+89
-12
No files matched your search
+23
-2
@@ -51,7 +51,8 @@ export function fileStem(name: string): string {
|
||||
// Old-style rar volumes after .r99 ("BD_NoTHing018.s41", "….s00", ".t91", ".v81"): only as the file's own extension, in
|
||||
// lower case, so a season ("show.s01.rar", "Show.S01") stays. Split zip volumes (".z18"), and .xNN but not the builds
|
||||
// ".x32", ".x64", ".x86" ("Licence 700790900887990.z18", "….x31"; "….v1.0.142.x64" stays).
|
||||
let stem = name.trim().replace(/\.(?:[s-vz]\d{2}|x(?!32$|64$|86$)\d{2})$/, '')
|
||||
// Also three digits ("Reply 987986177631730.x004"), but not ".x264", ".x265".
|
||||
let stem = name.trim().replace(/\.(?:[s-v]\d{2}|z\d{2,3}|x(?!(?:32|64|86|264|265)$)\d{2,3})$/, '')
|
||||
let changed = true
|
||||
while (changed) {
|
||||
changed = false
|
||||
@@ -291,6 +292,26 @@ export function randomPoster(from: string): boolean {
|
||||
return looksRandom((at === -1 ? address : address.slice(0, at)).replace(/[-_.]/g, ''))
|
||||
}
|
||||
|
||||
/** An archive's or par2's extension, where a name that runs on into a title is cut (runOn). */
|
||||
const RUN_ON = /\.(?:part\d+\.rar|vol\d+[+-]\d+\.par2|par2|rar|r\d{2,3}|7z(?:\.\d{3})?|zip|nzb|nfo|sfv)/gi
|
||||
|
||||
/**
|
||||
* A quoted name that runs on past its extension into a title ("lois 1258 Billy Joel - Extremes.part01.rar lois 1258 Billy
|
||||
* Joel - Extremes ", "GrooveCoverage.part26.rarGrooveCoveragebestof", "Goga Sekulic.part134.rar - Goga Sekulic - …": each
|
||||
* part a release of its own): the name up to that extension, when a space or a dash follows it, or the name's own start.
|
||||
*/
|
||||
export function runOn(name: string): string {
|
||||
const head = name.slice(0, 4).toLowerCase()
|
||||
const ascii = /^[\x00-\x7f]{4}$/.test(head)
|
||||
for (const m of name.matchAll(RUN_ON)) {
|
||||
const end = m.index + m[0].length
|
||||
const rest = name.slice(end)
|
||||
if (rest.length === 0) return name
|
||||
if (/^\s|^\s*-/.test(rest) || (ascii && rest.slice(0, 4).toLowerCase() === head)) return name.slice(0, end)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
/** The subject without a number after the file's unquoted name at its end (" - 28": a size in kB). */
|
||||
export function sizeAfterName(subject: string, name: string): string {
|
||||
const end = subject.trimEnd()
|
||||
@@ -305,7 +326,7 @@ export function releaseIdentity(input: ReleaseInput): ReleaseIdentity | null {
|
||||
const counter = /\[(\d+)\/(\d+)\]/.exec(input.subject)
|
||||
// The post rule's key takes the [i/M] total (as when the catalog started); the release's file total any counter's.
|
||||
const postTotal = counter && !brokenTotal(counter[1], counter[2]) ? Number.parseInt(counter[2], 10) : undefined
|
||||
const stem = fileStem(input.name)
|
||||
const stem = fileStem(runOn(input.name))
|
||||
|
||||
if (input.weak) {
|
||||
// Obfuscating posters randomise the poster per article; a real filename
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Grouping of files into releases (downloads), independent of AdonisJS.
|
||||
*/
|
||||
export { releaseIdentity, par2ReleaseIdentity, par2ReleaseName, rarReleaseIdentity, isGenericName, fileStem, sizeAfterName, subjectRemainder, namesRelease, isPostToken, type ReleaseIdentity, type ReleaseInput } from './identity.js'
|
||||
export { releaseIdentity, par2ReleaseIdentity, par2ReleaseName, rarReleaseIdentity, isGenericName, fileStem, sizeAfterName, runOn, subjectRemainder, namesRelease, isPostToken, type ReleaseIdentity, type ReleaseInput } from './identity.js'
|
||||
export { looksRandom } from './random.js'
|
||||
Reference in new issue
Block a user