File size: 13,073 Bytes
845178e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | #!/usr/bin/env python3
"""
WorkBuddy Token 提取工具(傻瓜版)
全自动检测和安装依赖,用户只需双击运行即可。
功能:
- 自动检测并安装 Python(如未安装)
- 自动安装脚本依赖
- 自动启动 WorkBuddy(调试模式)
- 自动提取 Token 并保存到桌面
"""
import os
import sys
import time
import json
import subprocess
import asyncio
import platform
from pathlib import Path
def run_cmd(cmd, check=True, shell=True):
"""执行命令并返回结果"""
try:
result = subprocess.run(
cmd, shell=shell, capture_output=True, text=True, timeout=300
)
if check and result.returncode != 0:
return False, result.stderr
return True, result.stdout
except subprocess.TimeoutExpired:
return False, "命令执行超时"
except Exception as e:
return False, str(e)
def check_python():
"""检查 Python 是否安装"""
py_names = ["python", "python3"] if platform.system() == "Windows" else ["python3", "python"]
for name in py_names:
try:
result = subprocess.run(
[name, "--version"], capture_output=True, text=True
)
if result.returncode == 0:
version = result.stdout.strip()
print(f" ✅ Python 已安装: {version}")
return True
except FileNotFoundError:
continue
print(" ❌ Python 未安装,正在安装...")
return False
def install_homebrew():
"""安装 Homebrew"""
print("\n正在安装 Homebrew...")
print("(这可能需要几分钟,请耐心等待)\n")
cmd = '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'
ok, msg = run_cmd(cmd, check=False)
if ok:
print(" ✅ Homebrew 安装成功!")
return True
else:
print(f" ⚠️ Homebrew 安装失败")
print("\n请手动安装 Homebrew:")
print(" 打开终端,粘贴以下命令:")
print(" /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"")
return False
def install_python_via_installer():
"""通过 python.org 安装包安装 Python(不需要 sudo)"""
print("\n正在下载 Python 安装包...")
print("(这可能需要几分钟,取决于网速)\n")
dmg_url = "https://www.python.org/ftp/python/3.13.0/python-3.13.0-macos11.pkg"
dmg_path = "/tmp/python-installer.pkg"
ok, _ = run_cmd(f'curl -L -o "{dmg_path}" "{dmg_url}"', check=False)
if not ok:
print(" ❌ 下载失败,请检查网络连接")
return False
print(" ✅ 下载完成,正在打开安装程序...")
print("\n" + "=" * 50)
print(" 请在弹出的安装程序中:")
print(" 1. 点击「继续」")
print(" 2. 阅读许可协议,点击「继续」→「同意」")
print(" 3. 选择安装位置,点击「安装」")
print(" 4. 输入电脑密码(如果有)")
print(" 5. 等待安装完成,点击「关闭」")
print("=" * 50)
print("\n安装完成后,回到此窗口按回车键继续...")
print("(或者输入 q 退出,稍后手动安装)")
response = input("\n按回车继续,或输入 q 退出: ").strip().lower()
if response == 'q':
return False
run_cmd(f'open "{dmg_path}"', check=False)
input("\n安装完成后,按回车继续...")
return True
def install_python():
"""安装 Python"""
print("\n" + "=" * 50)
print("正在安装 Python...")
print("=" * 50)
success, _ = run_cmd("which brew")
if not success:
print(" ❌ 未检测到 Homebrew")
print("\n尝试通过安装包安装 Python(不需要 sudo)...")
if install_python_via_installer():
ok, _ = run_cmd("which python3", check=False)
if ok:
print(" ✅ Python 安装成功!")
return True
print("\n正在安装 Homebrew 作为备选...")
if not install_homebrew():
print("\n⚠️ 无法自动安装 Python")
print("请手动安装: https://www.python.org/downloads/")
return False
print("\n重新检测 Homebrew...")
success, _ = run_cmd("which brew")
if not success:
print(" ❌ Homebrew 安装失败")
return False
print("使用 Homebrew 安装 Python...")
ok, msg = run_cmd("brew install python", check=False)
if ok:
print(" ✅ Python 安装成功!")
return True
else:
print(f" ⚠️ Homebrew 安装 Python 失败")
print("尝试通过安装包安装...")
if install_python_via_installer():
ok, _ = run_cmd("which python3", check=False)
if ok:
print(" ✅ Python 安装成功!")
return True
return False
def install_dependencies():
"""安装脚本依赖"""
print("\n正在安装依赖 (httpx, websockets)...")
pip_cmd = "pip" if platform.system() == "Windows" else "pip3"
deps = ["httpx", "websockets"]
for dep in deps:
ok, _ = run_cmd(f"{pip_cmd} install {dep}")
if ok:
print(f" ✅ {dep} 安装成功")
else:
print(f" ❌ {dep} 安装失败")
return False
return True
def check_workbuddy_installed():
"""检查 WorkBuddy 是否安装"""
paths = [
Path("/Applications/WorkBuddy.app"),
Path.home() / "Applications/WorkBuddy.app",
# Windows paths
Path(os.path.expandvars(r"%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe")),
Path(os.path.expandvars(r"%ProgramFiles%\WorkBuddy\WorkBuddy.exe")),
Path(os.path.expandvars(r"%ProgramFiles(x86)%\WorkBuddy\WorkBuddy.exe")),
Path(r"D:\Program Files\WorkBuddy\WorkBuddy.exe"),
Path(r"E:\Program Files\WorkBuddy\WorkBuddy.exe"),
]
for p in paths:
if p.exists():
return True, p
return False, None
def check_workbuddy_running():
"""检查 WorkBuddy 是否正在运行(调试模式)"""
try:
import httpx
resp = httpx.get("http://127.0.0.1:9222/json", timeout=2)
if resp.status_code == 200:
return True
except:
pass
return False
def start_workbuddy_debug():
"""启动 WorkBuddy 调试模式"""
print("\n正在启动 WorkBuddy(调试模式)...")
if platform.system() == "Windows":
# Find WorkBuddy on Windows
candidates = [
os.path.expandvars(r"%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe"),
os.path.expandvars(r"%ProgramFiles%\WorkBuddy\WorkBuddy.exe"),
os.path.expandvars(r"%ProgramFiles(x86)%\WorkBuddy\WorkBuddy.exe"),
r"D:\Program Files\WorkBuddy\WorkBuddy.exe",
r"E:\Program Files\WorkBuddy\WorkBuddy.exe",
]
workbuddy_path = next((p for p in candidates if os.path.exists(p)), None)
if not workbuddy_path:
print(" ❌ 找不到 WorkBuddy,请手动启动" )
print(" → 关闭 WorkBuddy,然后重新打开" )
print(" → 或者:Win+R 运行:workbuddy --remote-debugging-port=9222" )
return False
cmd = f'"{workbuddy_path}" --remote-debugging-port=9222'
else:
workbuddy_path = "/Applications/WorkBuddy.app/Contents/MacOS/Electron"
cmd = f'"{workbuddy_path}" --remote-debugging-port=9222'
try:
subprocess.Popen(cmd, shell=True)
print(" ✅ WorkBuddy 已启动")
print("\n等待 WorkBuddy 完全加载(5秒)...")
time.sleep(5)
return True
except Exception as e:
print(f" ❌ 启动失败: {e}")
return False
def check_requirements():
"""检查前置条件"""
print("\n[检查 1/4] 检测 Python...")
if not check_python():
if not install_python():
return False
print("\n[检查 2/4] 安装依赖...")
if not install_dependencies():
return False
print("\n[检查 3/4] 检测 WorkBuddy...")
installed, path = check_workbuddy_installed()
if not installed:
print(" ❌ WorkBuddy 未安装")
print(" 请先安装 WorkBuddy: https://workbuddy.com/download")
return False
print(f" ✅ WorkBuddy 已安装: {path}")
print("\n[检查 4/4] 检测 WorkBuddy 运行状态...")
if check_workbuddy_running():
print(" ✅ WorkBuddy 已运行(调试模式)")
else:
print(" ⚠️ WorkBuddy 未运行,正在启动...")
if not start_workbuddy_debug():
return False
return True
async def extract_token():
"""从 WorkBuddy 提取 Token"""
import httpx
import websockets
print("\n正在连接 WorkBuddy...")
async with httpx.AsyncClient() as client:
resp = await client.get("http://127.0.0.1:9222/json", timeout=5)
targets = resp.json()
print(f" ✅ 找到 {len(targets)} 个页面")
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:
raise Exception("未找到 WorkBuddy 页面")
print(" ✅ 已找到 WorkBuddy 页面")
print("\n正在提取 Token...")
async with websockets.connect(ws_url, ping_timeout=30) 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=30))
value = result.get("result", {}).get("result", {}).get("value", "")
if not value:
raise Exception("CDP 返回为空")
session = json.loads(value)
if session.get("error"):
raise Exception(f"CDP 错误: {session['error']}")
return session
def save_token(access_token, refresh_token):
"""保存 Token 到桌面"""
desktop = Path.home() / "Desktop"
output_file = desktop / "token.txt"
content = f"""WorkBuddy Token
生成时间: {time.strftime("%Y-%m-%d %H:%M:%S")}
access_token={access_token}
refresh_token={refresh_token}
"""
output_file.write_text(content, encoding="utf-8")
return output_file
def main():
print("=" * 50)
print(" WorkBuddy Token 提取工具")
print("=" * 50)
print("\n正在检测环境...\n")
if not check_requirements():
input("\n按回车键退出...")
sys.exit(1)
try:
session = asyncio.run(extract_token())
except Exception as e:
print(f"\n❌ 提取失败: {e}")
print("\n请确保:")
print(" 1. WorkBuddy 已登录")
print(" 2. 重新运行此脚本")
input("\n按回车键退出...")
sys.exit(1)
auth = session.get("auth", session)
access_token = auth.get("accessToken", "")
refresh_token = auth.get("refreshToken", "")
if not access_token:
print("\n❌ 未获取到 accessToken")
print("请确保 WorkBuddy 已登录 AI 功能")
input("\n按回车键退出...")
sys.exit(1)
try:
output_file = save_token(access_token, refresh_token)
except Exception as e:
print(f"\n❌ 保存失败: {e}")
input("\n按回车键退出...")
sys.exit(1)
print("\n" + "=" * 50)
print("✅ 成功!")
print("=" * 50)
print(f"\n📄 Token 已保存到桌面:")
print(f" {output_file}")
print(f"\n🔑 access_token: {access_token[:30]}...")
print(f"🔑 refresh_token: {refresh_token[:30] if refresh_token else 'N/A'}...")
print("\n" + "=" * 50)
input("\n按回车键退出...")
if __name__ == "__main__":
main()
|