@fudrouter/fsrouter 0.6.79 → 0.6.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,6 +28,7 @@ export default {
28
28
  baseUrl: "https://inference-api.nousresearch.com/v1/chat/completions",
29
29
  format: "openai",
30
30
  auth: {
31
+ combined: true,
31
32
  header: "Authorization",
32
33
  scheme: "bearer",
33
34
  },
@@ -1,4 +1,5 @@
1
- import { machineIdSync } from "node-machine-id";
1
+ import nodeMachineId from "node-machine-id";
2
+ const { machineIdSync } = nodeMachineId;
2
3
  import crypto from "node:crypto";
3
4
 
4
5
  let cachedRawId = null;
@@ -28,6 +28,7 @@ export default {
28
28
  baseUrl: "https://inference-api.nousresearch.com/v1/chat/completions",
29
29
  format: "openai",
30
30
  auth: {
31
+ combined: true,
31
32
  header: "Authorization",
32
33
  scheme: "bearer",
33
34
  },
@@ -1,4 +1,5 @@
1
- import { machineIdSync } from "node-machine-id";
1
+ import nodeMachineId from "node-machine-id";
2
+ const { machineIdSync } = nodeMachineId;
2
3
  import crypto from "node:crypto";
3
4
 
4
5
  let cachedRawId = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fudrouter/fsrouter",
3
- "version": "0.6.79",
3
+ "version": "0.6.81",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "9Router v2 — Express Backend (API, SSE, DB, Auth, MITM)",
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ cf_token_via_session.py
4
+ Login ke akun Cloudflare yang ada, buat Workers AI token via session cookie API.
5
+ Usage:
6
+ python cf_token_via_session.py --email X --password Y --account-id Z
7
+ """
8
+ import argparse, json, time, sys
9
+ import requests
10
+ from pathlib import Path
11
+
12
+ def log(m): print(json.dumps({"step": m}), flush=True)
13
+ def die(m): print(json.dumps({"status": "error", "error": m}), flush=True); sys.exit(1)
14
+
15
+
16
+ def create_token_with_cookies(cookies: dict, account_id: str) -> str | None:
17
+ """POST /api/v4/user/tokens using browser session cookies."""
18
+ base = "https://dash.cloudflare.com"
19
+ sess = requests.Session()
20
+ sess.cookies.update(cookies)
21
+ sess.headers.update({
22
+ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120",
23
+ "Referer": f"{base}/profile/api-tokens/create",
24
+ "Origin": base,
25
+ "Accept": "application/json",
26
+ })
27
+
28
+ # A1: Get permission groups to find Workers AI ID
29
+ log("Fetching permission groups...")
30
+ r = sess.get(f"{base}/api/v4/user/tokens/permission_groups", timeout=15)
31
+ log(f"Permission groups status: {r.status_code}")
32
+ if r.status_code != 200:
33
+ log(f"Permission groups response: {r.text[:300]}")
34
+ return None
35
+
36
+ pg_data = r.json()
37
+ log(f"Total groups: {len(pg_data.get('result', []))}")
38
+
39
+ # Find Workers AI groups
40
+ workers_ai_ids = []
41
+ for pg in pg_data.get('result', []):
42
+ name = pg.get('name', '')
43
+ if 'Workers AI' in name:
44
+ log(f"Found: {name} -> {pg['id']}")
45
+ workers_ai_ids.append({'id': pg['id'], 'name': name})
46
+
47
+ if not workers_ai_ids:
48
+ log("No Workers AI permission groups found")
49
+ log(f"All groups: {[p['name'] for p in pg_data.get('result', [])][:20]}")
50
+ return None
51
+
52
+ # Prefer Workers AI:Read for safety, otherwise take first
53
+ target_id = workers_ai_ids[0]['id']
54
+ for pg in workers_ai_ids:
55
+ if 'Read' in pg['name']:
56
+ target_id = pg['id']
57
+ break
58
+
59
+ log(f"Using permission group ID: {target_id}")
60
+
61
+ # A2: Create token
62
+ payload = {
63
+ "name": "9router-workers-ai",
64
+ "policies": [{
65
+ "effect": "allow",
66
+ "resources": {f"com.cloudflare.api.account.{account_id}": "*"},
67
+ "permission_groups": [{"id": target_id}]
68
+ }]
69
+ }
70
+
71
+ log(f"Creating token with payload: {json.dumps(payload)}")
72
+ r2 = sess.post(f"{base}/api/v4/user/tokens", json=payload, timeout=15)
73
+ log(f"Create token status: {r2.status_code}")
74
+ resp2 = r2.json()
75
+ log(f"Response: {json.dumps(resp2)[:500]}")
76
+
77
+ if resp2.get('success'):
78
+ return resp2['result'].get('value', '')
79
+ return None
80
+
81
+
82
+ def main():
83
+ parser = argparse.ArgumentParser()
84
+ parser.add_argument("--email", required=True)
85
+ parser.add_argument("--password", required=True)
86
+ parser.add_argument("--account-id", required=True, dest="account_id")
87
+ parser.add_argument("--headless", action="store_true")
88
+ args = parser.parse_args()
89
+
90
+ try:
91
+ from camoufox.sync_api import Camoufox
92
+ except ImportError:
93
+ die("Camoufox tidak terinstall")
94
+
95
+ log(f"Login ke CF sebagai {args.email}...")
96
+ with Camoufox(headless=args.headless, os="windows") as browser:
97
+ page = browser.new_page()
98
+
99
+ # Navigate to login
100
+ page.goto("https://dash.cloudflare.com/login", wait_until="domcontentloaded", timeout=30000)
101
+ time.sleep(3)
102
+
103
+ # Fill login form
104
+ try:
105
+ email_inp = page.locator("input[name='email'], input[type='email']").first
106
+ if email_inp.is_visible(timeout=5000):
107
+ email_inp.fill(args.email)
108
+ time.sleep(0.3)
109
+
110
+ pass_inp = page.locator("input[type='password']").first
111
+ if pass_inp.is_visible(timeout=3000):
112
+ pass_inp.fill(args.password)
113
+ time.sleep(0.3)
114
+
115
+ for sel in ["button[type='submit']", "button:has-text('Log in')", "button:has-text('Sign in')"]:
116
+ try:
117
+ btn = page.locator(sel).first
118
+ if btn.is_visible(timeout=2000):
119
+ btn.click()
120
+ break
121
+ except Exception:
122
+ continue
123
+
124
+ log("Login submitted, waiting...")
125
+ time.sleep(6)
126
+ except Exception as e:
127
+ log(f"Login form error: {e}")
128
+
129
+ log(f"Current URL: {page.url}")
130
+ page.screenshot(path="/tmp/cf_login_state.png")
131
+
132
+ # Check if logged in
133
+ if "dash.cloudflare.com" not in page.url:
134
+ die(f"Login failed, URL: {page.url}")
135
+
136
+ # Extract cookies
137
+ cookies_list = page.context.cookies()
138
+ cookies = {c['name']: c['value'] for c in cookies_list}
139
+ log(f"Got {len(cookies)} cookies: {list(cookies.keys())[:10]}")
140
+
141
+ # Create token via API
142
+ token = create_token_with_cookies(cookies, args.account_id)
143
+
144
+ if token:
145
+ log(f"TOKEN BERHASIL: {token[:12]}...")
146
+ print(json.dumps({
147
+ "status": "success",
148
+ "workers_ai_token": token,
149
+ "account_id": args.account_id,
150
+ "email": args.email
151
+ }), flush=True)
152
+ else:
153
+ page.screenshot(path="/tmp/cf_session_debug.png")
154
+ die("Token creation via session failed")
155
+
156
+
157
+ if __name__ == "__main__":
158
+ main()