"""Build the small extension archive; the Windows helper is distributed separately.""" import binascii import json import struct import zlib import zipfile from pathlib import Path ROOT = Path(__file__).resolve().parent.parent def png_chunk(kind, data): return struct.pack(">I", len(data)) + kind + data + struct.pack(">I", binascii.crc32(kind + data) & 0xffffffff) def icon(size): rows = bytearray() for y in range(size): rows.append(0) for x in range(size): u, v = (x + 0.5) / size, (y + 0.5) / size dx, dy = max(0.18 - u, 0, u - 0.82), max(0.18 - v, 0, v - 0.82) alpha = 255 if dx * dx + dy * dy < 0.18 ** 2 else 0 color = (int(74 - 47 * v), int(205 - 52 * v), int(243 - 32 * v), alpha) stem = 0.44 < u < 0.56 and 0.22 < v < 0.60 arrow = 0.46 < v < 0.71 and abs(u - 0.5) < (0.71 - v) * 1.15 tray = (0.26 < u < 0.74 and 0.76 < v < 0.82) or (0.26 < u < 0.32 or 0.68 < u < 0.74) and 0.66 < v < 0.82 if stem or arrow or tray: color = (8, 39, 57, alpha) rows.extend(color) return b"\x89PNG\r\n\x1a\n" + png_chunk(b"IHDR", struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0)) + png_chunk(b"IDAT", zlib.compress(bytes(rows))) + png_chunk(b"IEND", b"") def main(): icons = ROOT / "extension" / "icons" icons.mkdir(exist_ok=True) for size in (16, 32, 48, 128): (icons / f"{size}.png").write_bytes(icon(size)) (ROOT / "dist").mkdir(exist_ok=True) version = json.loads((ROOT / "extension" / "manifest.json").read_text(encoding="utf-8"))["version"] destination = ROOT / "dist" / f"YouTubeDL-{version}.zip" with zipfile.ZipFile(destination, "w", compression=zipfile.ZIP_DEFLATED) as archive: for path in (ROOT / "extension").rglob("*"): if path.is_file() and path.suffix.lower() != ".exe" and "__pycache__" not in path.parts: archive.write(path, str(path.relative_to(ROOT))) for name in ("INSTALL.md", "LICENSE", "PRIVACY.md", "THIRD_PARTY.md"): path = ROOT / name if path.is_file(): archive.write(path, name) print(destination) if __name__ == "__main__": main()