website-api 1.0.1 → 1.0.3
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.
package/README.md
CHANGED
|
@@ -1,241 +1,3 @@
|
|
|
1
1
|
# website-api
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Features
|
|
8
|
-
|
|
9
|
-
- 🔑 **Keychain Decryption** — Leverages `chrome-tools` to decrypt Chrome cookies via the macOS Keychain.
|
|
10
|
-
- 📂 **Auto-Loading Adapters** — Drop a folder into `src/website/`, and the adapter is auto-discovered at runtime.
|
|
11
|
-
- 🧩 **Zero-Boilerplate Adapters** — The `defineAdapter()` factory handles cookies, user-agent, fetch, and error handling. Simple adapters are ~10 lines.
|
|
12
|
-
- 👥 **Multi-Profile Support** — Target specific Chrome profiles (e.g., `Default`, `Profile 1`) or custom user data paths.
|
|
13
|
-
- 🚀 **Dual Interface** — Works as both an importable ES module library and a terminal CLI.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Supported Website APIs
|
|
18
|
-
|
|
19
|
-
| ID | Name | Domain | Description |
|
|
20
|
-
|----|------|--------|-------------|
|
|
21
|
-
| `codex-usage` | ChatGPT / Codex Usage | chatgpt.com | Fetches ChatGPT rate limit usage and quota details from the private wham/usage API. |
|
|
22
|
-
| `cursor-usage` | Cursor Usage | cursor.com | Fetches the active Cursor usage summary from the private usage-summary API. |
|
|
23
|
-
| `ollama-usage` | Ollama Usage | ollama.com | Fetches Ollama plan and usage details from the authenticated settings page. |
|
|
24
|
-
|
|
25
|
-
Each adapter has a `request.md` file documenting the exact HTTP requests and expected responses.
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Installation & Setup
|
|
30
|
-
|
|
31
|
-
### Prerequisites
|
|
32
|
-
|
|
33
|
-
- macOS with Google Chrome installed
|
|
34
|
-
- Node.js ≥ 18
|
|
35
|
-
- [pnpm](https://pnpm.io/) package manager
|
|
36
|
-
|
|
37
|
-
### Install
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
pnpm install
|
|
41
|
-
pnpm run build
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Link CLI globally (optional)
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
pnpm link --global
|
|
48
|
-
website-api --help
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## CLI Usage
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
# Show help
|
|
57
|
-
node dist/bin/cli.js --help
|
|
58
|
-
|
|
59
|
-
# List all supported adapters
|
|
60
|
-
node dist/bin/cli.js list
|
|
61
|
-
|
|
62
|
-
# Query a website API
|
|
63
|
-
node dist/bin/cli.js codex-usage
|
|
64
|
-
node dist/bin/cli.js cursor-usage
|
|
65
|
-
node dist/bin/cli.js ollama-usage
|
|
66
|
-
|
|
67
|
-
# Domain aliases still work too
|
|
68
|
-
node dist/bin/cli.js chatgpt.com
|
|
69
|
-
node dist/bin/cli.js cursor.com
|
|
70
|
-
node dist/bin/cli.js ollama.com
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Options
|
|
74
|
-
|
|
75
|
-
| Option | Description |
|
|
76
|
-
|--------|-------------|
|
|
77
|
-
| `--profile <name>` | Target a specific Chrome profile (e.g., `Default`, `Profile 1`) |
|
|
78
|
-
| `--current-profile` | Show the currently resolved Chrome profile directory and name |
|
|
79
|
-
| `-u, --user-agent <string>` | Custom User-Agent header for HTTP requests |
|
|
80
|
-
|
|
81
|
-
### Universal Fallback
|
|
82
|
-
|
|
83
|
-
Any URL or domain not matching a registered adapter will be fetched directly with Chrome cookies:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
node dist/bin/cli.js https://example.com/api/data
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## Library Usage (Programmatic API)
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
import { queryWebsite } from "website-api";
|
|
95
|
-
|
|
96
|
-
const data = await queryWebsite("chatgpt.com", {
|
|
97
|
-
profile: "Default",
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// Command IDs also work:
|
|
101
|
-
// await queryWebsite("codex-usage", { profile: "Default" });
|
|
102
|
-
|
|
103
|
-
console.log(JSON.stringify(data, null, 2));
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## How to Add a New Website Adapter
|
|
109
|
-
|
|
110
|
-
### Step 1: Create the adapter folder
|
|
111
|
-
|
|
112
|
-
```
|
|
113
|
-
src/website/github.com/
|
|
114
|
-
├── github-adapter.ts ← adapter code
|
|
115
|
-
└── request.md ← document the endpoint (required)
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Step 2: Write the adapter
|
|
119
|
-
|
|
120
|
-
For **simple single-endpoint** APIs — just declare the endpoint:
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// src/website/github.com/github-adapter.ts
|
|
124
|
-
import { defineAdapter } from "../../base-adapter.js";
|
|
125
|
-
|
|
126
|
-
export default defineAdapter({
|
|
127
|
-
id: "github.com",
|
|
128
|
-
name: "GitHub Notifications",
|
|
129
|
-
domain: "github.com",
|
|
130
|
-
description: "Fetches unread notifications from the GitHub API.",
|
|
131
|
-
endpoints: [{ url: "https://api.github.com/notifications" }],
|
|
132
|
-
});
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
For **multi-step flows** (e.g., session token → API call) — override `fetchData`:
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
// src/website/example.com/example-adapter.ts
|
|
139
|
-
import { defineAdapter } from "../../base-adapter.js";
|
|
140
|
-
|
|
141
|
-
export default defineAdapter({
|
|
142
|
-
id: "example.com",
|
|
143
|
-
name: "Example Service",
|
|
144
|
-
domain: "example.com",
|
|
145
|
-
description: "Fetches data with a two-step auth flow.",
|
|
146
|
-
|
|
147
|
-
async fetchData(cookies, options) {
|
|
148
|
-
const cookieStr = this.buildCookieString(cookies); // shared helper
|
|
149
|
-
const ua = this.resolveUserAgent(options); // shared helper
|
|
150
|
-
|
|
151
|
-
// Step 1: get token
|
|
152
|
-
const session = await this.fetchJson("https://example.com/auth", {
|
|
153
|
-
headers: { Cookie: cookieStr, "User-Agent": ua },
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// Step 2: use token
|
|
157
|
-
return this.fetchJson("https://example.com/api/data", {
|
|
158
|
-
headers: { Authorization: `Bearer ${session.token}` },
|
|
159
|
-
});
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Step 3: Document the endpoint
|
|
165
|
-
|
|
166
|
-
Create `request.md` in the adapter folder documenting the HTTP requests, headers, and example responses. See [chatgpt.com/request.md](src/website/chatgpt.com/request.md) for reference.
|
|
167
|
-
|
|
168
|
-
### Step 4: Build and test
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
pnpm run build
|
|
172
|
-
node dist/bin/cli.js list # verify it appears
|
|
173
|
-
node dist/bin/cli.js github.com # test it
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
That's it — **no registration needed**. The adapter is auto-discovered from the `website/` directory at runtime.
|
|
177
|
-
|
|
178
|
-
---
|
|
179
|
-
|
|
180
|
-
## Shared Adapter Helpers
|
|
181
|
-
|
|
182
|
-
Every adapter created with `defineAdapter()` automatically gets these methods via `this`:
|
|
183
|
-
|
|
184
|
-
| Method | Description |
|
|
185
|
-
|--------|-------------|
|
|
186
|
-
| `this.buildCookieString(cookies)` | Converts cookies array to `"name=value; ..."` header string |
|
|
187
|
-
| `this.resolveUserAgent(options)` | Resolves User-Agent from options → `.env` → default |
|
|
188
|
-
| `this.fetchJson(url, init?)` | Fetch with error handling + automatic JSON parsing |
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## Configuration
|
|
193
|
-
|
|
194
|
-
Create a `.env` file in the project root:
|
|
195
|
-
|
|
196
|
-
```env
|
|
197
|
-
# Custom User-Agent (defaults to Chrome 148 on macOS)
|
|
198
|
-
userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"
|
|
199
|
-
|
|
200
|
-
# Custom Chrome profile path (defaults to standard macOS location)
|
|
201
|
-
PROFILE_PATH="/Users/yourname/chrome_profile/chrome"
|
|
202
|
-
PROFILE_NAME="Default"
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Project Structure
|
|
208
|
-
|
|
209
|
-
```
|
|
210
|
-
├── src/
|
|
211
|
-
│ ├── website-api.ts # Main entry — auto-loads adapters, queryWebsite()
|
|
212
|
-
│ ├── base-adapter.ts # defineAdapter() factory + shared helpers
|
|
213
|
-
│ ├── types.ts # TypeScript interfaces
|
|
214
|
-
│ ├── env.ts # .env file loader
|
|
215
|
-
│ ├── universal-adapter.ts # Fallback for unregistered domains
|
|
216
|
-
│ └── website/
|
|
217
|
-
│ ├── chatgpt.com/
|
|
218
|
-
│ │ ├── chatgpt-adapter.ts
|
|
219
|
-
│ │ └── request.md
|
|
220
|
-
│ ├── cursor.com/
|
|
221
|
-
│ ├── cursor-adapter.ts
|
|
222
|
-
│ └── request.md
|
|
223
|
-
│ └── ollama.com/
|
|
224
|
-
│ ├── ollama-adapter.ts
|
|
225
|
-
│ └── request.md
|
|
226
|
-
├── bin/
|
|
227
|
-
│ └── cli.ts # CLI entry point
|
|
228
|
-
├── tsconfig.json
|
|
229
|
-
├── package.json
|
|
230
|
-
└── .env # Local config (gitignored)
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
---
|
|
234
|
-
|
|
235
|
-
## Security Warning
|
|
236
|
-
|
|
237
|
-
This utility is designed strictly for local development and authorized administrative use. macOS will request explicit Keychain authorization before allowing `chrome-tools` to access the Chrome Safe Storage Password. Only run this tool in trusted environments.
|
|
238
|
-
|
|
239
|
-
## License
|
|
240
|
-
|
|
241
|
-
MIT License
|
|
3
|
+
CLI and library to fetch website API data
|
package/dist/src/base-adapter.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const t={buildCookieString:t=>t.map(t=>`${t.name}=${t.value}`).join("; "),resolveUserAgent:t=>t.userAgent||process.env.userAgent||process.env.USER_AGENT||"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",async fetchJson(t,e){const n=await fetch(t,e);if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);const r=await n.text();try{return JSON.parse(r)}catch{return{response:r}}},async fetchText(t,e){const n=await fetch(t,e);if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);return n.text()},async fetchHtml(t,e){return this.fetchText(t,e)}};async function e(t,e){if(!this.endpoints||0===this.endpoints.length)throw new Error(`Adapter "${this.id}" has no endpoints defined and no fetchData override`);const n=this.endpoints[0],r=this.buildCookieString(t),s=this.resolveUserAgent(e),o=await async function(t,e,n){const r=await fetch(t.url,{method:t.method||"GET",headers:{Cookie:e,"User-Agent":n,Accept:"html"===t.responseType?"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8":"text"===t.responseType?"text/plain,*/*;q=0.8":"application/json, text/plain, */*",...t.headers}});if(!r.ok)throw new Error(`HTTP ${r.status}: ${r.statusText}`);const s=await r.text(),o=r.headers.get("content-type")?.toLowerCase()??"";if("json"===t.responseType||"text"!==t.responseType&&"html"!==t.responseType&&(o.includes("application/json")||o.includes("+json")))try{return JSON.parse(s)}catch(e){throw new Error(`Expected JSON from ${t.url}, but received invalid JSON: ${e instanceof Error?e.message:String(e)}`)}return s}(n,r,s);return n.transform?n.transform.call(this,o,t,e):o}export function defineAdapter(n){const r={...n,...t,fetchData:n.fetchData??e};return r.fetchData=r.fetchData.bind(r),r}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -9,6 +9,13 @@ export interface Endpoint {
|
|
|
9
9
|
method?: string;
|
|
10
10
|
/** Additional headers to include in the request. */
|
|
11
11
|
headers?: Record<string, string>;
|
|
12
|
+
/**
|
|
13
|
+
* Expected response body type. Defaults to auto-detect from content-type.
|
|
14
|
+
* Use "html" for text/html responses that need parsing.
|
|
15
|
+
*/
|
|
16
|
+
responseType?: "auto" | "json" | "text" | "html";
|
|
17
|
+
/** Optional post-processing step for the parsed response body. */
|
|
18
|
+
transform?: (this: WebsiteAdapter, body: unknown, cookies: CookieEntry[], options: QueryOptions) => Promise<unknown> | unknown;
|
|
12
19
|
}
|
|
13
20
|
/**
|
|
14
21
|
* Configuration for defining a website adapter.
|
|
@@ -39,6 +46,10 @@ export interface WebsiteAdapter extends AdapterConfig {
|
|
|
39
46
|
resolveUserAgent(options: QueryOptions): string;
|
|
40
47
|
/** Fetches a URL and returns parsed JSON, with error handling. */
|
|
41
48
|
fetchJson(url: string, init?: RequestInit): Promise<any>;
|
|
49
|
+
/** Fetches a URL and returns the raw response text, with error handling. */
|
|
50
|
+
fetchText(url: string, init?: RequestInit): Promise<string>;
|
|
51
|
+
/** Fetches an HTML document as text, with error handling. */
|
|
52
|
+
fetchHtml(url: string, init?: RequestInit): Promise<string>;
|
|
42
53
|
}
|
|
43
54
|
/**
|
|
44
55
|
* Options passed when querying a website API.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{defineAdapter as e}from"../../base-adapter.js";export default e({id:"ollama-usage",name:"Ollama Usage",domain:"ollama.com",description:"Fetches Ollama plan and usage details from the authenticated settings page.",
|
|
1
|
+
import{defineAdapter as e}from"../../base-adapter.js";export default e({id:"ollama-usage",name:"Ollama Usage",domain:"ollama.com",description:"Fetches Ollama plan and usage details from the authenticated settings page.",endpoints:[{url:"https://ollama.com/settings",responseType:"html",headers:{Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},transform(e){const t="string"==typeof e?e:String(e),n=a(t,"Session usage"),i=a(t,"Weekly usage");return{time:(new Date).toISOString(),Plan:s(t),"Session Usage":n.usage,"Session Reset":n.reset,"Weekly Usage":i.usage,"Weekly Reset":i.reset}}}]});function s(e){const s=e.match(/Cloud Usage[\s\S]*?<\/span>[\s\S]*?<span[^>]*>([\s\S]*?)<\/span/i);return s?.[1]?.trim()??"unknown"}function a(e,s){const a=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");const t=new RegExp(`<div[\\s\\S]*?<span[^>]*>\\s*${a}\\s*<\\/span>[\\s\\S]*?aria-label="${a}\\s+([^"]+)"[\\s\\S]*?data-time="([^"]+)"`,"i"),n=e.match(t);return{usage:n?.[1]?.replace(/\s+used$/i,"").trim()??"unknown",reset:n?.[2]?.trim()??"unknown"}}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "website-api",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "CLI and library to fetch website API data
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "CLI and library to fetch website API data",
|
|
5
5
|
"main": "./dist/src/website-api.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|