Initial commit
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"""Build canonical filenames: ``Title (Region) (tags) (Serial).iso``.
|
||||
|
||||
Revision (``(v1.03)``), disc (``(Disc 1)``) and edition tags are preserved;
|
||||
language tags (``(En,Fr,De)``) are dropped; leading articles are moved back in
|
||||
front (``Sims 2, The`` -> ``The Sims 2``).
|
||||
"""
|
||||
import re
|
||||
|
||||
_ILLEGAL = re.compile(r'[<>:"/\\|?*\x00-\x1f]')
|
||||
_TAG_RE = re.compile(r"\s*\(([^()]*)\)\s*$")
|
||||
_ARTICLE_RE = re.compile(r"^(.+),\s*(The|A|An)(?:\s+-\s+(.+))?$", re.IGNORECASE)
|
||||
|
||||
_LANG_CODES = {
|
||||
"en", "fr", "de", "es", "it", "nl", "pt", "sv", "no", "da", "fi",
|
||||
"ja", "ko", "zh", "pl", "ru", "el", "tr", "cs", "hu", "hi", "ar", "th",
|
||||
}
|
||||
|
||||
|
||||
def _is_language_tag(inner):
|
||||
parts = [p.strip().lower() for p in inner.split(",")]
|
||||
return bool(parts) and all(p in _LANG_CODES for p in parts)
|
||||
|
||||
|
||||
def _split_tags(name):
|
||||
"""Split trailing parenthetical tags; keep non-language tags, drop languages."""
|
||||
title = name
|
||||
kept = []
|
||||
while True:
|
||||
m = _TAG_RE.search(title)
|
||||
if not m:
|
||||
break
|
||||
inner = m.group(1).strip()
|
||||
if _is_language_tag(inner):
|
||||
title = title[: m.start()]
|
||||
else:
|
||||
kept.insert(0, f"({inner})")
|
||||
title = title[: m.start()]
|
||||
return title.strip(), kept
|
||||
|
||||
|
||||
def region_from_name(name):
|
||||
"""Extract the region from a release name (first non-language tag).
|
||||
|
||||
Used when a DAT leaves the region field empty and embeds it in the name
|
||||
(e.g. ``Oceans 11 (Japan, Europe)``).
|
||||
"""
|
||||
_, kept = _split_tags(str(name))
|
||||
if not kept:
|
||||
return ""
|
||||
inner = kept[0][1:-1].strip()
|
||||
return inner
|
||||
|
||||
|
||||
def _reorder_article(title):
|
||||
m = _ARTICLE_RE.match(title)
|
||||
if m:
|
||||
prefix, article, suffix = m.group(1), m.group(2), m.group(3)
|
||||
result = f"{article} {prefix}"
|
||||
if suffix:
|
||||
result += f" - {suffix}"
|
||||
return result
|
||||
return title
|
||||
|
||||
|
||||
def canonical_name(release, serial):
|
||||
name = release["name"]
|
||||
region = release.get("region")
|
||||
if region:
|
||||
for r in [x.strip() for x in region.split(",") if x.strip()]:
|
||||
name = re.sub(rf"\s*\(\s*{re.escape(r)}\s*\)", "", name, flags=re.IGNORECASE)
|
||||
title, tags = _split_tags(name)
|
||||
title = _reorder_article(title)
|
||||
parts = [title]
|
||||
if region and region != "World":
|
||||
parts.append(f"({region})")
|
||||
parts.extend(tags)
|
||||
if serial:
|
||||
parts.append(f"({serial})")
|
||||
name = _ILLEGAL.sub(" ", " ".join(parts)).strip()
|
||||
name = re.sub(r"\s+", " ", name)
|
||||
return f"{name}.iso"
|
||||
Reference in New Issue
Block a user