""" youtube.ini 结构化读写:多行 key=(注释行为备用密钥)、其它键值对保留。 """ from __future__ import annotations import re from typing import Any def parse_youtube_ini(content: str) -> dict[str, Any]: if not (content or "").strip(): return { "keys": [""], "activeIndex": 0, "options": {}, "header": "", } m = re.search(r"(?im)^\s*\[youtube\]\s*$", content) if not m: return { "keys": [""], "activeIndex": 0, "options": {}, "header": content, } header = content[: m.start()] body = content[m.end() :] keys: list[str] = [] key_commented: list[bool] = [] options: dict[str, str] = {} active_index = 0 found_active = False for raw in body.splitlines(): stripped = raw.strip() if not stripped: continue if stripped.startswith("[") and stripped.endswith("]"): break km = re.match(r"^;\s*(key|stream_key)\s*=\s*(.+)$", stripped, re.I) if km: val = km.group(2).strip().split("#")[0].strip() keys.append(val) key_commented.append(True) continue km2 = re.match(r"^(key|stream_key)\s*=\s*(.+)$", stripped, re.I) if km2: val = km2.group(2).strip().split("#")[0].strip() keys.append(val) key_commented.append(False) if not found_active: active_index = len(keys) - 1 found_active = True continue if stripped.startswith(";"): continue om = re.match(r"^(\w+)\s*=\s*(.+)$", stripped) if om: k = om.group(1).strip() v = om.group(2).strip().split("#")[0].strip() if k.lower() not in ("key", "stream_key"): options[k] = v if not keys: keys = [""] active_index = 0 elif not found_active: active_index = 0 return { "keys": keys, "activeIndex": max(0, min(active_index, len(keys) - 1)), "options": options, "header": header, } def serialize_youtube_ini( keys: list[str], active_index: int, options: dict[str, str], header: str, ) -> str: lines: list[str] = [] h = (header or "").rstrip() if h: lines.append(h.rstrip("\n")) if not lines[-1].endswith("\n"): lines[-1] = lines[-1] + "\n" lines.append("[youtube]") if not keys: keys = [""] ai = max(0, min(int(active_index), len(keys) - 1)) for i, k in enumerate(keys): val = (k or "").strip() if i == ai: lines.append(f"key = {val}") else: lines.append(f"; key = {val}") for opt_k, opt_v in options.items(): if opt_k.lower() in ("key", "stream_key"): continue lines.append(f"{opt_k} = {opt_v}") lines.append("") return "\n".join(lines)