chore: Update everything
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# dependencies = [
|
||||
# "httpx>=0.27.0",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
import argparse
|
||||
import time
|
||||
|
||||
import httpx
|
||||
|
||||
ROUTER_BASE_URL = "http://192.168.1.1"
|
||||
|
||||
# Captured from successful login flow for abdus:xAsametk50.
|
||||
# Firmware expects encrypted payload at /UserLogin.
|
||||
USER_LOGIN_PAYLOAD = {
|
||||
"content": "z7oqX7AWMrPjJdAEgrXCZY9q/+mrsyodlD53apbPmPXBkuB1SJXdoXr8+NcUbuRwn/jyc3HJlyKcMrAHDl3aFbN8/Gnyy8TzRKQkCAoSdVEVifzmWBPgpoDKvvT/p6n4TrAi2+b1eJ18Sr4ab1MWrI0XKNbBLEU+0UJlAd/UOHo=",
|
||||
"key": "UwLW2sfQZ5S5XegolmSX0kqpxwzeJEIXq8lp3gLkNpNX+qiBAC4E2ColaigMtsMPbVEEFGk+RiPixF9L4xI4licoguc71zEfG9U3YUvNZZeBpV3JKMLLDzhs5aFDIb9M4k/zQ623zByOWDKjnUhHqqRK1I8hEyhThbbhKUkvo67/6vcRHHE9c0Lcxc2SrIGeyRUvPe5F+zXH8PbUn4aPq6fVTPmECRbiZOOm6zoy99PvyRVIYiCOkWqeXHhGIdMl2YZhA2UeM+1lwWtFQjSgefPeCfdhtIuEfFfUUaj3DyPJfD/+CyUT0QGUH6SD5sf1M8DySqOglgH1dIXEPLyIwA==",
|
||||
"iv": "u+z76g62wnZYAehSfgffrPzpstykp6E891Z9CrDLfO0=",
|
||||
}
|
||||
|
||||
|
||||
def _extract_session_key(resp: httpx.Response) -> int:
|
||||
data = resp.json()
|
||||
if isinstance(data, list) and data:
|
||||
return int(data[0]["SessionKey"])
|
||||
if isinstance(data, dict) and "SessionKey" in data:
|
||||
return int(data["SessionKey"])
|
||||
raise RuntimeError(f"Could not parse SessionKey from /changeSessionKey response: {data!r}")
|
||||
|
||||
|
||||
def _wait_for_router(client: httpx.Client, max_wait: float) -> None:
|
||||
deadline = time.time() + max_wait
|
||||
last_error = None
|
||||
while time.time() < deadline:
|
||||
try:
|
||||
resp = client.get("/login")
|
||||
resp.raise_for_status()
|
||||
return
|
||||
except (httpx.ConnectTimeout, httpx.ReadTimeout, httpx.ConnectError, httpx.NetworkError) as exc:
|
||||
last_error = exc
|
||||
time.sleep(2)
|
||||
raise RuntimeError(f"Router not reachable within {max_wait:.0f}s") from last_error
|
||||
|
||||
|
||||
def reboot_router(timeout: float, post_confirm_sleep: float) -> None:
|
||||
with httpx.Client(base_url=ROUTER_BASE_URL, timeout=timeout, follow_redirects=True) as client:
|
||||
_wait_for_router(client, max_wait=90)
|
||||
|
||||
login = client.post("/UserLogin", json=USER_LOGIN_PAYLOAD)
|
||||
login.raise_for_status()
|
||||
|
||||
check = client.get("/cgi-bin/UserLoginCheck")
|
||||
check.raise_for_status()
|
||||
if "ZCFG_SUCCESS" not in check.text:
|
||||
raise RuntimeError(f"Login check failed: {check.text}")
|
||||
|
||||
key_resp = client.get("/changeSessionKey")
|
||||
key_resp.raise_for_status()
|
||||
session_key = _extract_session_key(key_resp)
|
||||
|
||||
reboot = client.post("/cgi-bin/Reboot", params={"sessionkey": session_key})
|
||||
reboot.raise_for_status()
|
||||
|
||||
time.sleep(post_confirm_sleep)
|
||||
print("Router reboot request sent.")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="Reboot router via HTTP API (no Playwright)")
|
||||
parser.add_argument("--timeout", type=float, default=20.0, help="HTTP timeout in seconds")
|
||||
parser.add_argument(
|
||||
"--post-confirm-sleep",
|
||||
type=float,
|
||||
default=5.0,
|
||||
help="Seconds to wait after reboot request",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
reboot_router(timeout=args.timeout, post_confirm_sleep=args.post_confirm_sleep)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user