buddy2api / extract_token.py
li2895's picture
Upload 6 files
845178e verified
Raw
History Blame Contribute Delete
4.08 kB
#!/usr/bin/env python3
"""
从运行中的 WorkBuddy 提取 Token(通过 CDP)。
用法:
python extract_token.py # 默认 CDP 端口 9222
python extract_token.py --port 9223 # 自定义端口
python extract_token.py --save # 提取并保存到 data/token.json
前提: WorkBuddy 以 --remote-debugging-port=9222 启动。
"""
import argparse
import asyncio
import json
import sys
from pathlib import Path
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
try:
import httpx
except ImportError:
sys.exit("请先安装依赖: pip install httpx")
async def extract(cdp_port: int = 9222) -> dict | None:
base = f"http://127.0.0.1:{cdp_port}"
async with httpx.AsyncClient() as client:
try:
resp = await client.get(f"{base}/json", timeout=5)
except httpx.ConnectError:
print(f"无法连接 CDP ({base}),请确认 WorkBuddy 已用调试模式启动")
return None
targets = resp.json()
ws_url = None
for t in targets:
if t.get("type") == "page" and "workbench" in t.get("url", ""):
ws_url = t.get("webSocketDebuggerUrl")
break
if not ws_url:
for t in targets:
if t.get("type") == "page":
ws_url = t.get("webSocketDebuggerUrl")
break
if not ws_url:
print("未找到可用的 CDP 页面目标")
return None
try:
import websockets
except ImportError:
sys.exit("请安装 websockets: pip install websockets")
async with websockets.connect(ws_url) as ws:
cmd = {
"id": 1,
"method": "Runtime.evaluate",
"params": {
"expression": """
(async () => {
try {
const s = await window.vscode.ipcRenderer.invoke(
'vscode:genie:auth:getSession'
);
return JSON.stringify(s);
} catch(e) {
return JSON.stringify({error: e.message});
}
})()
""",
"awaitPromise": True,
"returnByValue": True,
},
}
await ws.send(json.dumps(cmd))
result = json.loads(await asyncio.wait_for(ws.recv(), timeout=10))
value = result.get("result", {}).get("result", {}).get("value", "")
if not value:
print("CDP 返回为空")
return None
session = json.loads(value)
if session.get("error"):
print(f"CDP 错误: {session['error']}")
return None
return session
def main():
parser = argparse.ArgumentParser(description="从 WorkBuddy 提取 Token")
parser.add_argument("--port", type=int, default=9222, help="CDP 端口 (默认 9222)")
parser.add_argument("--save", action="store_true", help="保存到 data/token.json")
args = parser.parse_args()
session = asyncio.run(extract(args.port))
if not session:
sys.exit(1)
# 兼容新版(嵌套 auth)和旧版(扁平)结构
auth = session.get("auth", session)
access_token = auth.get("accessToken", "")
refresh_token = auth.get("refreshToken", "")
if not access_token:
print("未获取到 accessToken")
sys.exit(1)
print(f"accessToken: {access_token[:40]}... (len={len(access_token)})")
print(f"refreshToken: {refresh_token[:40]}... (len={len(refresh_token)})")
if args.save:
import time
out = Path(__file__).parent / "data" / "token.json"
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(json.dumps({
"access_token": access_token,
"refresh_token": refresh_token,
"saved_at": time.strftime("%Y-%m-%d %H:%M:%S"),
}, indent=2))
print(f"\n已保存到 {out}")
if __name__ == "__main__":
main()