s
This commit is contained in:
91
d2ypp2/tools/render_tampermonkey_provisioning.py
Normal file
91
d2ypp2/tools/render_tampermonkey_provisioning.py
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
DEFAULT_SCRIPT = ROOT / "services" / "neko" / "provisioning" / "youtube-studio-auto-dismiss.user.js"
|
||||
DEFAULT_OUTPUT = ROOT / "services" / "neko" / "provisioning" / "tampermonkey-provisioning.json"
|
||||
GREASYFORK_URL = "https://greasyfork.org/scripts/557378-youtube-studio-auto-dismiss/code/YouTube%20Studio%20Auto%20Dismiss.user.js"
|
||||
|
||||
|
||||
def tm_sha256(text: str) -> str:
|
||||
return hashlib.sha256(text.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def tm_hash(value: Any, seen: list[int] | None = None) -> str:
|
||||
if seen is None:
|
||||
seen = []
|
||||
if value is None:
|
||||
return tm_sha256("object:null")
|
||||
if isinstance(value, dict):
|
||||
ident = id(value)
|
||||
if ident in seen:
|
||||
raise ValueError("Found circular structure")
|
||||
seen.append(ident)
|
||||
try:
|
||||
parts = [tm_hash(value[key], seen) for key in sorted(value)]
|
||||
finally:
|
||||
seen.pop()
|
||||
return tm_sha256("".join(parts))
|
||||
if isinstance(value, list):
|
||||
ident = id(value)
|
||||
if ident in seen:
|
||||
raise ValueError("Found circular structure")
|
||||
seen.append(ident)
|
||||
try:
|
||||
parts = [tm_hash(item, seen) for item in value]
|
||||
finally:
|
||||
seen.pop()
|
||||
return tm_sha256("".join(parts))
|
||||
if isinstance(value, bool):
|
||||
return tm_sha256(f"boolean:{str(value).lower()}")
|
||||
if isinstance(value, (int, float)) and not isinstance(value, bool):
|
||||
return tm_sha256(f"number:{value}")
|
||||
if isinstance(value, str):
|
||||
return tm_sha256(f"string:{value}")
|
||||
raise TypeError(f"Unsupported provisioning value: {type(value)!r}")
|
||||
|
||||
|
||||
def build_payload(script_text: str) -> dict[str, Any]:
|
||||
return {
|
||||
"version": "1",
|
||||
"scripts": [
|
||||
{
|
||||
"name": "YouTube Studio Auto Dismiss",
|
||||
"file_url": GREASYFORK_URL,
|
||||
"source": script_text,
|
||||
"enabled": True,
|
||||
"position": 1,
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"runtime_content_mode": "content",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Render Tampermonkey provisioning JSON and hash.")
|
||||
parser.add_argument("--script", type=Path, default=DEFAULT_SCRIPT)
|
||||
parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
|
||||
parser.add_argument("--write", action="store_true", help="Write the rendered JSON to --output.")
|
||||
args = parser.parse_args()
|
||||
|
||||
script_text = args.script.read_text(encoding="utf-8").strip() + "\n"
|
||||
payload = build_payload(script_text)
|
||||
rendered = json.dumps(payload, ensure_ascii=False, indent=2) + "\n"
|
||||
if args.write:
|
||||
args.output.write_text(rendered, encoding="utf-8")
|
||||
print(rendered, end="")
|
||||
print(f"hash=1:{tm_hash(payload)}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user