Initial project import
This commit is contained in:
+207
@@ -0,0 +1,207 @@
|
||||
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 = ["__reactContainer$fzelfjyxej8", "_reactListening5dehydibo78", "location"]
|
||||
SCREEN_RESOLUTIONS = [[1920, 1080], [1440, 900], [2560, 1440], [3840, 2160]]
|
||||
|
||||
|
||||
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 [
|
||||
sum(random.choices(SCREEN_RESOLUTIONS, k=1)[0]),
|
||||
_legacy_parse_time(),
|
||||
4294705152,
|
||||
1,
|
||||
user_agent,
|
||||
script_source,
|
||||
data_build,
|
||||
"en-US",
|
||||
"en-US,es-US,en,es",
|
||||
random.random(),
|
||||
navigator_key,
|
||||
random.choice(DOCUMENT_KEYS),
|
||||
window_key,
|
||||
time.perf_counter() * 1000,
|
||||
new_uuid(),
|
||||
"",
|
||||
random.choice(CORES),
|
||||
time.time() * 1000 - (time.perf_counter() * 1000),
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, # 0 = edge/chrome, 1 = firefox
|
||||
]
|
||||
|
||||
|
||||
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:
|
||||
config = build_pow_config(user_agent, script_sources=script_sources, data_build=data_build)
|
||||
return "gAAAAAC" + pybase64.b64encode(
|
||||
json.dumps(config, separators=(",", ":"), ensure_ascii=False).encode()
|
||||
).decode()
|
||||
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user