stuff
This commit is contained in:
@@ -789,7 +789,7 @@ class ComicInfoBuilder:
|
|||||||
if favs is not None: rows.append(f"<tr><td {_TD}>Favorites</td><td>{favs:,}</td></tr>")
|
if favs is not None: rows.append(f"<tr><td {_TD}>Favorites</td><td>{favs:,}</td></tr>")
|
||||||
|
|
||||||
if rows:
|
if rows:
|
||||||
link = f'<a href="{url}">MyAnimeList</a>' if url else "MyAnimeList"
|
link = f'<a href="{url}" target="_blank">MyAnimeList</a>' if url else "MyAnimeList"
|
||||||
parts.append(f"<p>{link} stats as of {as_of}:</p><table>{''.join(rows)}</table>")
|
parts.append(f"<p>{link} stats as of {as_of}:</p><table>{''.join(rows)}</table>")
|
||||||
|
|
||||||
# 2. Description — Markdown → HTML (middle) -----------------------
|
# 2. Description — Markdown → HTML (middle) -----------------------
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ def _build_character_description(details: dict) -> str:
|
|||||||
url = details.get("url") or ""
|
url = details.get("url") or ""
|
||||||
favorites = details.get("favorites")
|
favorites = details.get("favorites")
|
||||||
if url and favorites is not None:
|
if url and favorites is not None:
|
||||||
parts.append(f'<p><a href="{url}">Favorites: {favorites:,}</a></p>')
|
parts.append(f'<p><a href="{url}" target="_blank">Favorites: {favorites:,}</a></p>')
|
||||||
about = (details.get("about") or "").strip()
|
about = (details.get("about") or "").strip()
|
||||||
if about:
|
if about:
|
||||||
parts.append(_plain_to_html(about))
|
parts.append(_plain_to_html(about))
|
||||||
@@ -469,7 +469,7 @@ def _build_person_description(details: dict) -> str:
|
|||||||
f'<td><a href="{website}">{website}</a></td></tr>'
|
f'<td><a href="{website}">{website}</a></td></tr>'
|
||||||
)
|
)
|
||||||
if favorites is not None:
|
if favorites is not None:
|
||||||
fav_cell = (f'<a href="{url}">{favorites:,}</a>' if url
|
fav_cell = (f'<a href="{url}" target="_blank">{favorites:,}</a>' if url
|
||||||
else f"{favorites:,}")
|
else f"{favorites:,}")
|
||||||
rows.append(
|
rows.append(
|
||||||
f"<tr><td {_TD}>Member Favorites</td><td>{fav_cell}</td></tr>")
|
f"<tr><td {_TD}>Member Favorites</td><td>{fav_cell}</td></tr>")
|
||||||
|
|||||||
+22
-3
@@ -69,12 +69,30 @@ _SOURCE_LABEL_RE = re.compile(
|
|||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Characters that Windows (and SMB shares) forbid in path components.
|
||||||
|
_WIN_ILLEGAL_RE = re.compile(r'[\\/*?"<>|]')
|
||||||
|
|
||||||
|
|
||||||
def _natural_key(name: str) -> list:
|
def _natural_key(name: str) -> list:
|
||||||
return [int(p) if p.isdigit() else p.lower()
|
return [int(p) if p.isdigit() else p.lower()
|
||||||
for p in re.split(r"(\d+)", name)]
|
for p in re.split(r"(\d+)", name)]
|
||||||
|
|
||||||
|
|
||||||
|
def _sanitize_dirname(name: str) -> str:
|
||||||
|
"""
|
||||||
|
Makes a string safe to use as a Windows (or SMB) directory name.
|
||||||
|
|
||||||
|
Rules applied:
|
||||||
|
- ": " or ":" surrounded by optional spaces -> " - "
|
||||||
|
("Call of the Night: Paradise Arc" -> "Call of the Night - Paradise Arc")
|
||||||
|
- Remaining Windows-illegal chars (\\ / * ? " < > |) are stripped.
|
||||||
|
- Leading/trailing dots and spaces are removed (Windows restriction).
|
||||||
|
"""
|
||||||
|
name = re.sub(r"\s*:\s*", " - ", name)
|
||||||
|
name = _WIN_ILLEGAL_RE.sub("", name)
|
||||||
|
return name.strip(". ")
|
||||||
|
|
||||||
|
|
||||||
_SUWAYOMI_WANTED = {"Title", "Series", "Number", "Summary",
|
_SUWAYOMI_WANTED = {"Title", "Series", "Number", "Summary",
|
||||||
"Writer", "Penciller", "Genre", "Web",
|
"Writer", "Penciller", "Genre", "Web",
|
||||||
"Year", "Month", "Day"}
|
"Year", "Month", "Day"}
|
||||||
@@ -326,8 +344,9 @@ class SuwayomiMover:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print(f" [warn] metadata fetch failed: {exc}")
|
print(f" [warn] metadata fetch failed: {exc}")
|
||||||
|
|
||||||
# Destination folder uses the MangaBaka canonical title.
|
# Destination folder uses the MangaBaka canonical title, sanitized for
|
||||||
dest_series = self._dst / mangabaka_title
|
# Windows / SMB paths (no colons, illegal chars, leading/trailing dots).
|
||||||
|
dest_series = self._dst / _sanitize_dirname(mangabaka_title)
|
||||||
dest_series.mkdir(parents=True, exist_ok=True)
|
dest_series.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
chapter_results: list[dict] = []
|
chapter_results: list[dict] = []
|
||||||
@@ -403,7 +422,7 @@ if __name__ == "__main__":
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Process a single series
|
# Process a single series
|
||||||
result = mover.process_series("Yofukashi no Uta")
|
result = mover.process_series("Yofukashi no Uta_ Rakuen-hen")
|
||||||
ok = sum(1 for c in result["chapters"] if c["ok"])
|
ok = sum(1 for c in result["chapters"] if c["ok"])
|
||||||
failed = sum(1 for c in result["chapters"] if not c["ok"])
|
failed = sum(1 for c in result["chapters"] if not c["ok"])
|
||||||
print(f"\nDone: {ok} ok, {failed} failed")
|
print(f"\nDone: {ok} ok, {failed} failed")
|
||||||
|
|||||||
Reference in New Issue
Block a user