feat: enhance download manager with folder notes and improved worker settings

This commit is contained in:
Nixevol
2026-09-27 15:30:48 +08:00
parent fdb1f73968
commit 68d27a5caf
5 changed files with 184 additions and 35 deletions
+75 -10
View File
@@ -147,7 +147,7 @@ def load_episodes(token: str, device: DeviceProfile | None, vid: int) -> list[di
return merged
def expand_variant(master_url: str) -> tuple[str, str, list[str]]:
def expand_variant(master_url: str) -> tuple[str, str, list[dict]]:
master_text = http.read_text(master_url)
variant_rel = next(
(line.strip() for line in master_text.splitlines() if line.strip() and not line.startswith("#")),
@@ -155,16 +155,81 @@ def expand_variant(master_url: str) -> tuple[str, str, list[str]]:
)
if not variant_rel:
raise RuntimeError("播放列表没有视频地址")
variant_url = urljoin(master_url, variant_rel)
media_text = http.read_text(variant_url)
segments = [
urljoin(variant_url, line.strip())
for line in media_text.splitlines()
if line.strip() and not line.startswith("#")
]
if not segments:
if _looks_like_segment(variant_rel):
variant_url = master_url
media_text = master_text
else:
variant_url = urljoin(master_url, variant_rel)
media_text = http.read_text(variant_url)
localized, items = localize_media(media_text, variant_url)
if not items:
raise RuntimeError("播放列表没有分片")
return master_text, media_text, segments
return master_text, localized, items
def localize_media(text: str, base: str) -> tuple[str, list[dict]]:
urls = _resource_urls(text, base)
names: list[str] = []
items: list[dict] = []
used: set[str] = set()
known: dict[str, str] = {}
for index, url in enumerate(urls, start=1):
name = known.get(url)
if name is None:
name = _resource_name(url, index, used)
known[url] = name
items.append({"name": name, "url": url})
names.append(name)
return _apply_local_names(text, names), items
def _resource_urls(text: str, base: str) -> list[str]:
urls = []
for line in text.splitlines():
stripped = line.strip()
if not stripped:
continue
if stripped.startswith("#"):
urls.extend(urljoin(base, match) for match in re.findall(r'URI="([^"]*)"', stripped))
continue
urls.append(urljoin(base, stripped))
return urls
def _resource_name(url: str, index: int, used: set[str]) -> str:
raw = Path(url.split("?", 1)[0].rstrip("/")).name
raw = re.sub(r'[<>:"/\\|?*\x00-\x1f]', "_", raw).strip(" .") or f"part-{index}.ts"
candidate = raw
sequence = index
while candidate in used:
suffix = Path(raw).suffix
stem = Path(raw).stem
candidate = f"{stem}-{sequence}{suffix}"
sequence += 1
used.add(candidate)
return candidate
def _apply_local_names(text: str, names: list[str]) -> str:
index = 0
def take() -> str:
nonlocal index
name = names[index] if index < len(names) else ""
index += 1
return name
lines = []
for line in text.splitlines():
stripped = line.strip()
if not stripped:
lines.append(line)
continue
if stripped.startswith("#"):
lines.append(re.sub(r'URI="([^"]*)"', lambda _match: f'URI="{take()}"', line))
continue
lines.append(take() or stripped)
return "\n".join(lines) + "\n"
def episode_src(token: str, device: DeviceProfile | None, vid: int, cid: int) -> str: