chatgpt2api / utils /pow.py
tx1538's picture
Upload 179 files
9d7ddb9 verified
Raw
History Blame
6.63 kB
import hashlib
import json
import random
import re
import time
from datetime import datetime, timedelta, timezone
from html.parser import HTMLParser
from typing import Any, Sequence
import pybase64
DEFAULT_POW_SCRIPT = "https://chatgpt.com/backend-api/sentinel/sdk.js"
from utils.helper import new_uuid
CORES = [8, 16, 24, 32]
DOCUMENT_KEYS = ["_reactListeningo743lnnpvdg", "location"]
class ScriptSrcParser(HTMLParser):
def __init__(self) -> None:
super().__init__()
self.script_sources: list[str] = []
self.data_build = ""
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
if tag != "script":
return
attrs_dict = dict(attrs)
src = attrs_dict.get("src")
if not src:
return
self.script_sources.append(src)
match = re.search(r"c/[^/]*/_", src)
if match:
self.data_build = match.group(0)
def parse_pow_resources(html_content: str) -> tuple[list[str], str]:
parser = ScriptSrcParser()
parser.feed(html_content)
script_sources = parser.script_sources or [DEFAULT_POW_SCRIPT]
data_build = parser.data_build
if not data_build:
match = re.search(r'<html[^>]*data-build="([^"]*)"', html_content)
if match:
data_build = match.group(1)
return script_sources, data_build
def _legacy_parse_time() -> str:
now = datetime.now(timezone(timedelta(hours=-5)))
return now.strftime("%a %b %d %Y %H:%M:%S") + " GMT-0500 (Eastern Standard Time)"
def build_pow_config(
user_agent: str,
script_sources: Sequence[str] | None = None,
data_build: str = "",
) -> list[Any]:
navigator_key = random.choice([
"registerProtocolHandler−function registerProtocolHandler() { [native code] }",
"storage−[object StorageManager]",
"locks−[object LockManager]",
"appCodeName−Mozilla",
"permissions−[object Permissions]",
"share−function share() { [native code] }",
"webdriver−false",
"managed−[object NavigatorManagedData]",
"canShare−function canShare() { [native code] }",
"vendor−Google Inc.",
"mediaDevices−[object MediaDevices]",
"vibrate−function vibrate() { [native code] }",
"storageBuckets−[object StorageBucketManager]",
"mediaCapabilities−[object MediaCapabilities]",
"cookieEnabled−true",
"virtualKeyboard−[object VirtualKeyboard]",
"product−Gecko",
"presentation−[object Presentation]",
"onLine−true",
"mimeTypes−[object MimeTypeArray]",
"credentials−[object CredentialsContainer]",
"serviceWorker−[object ServiceWorkerContainer]",
"keyboard−[object Keyboard]",
"gpu−[object GPU]",
"doNotTrack",
"serial−[object Serial]",
"pdfViewerEnabled−true",
"language−zh-CN",
"geolocation−[object Geolocation]",
"userAgentData−[object NavigatorUAData]",
"getUserMedia−function getUserMedia() { [native code] }",
"sendBeacon−function sendBeacon() { [native code] }",
"hardwareConcurrency−32",
"windowControlsOverlay−[object WindowControlsOverlay]",
])
window_key = random.choice([
"0",
"window",
"self",
"document",
"name",
"location",
"customElements",
"history",
"navigation",
"innerWidth",
"innerHeight",
"scrollX",
"scrollY",
"visualViewport",
"screenX",
"screenY",
"outerWidth",
"outerHeight",
"devicePixelRatio",
"screen",
"chrome",
"navigator",
"onresize",
"performance",
"crypto",
"indexedDB",
"sessionStorage",
"localStorage",
"scheduler",
"alert",
"atob",
"btoa",
"fetch",
"matchMedia",
"postMessage",
"queueMicrotask",
"requestAnimationFrame",
"setInterval",
"setTimeout",
"caches",
"__NEXT_DATA__",
"__BUILD_MANIFEST",
"__NEXT_PRELOADREADY",
])
script_source = random.choice(list(script_sources)) if script_sources else DEFAULT_POW_SCRIPT
return [
random.choice([3000, 4000, 5000]),
_legacy_parse_time(),
4294705152,
0,
user_agent,
script_source,
data_build,
"en-US",
"en-US,es-US,en,es",
0,
navigator_key,
random.choice(DOCUMENT_KEYS),
window_key,
time.perf_counter() * 1000,
new_uuid(),
"",
random.choice(CORES),
time.time() * 1000 - (time.perf_counter() * 1000),
]
def _pow_generate(seed: str, difficulty: str, config: list[Any], limit: int = 500000) -> tuple[str, bool]:
target = bytes.fromhex(difficulty)
diff_len = len(difficulty) // 2
seed_bytes = seed.encode()
static_1 = (json.dumps(config[:3], separators=(",", ":"), ensure_ascii=False)[:-1] + ",").encode()
static_2 = ("," + json.dumps(config[4:9], separators=(",", ":"), ensure_ascii=False)[1:-1] + ",").encode()
static_3 = ("," + json.dumps(config[10:], separators=(",", ":"), ensure_ascii=False)[1:]).encode()
for i in range(limit):
final_json = static_1 + str(i).encode() + static_2 + str(i >> 1).encode() + static_3
encoded = pybase64.b64encode(final_json)
digest = hashlib.sha3_512(seed_bytes + encoded).digest()
if digest[:diff_len] <= target:
return encoded.decode(), True
fallback = "wQ8Lk5FbGpA2NcR9dShT6gYjU7VxZ4D" + pybase64.b64encode(f'"{seed}"'.encode()).decode()
return fallback, False
def build_legacy_requirements_token(
user_agent: str,
script_sources: Sequence[str] | None = None,
data_build: str = "",
) -> str:
seed = format(random.random())
config = build_pow_config(user_agent, script_sources=script_sources, data_build=data_build)
answer, _ = _pow_generate(seed, "0fffff", config)
return "gAAAAAC" + answer
def build_proof_token(
seed: str,
difficulty: str,
user_agent: str,
script_sources: Sequence[str] | None = None,
data_build: str = "",
) -> str:
config = build_pow_config(user_agent, script_sources=script_sources, data_build=data_build)
answer, solved = _pow_generate(seed, difficulty, config)
if not solved:
raise RuntimeError(f"failed to solve proof token: difficulty={difficulty}")
return "gAAAAAB" + answer