zapret2-youtube-discord/scripts/validate_repository.py
loop-uh 7d5aec1bc7
All checks were successful
Проверка восстановленного репозитория / validate (push) Successful in 4s
Выпуск Zapret2 для Windows / release (push) Successful in 7s
Восстановить полный Zapret2 и перенести выпуск в Forgejo
2026-08-07 17:10:02 +03:00

157 lines
5.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Проверяет целостность восстановленного репозитория без запуска Windows-кода."""
from __future__ import annotations
import hashlib
import re
import struct
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REQUIRED_PATHS = (
"README.md",
"docs/assets/zapret2-console.png",
"zapret-console.bat",
"service.bat",
"exe/winws2.exe",
"exe/WinDivert.dll",
"exe/WinDivert32.sys",
"exe/WinDivert64.sys",
"exe/cygwin1.dll",
"presets/Default v5.txt",
"lists/discord-updates.txt",
"lists/googlevideo.txt",
"lists/tankix.txt",
"lua/zapret-custom.lua",
)
FORBIDDEN_TRACKED_PATHS = (
".github/workflows",
"lists/service_config.txt",
"utils/current_preset.txt",
"utils/preset-active.txt",
)
OWN_GITHUB_REFERENCES = re.compile(
rb"(?:github\.com/(?:youtubediscord|zapretdiscordyoutube|loop-uh)(?:/|\b)"
rb"|gist\.github\.com/loop-uh(?:/|\b)"
rb"|github\.com/user-attachments(?:/|\b))",
re.IGNORECASE,
)
REFERENCE_PATTERN = re.compile(
r"(?:@|=)((?:bin|lua|lists|windivert\.filter)/[^\s\"';,]+)",
re.IGNORECASE,
)
TEXT_SUFFIXES = {
".bat",
".cmd",
".lua",
".md",
".ps1",
".py",
".txt",
".vbs",
".yaml",
".yml",
}
def png_size(path: Path) -> tuple[int, int]:
data = path.read_bytes()
if data[:8] != b"\x89PNG\r\n\x1a\n" or data[12:16] != b"IHDR":
raise ValueError("файл не является корректным PNG")
return struct.unpack(">II", data[16:24])
def iter_repository_files():
for path in ROOT.rglob("*"):
if not path.is_file():
continue
relative = path.relative_to(ROOT)
if relative.parts[0] in {".git", "dist"} or "__pycache__" in relative.parts:
continue
yield path
def main() -> int:
errors: list[str] = []
for relative in REQUIRED_PATHS:
if not (ROOT / relative).is_file():
errors.append(f"нет обязательного файла: {relative}")
for relative in FORBIDDEN_TRACKED_PATHS:
if (ROOT / relative).exists():
errors.append(f"в репозиторий попало локальное или GitHub-состояние: {relative}")
image = ROOT / "docs/assets/zapret2-console.png"
if image.is_file():
try:
if png_size(image) != (980, 519):
errors.append("локальная картинка README имеет неожиданный размер")
except ValueError as exc:
errors.append(f"локальная картинка README повреждена: {exc}")
engine = ROOT / "exe/winws2.exe"
if engine.is_file():
data = engine.read_bytes()
digest = hashlib.sha256(data).hexdigest()
if data[:2] != b"MZ":
errors.append("exe/winws2.exe не является Windows PE-файлом")
if b"v1.0.3" not in data or b"b78b52c4cd7f843da3ff0848a3430afbd401bdf2" not in data:
errors.append(
"exe/winws2.exe не совпадает с восстановленным zapret2 v1.0.3 "
f"(sha256={digest})"
)
for path in iter_repository_files():
data = path.read_bytes()
match = OWN_GITHUB_REFERENCES.search(data)
if match:
relative = path.relative_to(ROOT)
errors.append(f"осталась ссылка собственного проекта на GitHub: {relative}")
referenced_from = list((ROOT / "presets").glob("*.txt"))
referenced_from.extend((ROOT / "utils").glob("*.txt"))
for source in referenced_from:
text = source.read_text(encoding="utf-8-sig", errors="replace")
for reference in REFERENCE_PATTERN.findall(text):
if "$" in reference or "%" in reference:
continue
if not (ROOT / reference).is_file():
errors.append(
f"{source.relative_to(ROOT)} ссылается на отсутствующий файл: {reference}"
)
text_files = [path for path in iter_repository_files() if path.suffix.lower() in TEXT_SUFFIXES]
if not text_files:
errors.append("не найдены текстовые файлы проекта")
for path in text_files:
for line_number, line in enumerate(path.read_bytes().splitlines(), start=1):
if line.endswith((b" ", b"\t")):
errors.append(
f"хвостовой пробел: {path.relative_to(ROOT)}:{line_number}"
)
if errors:
print("Проверка не пройдена:")
for error in sorted(set(errors)):
print(f"- {error}")
return 1
preset_count = len(list((ROOT / "presets").glob("*.txt")))
print("Проверка пройдена.")
print(f"Пресетов: {preset_count}")
print(f"Файлов в репозитории: {sum(1 for _ in iter_repository_files())}")
print(f"SHA256 winws2.exe: {hashlib.sha256(engine.read_bytes()).hexdigest()}")
return 0
if __name__ == "__main__":
sys.exit(main())