x-reader 0.1.0
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/LICENSE +21 -0
- package/README.md +206 -0
- package/dist/api/client.d.ts +65 -0
- package/dist/api/client.js +527 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/constants.d.ts +23 -0
- package/dist/api/constants.js +60 -0
- package/dist/api/constants.js.map +1 -0
- package/dist/api/features.d.ts +14 -0
- package/dist/api/features.js +158 -0
- package/dist/api/features.js.map +1 -0
- package/dist/api/parser.d.ts +23 -0
- package/dist/api/parser.js +236 -0
- package/dist/api/parser.js.map +1 -0
- package/dist/api/query-ids.d.ts +31 -0
- package/dist/api/query-ids.js +201 -0
- package/dist/api/query-ids.js.map +1 -0
- package/dist/api/types.d.ts +91 -0
- package/dist/api/types.js +3 -0
- package/dist/api/types.js.map +1 -0
- package/dist/cli/index.d.ts +15 -0
- package/dist/cli/index.js +258 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/auth.d.ts +21 -0
- package/dist/utils/auth.js +128 -0
- package/dist/utils/auth.js.map +1 -0
- package/dist/utils/format.d.ts +15 -0
- package/dist/utils/format.js +62 -0
- package/dist/utils/format.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-discovery of Twitter/X GraphQL query IDs.
|
|
3
|
+
*
|
|
4
|
+
* X periodically rotates the query IDs embedded in their JS bundles.
|
|
5
|
+
* This module scrapes x.com pages to find the current bundle URLs,
|
|
6
|
+
* then parses those bundles to extract queryId ↔ operationName mappings.
|
|
7
|
+
*
|
|
8
|
+
* Falls back to hardcoded defaults if discovery fails.
|
|
9
|
+
*/
|
|
10
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
11
|
+
import { homedir } from 'os';
|
|
12
|
+
import { join, dirname, resolve } from 'path';
|
|
13
|
+
import { DEFAULT_QUERY_IDS, DISCOVERY_PAGES, BUNDLE_URL_REGEX, QUERY_ID_PATTERNS, QUERY_ID_TTL_MS, DISCOVERY_OPERATIONS, } from './constants.js';
|
|
14
|
+
const VALID_QUERY_ID = /^[a-zA-Z0-9_-]+$/;
|
|
15
|
+
const FETCH_HEADERS = {
|
|
16
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
|
|
17
|
+
Accept: 'text/html,application/json;q=0.9,*/*;q=0.8',
|
|
18
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
19
|
+
};
|
|
20
|
+
// ─── Cache file path ─────────────────────────────────────────────
|
|
21
|
+
function getCachePath() {
|
|
22
|
+
const envPath = process.env.XREADER_QUERY_IDS_CACHE;
|
|
23
|
+
if (envPath?.trim())
|
|
24
|
+
return resolve(envPath.trim());
|
|
25
|
+
return join(homedir(), '.config', 'x-reader', 'query-ids-cache.json');
|
|
26
|
+
}
|
|
27
|
+
// ─── Load / Save cache ──────────────────────────────────────────
|
|
28
|
+
function parseCache(raw) {
|
|
29
|
+
if (!raw || typeof raw !== 'object')
|
|
30
|
+
return null;
|
|
31
|
+
const obj = raw;
|
|
32
|
+
const fetchedAt = typeof obj.fetchedAt === 'string' ? obj.fetchedAt : null;
|
|
33
|
+
const ttlMs = typeof obj.ttlMs === 'number' && Number.isFinite(obj.ttlMs) ? obj.ttlMs : null;
|
|
34
|
+
const ids = obj.ids && typeof obj.ids === 'object' ? obj.ids : null;
|
|
35
|
+
const disc = obj.discovery && typeof obj.discovery === 'object'
|
|
36
|
+
? obj.discovery
|
|
37
|
+
: null;
|
|
38
|
+
if (!fetchedAt || !ttlMs || !ids || !disc)
|
|
39
|
+
return null;
|
|
40
|
+
const pages = Array.isArray(disc.pages) ? disc.pages.filter((p) => typeof p === 'string') : null;
|
|
41
|
+
const bundles = Array.isArray(disc.bundles) ? disc.bundles.filter((b) => typeof b === 'string') : null;
|
|
42
|
+
if (!pages || !bundles)
|
|
43
|
+
return null;
|
|
44
|
+
const cleanIds = {};
|
|
45
|
+
for (const [k, v] of Object.entries(ids)) {
|
|
46
|
+
if (typeof v === 'string' && v.trim())
|
|
47
|
+
cleanIds[k] = v.trim();
|
|
48
|
+
}
|
|
49
|
+
return { fetchedAt, ttlMs, ids: cleanIds, discovery: { pages, bundles } };
|
|
50
|
+
}
|
|
51
|
+
async function loadCache(path) {
|
|
52
|
+
try {
|
|
53
|
+
const raw = await readFile(path, 'utf8');
|
|
54
|
+
return parseCache(JSON.parse(raw));
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function saveCache(path, cache) {
|
|
61
|
+
await mkdir(dirname(path), { recursive: true });
|
|
62
|
+
await writeFile(path, JSON.stringify(cache, null, 2) + '\n', 'utf8');
|
|
63
|
+
}
|
|
64
|
+
// ─── Bundle discovery ───────────────────────────────────────────
|
|
65
|
+
async function fetchText(url) {
|
|
66
|
+
const resp = await fetch(url, { headers: FETCH_HEADERS });
|
|
67
|
+
if (!resp.ok) {
|
|
68
|
+
const body = await resp.text().catch(() => '');
|
|
69
|
+
throw new Error(`HTTP ${resp.status} for ${url}: ${body.slice(0, 120)}`);
|
|
70
|
+
}
|
|
71
|
+
return resp.text();
|
|
72
|
+
}
|
|
73
|
+
async function discoverBundleUrls() {
|
|
74
|
+
const found = new Set();
|
|
75
|
+
for (const page of DISCOVERY_PAGES) {
|
|
76
|
+
try {
|
|
77
|
+
const html = await fetchText(page);
|
|
78
|
+
for (const match of html.matchAll(BUNDLE_URL_REGEX)) {
|
|
79
|
+
found.add(match[0]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Some pages may fail — that's OK
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const urls = [...found];
|
|
87
|
+
if (urls.length === 0) {
|
|
88
|
+
throw new Error('No client bundles discovered; x.com layout may have changed.');
|
|
89
|
+
}
|
|
90
|
+
return urls;
|
|
91
|
+
}
|
|
92
|
+
function extractFromBundle(js, bundleName, wantedOps, results) {
|
|
93
|
+
for (const pattern of QUERY_ID_PATTERNS) {
|
|
94
|
+
pattern.regex.lastIndex = 0;
|
|
95
|
+
let match;
|
|
96
|
+
while ((match = pattern.regex.exec(js)) !== null) {
|
|
97
|
+
const op = match[pattern.operationGroup];
|
|
98
|
+
const qid = match[pattern.queryIdGroup];
|
|
99
|
+
if (!op || !qid || !wantedOps.has(op) || !VALID_QUERY_ID.test(qid))
|
|
100
|
+
continue;
|
|
101
|
+
if (results.has(op))
|
|
102
|
+
continue;
|
|
103
|
+
results.set(op, { queryId: qid, bundle: bundleName });
|
|
104
|
+
if (results.size === wantedOps.size)
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function scanBundles(urls, wantedOps) {
|
|
110
|
+
const results = new Map();
|
|
111
|
+
const BATCH = 6;
|
|
112
|
+
for (let i = 0; i < urls.length; i += BATCH) {
|
|
113
|
+
const batch = urls.slice(i, i + BATCH);
|
|
114
|
+
await Promise.all(batch.map(async (url) => {
|
|
115
|
+
if (results.size === wantedOps.size)
|
|
116
|
+
return;
|
|
117
|
+
const name = url.split('/').at(-1) ?? url;
|
|
118
|
+
try {
|
|
119
|
+
const js = await fetchText(url);
|
|
120
|
+
extractFromBundle(js, name, wantedOps, results);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Individual bundle failures are OK
|
|
124
|
+
}
|
|
125
|
+
}));
|
|
126
|
+
if (results.size === wantedOps.size)
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
return results;
|
|
130
|
+
}
|
|
131
|
+
// ─── Public API ─────────────────────────────────────────────────
|
|
132
|
+
let memoryCache = null;
|
|
133
|
+
export async function getSnapshotInfo() {
|
|
134
|
+
const cachePath = getCachePath();
|
|
135
|
+
if (!memoryCache) {
|
|
136
|
+
memoryCache = await loadCache(cachePath);
|
|
137
|
+
}
|
|
138
|
+
if (!memoryCache)
|
|
139
|
+
return null;
|
|
140
|
+
const age = Date.now() - new Date(memoryCache.fetchedAt).getTime();
|
|
141
|
+
return {
|
|
142
|
+
snapshot: memoryCache,
|
|
143
|
+
cachePath,
|
|
144
|
+
ageMs: Number.isFinite(age) ? Math.max(0, age) : Infinity,
|
|
145
|
+
isFresh: age <= (memoryCache.ttlMs || QUERY_ID_TTL_MS),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get a single query ID by operation name.
|
|
150
|
+
* Returns cached value, or falls back to hardcoded default.
|
|
151
|
+
*/
|
|
152
|
+
export async function getQueryId(operation) {
|
|
153
|
+
const info = await getSnapshotInfo();
|
|
154
|
+
if (info?.snapshot.ids[operation]) {
|
|
155
|
+
return info.snapshot.ids[operation];
|
|
156
|
+
}
|
|
157
|
+
return DEFAULT_QUERY_IDS[operation] ?? '';
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Refresh query IDs by scraping x.com JS bundles.
|
|
161
|
+
* Saves results to disk cache.
|
|
162
|
+
*/
|
|
163
|
+
export async function refreshQueryIds(options = {}) {
|
|
164
|
+
const cachePath = getCachePath();
|
|
165
|
+
// Check if cache is still fresh
|
|
166
|
+
if (!options.force) {
|
|
167
|
+
const existing = await getSnapshotInfo();
|
|
168
|
+
if (existing?.isFresh)
|
|
169
|
+
return existing;
|
|
170
|
+
}
|
|
171
|
+
const wantedOps = new Set(DISCOVERY_OPERATIONS);
|
|
172
|
+
const bundleUrls = await discoverBundleUrls();
|
|
173
|
+
const found = await scanBundles(bundleUrls, wantedOps);
|
|
174
|
+
if (found.size === 0) {
|
|
175
|
+
// Discovery failed — return existing cache if any
|
|
176
|
+
return getSnapshotInfo();
|
|
177
|
+
}
|
|
178
|
+
const ids = {};
|
|
179
|
+
for (const op of DISCOVERY_OPERATIONS) {
|
|
180
|
+
const entry = found.get(op);
|
|
181
|
+
if (entry?.queryId)
|
|
182
|
+
ids[op] = entry.queryId;
|
|
183
|
+
}
|
|
184
|
+
const cache = {
|
|
185
|
+
fetchedAt: new Date().toISOString(),
|
|
186
|
+
ttlMs: QUERY_ID_TTL_MS,
|
|
187
|
+
ids,
|
|
188
|
+
discovery: {
|
|
189
|
+
pages: [...DISCOVERY_PAGES],
|
|
190
|
+
bundles: bundleUrls.map((u) => u.split('/').at(-1) ?? u),
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
await saveCache(cachePath, cache);
|
|
194
|
+
memoryCache = cache;
|
|
195
|
+
return getSnapshotInfo();
|
|
196
|
+
}
|
|
197
|
+
/** Clear in-memory cache (for testing) */
|
|
198
|
+
export function clearMemory() {
|
|
199
|
+
memoryCache = null;
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=query-ids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-ids.js","sourceRoot":"","sources":["../../src/api/query-ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,MAAM,aAAa,GAA2B;IAC5C,YAAY,EACV,iHAAiH;IACnH,MAAM,EAAE,4CAA4C;IACpD,iBAAiB,EAAE,gBAAgB;CACpC,CAAC;AAEF,oEAAoE;AAEpE,SAAS,YAAY;IACnB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IACpD,IAAI,OAAO,EAAE,IAAI,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,sBAAsB,CAAC,CAAC;AACxE,CAAC;AAED,mEAAmE;AAEnE,SAAS,UAAU,CAAC,GAAY;IAC9B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,GAAG,GAAG,GAA8B,CAAC;IAE3C,MAAM,SAAS,GAAG,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7F,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAE,GAAG,CAAC,GAA+B,CAAC,CAAC,CAAC,IAAI,CAAC;IACjG,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ;QAC7D,CAAC,CAAE,GAAG,CAAC,SAAqC;QAC5C,CAAC,CAAC,IAAI,CAAC;IAET,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9G,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpH,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAEpC,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAC5C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE;YAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;AAC5E,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,KAAmB;IACxD,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACvE,CAAC;AAED,mEAAmE;AAEnE,KAAK,UAAU,SAAS,CAAC,GAAW;IAClC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,kBAAkB;IAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;YACnC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACpD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACxB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CACxB,EAAU,EACV,UAAkB,EAClB,SAAsB,EACtB,OAAyD;IAEzD,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;QAC5B,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACjD,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YACxC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC7E,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,SAAS;YAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YACtD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI;gBAAE,OAAO;QAC9C,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,IAAc,EACd,SAAsB;IAEtB,MAAM,OAAO,GAAG,IAAI,GAAG,EAA+C,CAAC;IACvE,MAAM,KAAK,GAAG,CAAC,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;QACvC,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACtB,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI;gBAAE,OAAO;YAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;gBAChC,iBAAiB,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YAClD,CAAC;YAAC,MAAM,CAAC;gBACP,oCAAoC;YACtC,CAAC;QACH,CAAC,CAAC,CACH,CAAC;QACF,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI;YAAE,MAAM;IAC7C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,mEAAmE;AAEnE,IAAI,WAAW,GAAwB,IAAI,CAAC;AAS5C,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,WAAW,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAE9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IACnE,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,SAAS;QACT,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ;QACzD,OAAO,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,eAAe,CAAC;KACvD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAAiB;IAChD,MAAM,IAAI,GAAG,MAAM,eAAe,EAAE,CAAC;IACrC,IAAI,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,iBAAiB,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAA+B,EAAE;IAEjC,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,gCAAgC;IAChC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,MAAM,eAAe,EAAE,CAAC;QACzC,IAAI,QAAQ,EAAE,OAAO;YAAE,OAAO,QAAQ,CAAC;IACzC,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC9C,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAEvD,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACrB,kDAAkD;QAClD,OAAO,eAAe,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,EAAE,IAAI,oBAAoB,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5B,IAAI,KAAK,EAAE,OAAO;YAAE,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9C,CAAC;IAED,MAAM,KAAK,GAAiB;QAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,KAAK,EAAE,eAAe;QACtB,GAAG;QACH,SAAS,EAAE;YACT,KAAK,EAAE,CAAC,GAAG,eAAe,CAAC;YAC3B,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACzD;KACF,CAAC;IAEF,MAAM,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAClC,WAAW,GAAG,KAAK,CAAC;IACpB,OAAO,eAAe,EAAE,CAAC;AAC3B,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,WAAW;IACzB,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** Core types for x-reader */
|
|
2
|
+
export interface Tweet {
|
|
3
|
+
id: string;
|
|
4
|
+
text: string;
|
|
5
|
+
createdAt?: string;
|
|
6
|
+
replyCount?: number;
|
|
7
|
+
retweetCount?: number;
|
|
8
|
+
likeCount?: number;
|
|
9
|
+
conversationId?: string;
|
|
10
|
+
inReplyToStatusId?: string;
|
|
11
|
+
author: {
|
|
12
|
+
username: string;
|
|
13
|
+
name: string;
|
|
14
|
+
};
|
|
15
|
+
authorId?: string;
|
|
16
|
+
quotedTweet?: Tweet;
|
|
17
|
+
media?: TweetMedia[];
|
|
18
|
+
article?: {
|
|
19
|
+
title: string;
|
|
20
|
+
previewText?: string;
|
|
21
|
+
};
|
|
22
|
+
_raw?: unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface TweetMedia {
|
|
25
|
+
type: string;
|
|
26
|
+
url: string;
|
|
27
|
+
width?: number;
|
|
28
|
+
height?: number;
|
|
29
|
+
previewUrl?: string;
|
|
30
|
+
videoUrl?: string;
|
|
31
|
+
durationMs?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface User {
|
|
34
|
+
id: string;
|
|
35
|
+
username: string;
|
|
36
|
+
name: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
followersCount?: number;
|
|
39
|
+
followingCount?: number;
|
|
40
|
+
isBlueVerified?: boolean;
|
|
41
|
+
profileImageUrl?: string;
|
|
42
|
+
createdAt?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface Cookies {
|
|
45
|
+
authToken: string;
|
|
46
|
+
ct0: string;
|
|
47
|
+
cookieHeader?: string;
|
|
48
|
+
source?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface ClientOptions {
|
|
51
|
+
cookies: Cookies;
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
quoteDepth?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface ApiResult<T> {
|
|
56
|
+
success: boolean;
|
|
57
|
+
error?: string;
|
|
58
|
+
tweets?: Tweet[];
|
|
59
|
+
tweet?: Tweet;
|
|
60
|
+
users?: User[];
|
|
61
|
+
user?: User;
|
|
62
|
+
nextCursor?: string;
|
|
63
|
+
items?: T[];
|
|
64
|
+
}
|
|
65
|
+
export interface TweetResult {
|
|
66
|
+
success: boolean;
|
|
67
|
+
error?: string;
|
|
68
|
+
tweet?: Tweet;
|
|
69
|
+
}
|
|
70
|
+
export interface TweetsResult {
|
|
71
|
+
success: boolean;
|
|
72
|
+
error?: string;
|
|
73
|
+
tweets?: Tweet[];
|
|
74
|
+
nextCursor?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface UserResult {
|
|
77
|
+
success: boolean;
|
|
78
|
+
error?: string;
|
|
79
|
+
userId?: string;
|
|
80
|
+
username?: string;
|
|
81
|
+
name?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface QueryIdCache {
|
|
84
|
+
fetchedAt: string;
|
|
85
|
+
ttlMs: number;
|
|
86
|
+
ids: Record<string, string>;
|
|
87
|
+
discovery: {
|
|
88
|
+
pages: string[];
|
|
89
|
+
bundles: string[];
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA,8BAA8B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* x-reader CLI — Read-only Twitter/X client
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* search <query> Search tweets
|
|
7
|
+
* user-tweets <handle> Get tweets from a user
|
|
8
|
+
* read <tweet-id-or-url> Read a single tweet
|
|
9
|
+
* replies <tweet-id-or-url> Get replies to a tweet
|
|
10
|
+
* bookmarks Get your bookmarks
|
|
11
|
+
* user-lookup <handle> Look up user info
|
|
12
|
+
* query-ids Show/refresh cached query IDs
|
|
13
|
+
* setup Configure authentication
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* x-reader CLI — Read-only Twitter/X client
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* search <query> Search tweets
|
|
7
|
+
* user-tweets <handle> Get tweets from a user
|
|
8
|
+
* read <tweet-id-or-url> Read a single tweet
|
|
9
|
+
* replies <tweet-id-or-url> Get replies to a tweet
|
|
10
|
+
* bookmarks Get your bookmarks
|
|
11
|
+
* user-lookup <handle> Look up user info
|
|
12
|
+
* query-ids Show/refresh cached query IDs
|
|
13
|
+
* setup Configure authentication
|
|
14
|
+
*/
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
import { XReaderClient } from '../api/client.js';
|
|
17
|
+
import { resolveCookies } from '../utils/auth.js';
|
|
18
|
+
import { formatTweets, formatTweet, extractTweetId, normalizeUsername } from '../utils/format.js';
|
|
19
|
+
import { getSnapshotInfo, refreshQueryIds } from '../api/query-ids.js';
|
|
20
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
21
|
+
import { homedir } from 'os';
|
|
22
|
+
import { join } from 'path';
|
|
23
|
+
import { createInterface } from 'readline';
|
|
24
|
+
const VERSION = '0.1.0';
|
|
25
|
+
const program = new Command();
|
|
26
|
+
program
|
|
27
|
+
.name('x-reader')
|
|
28
|
+
.description('Read-only Twitter/X CLI — personal tool for reading tweets')
|
|
29
|
+
.version(VERSION)
|
|
30
|
+
.option('--auth-token <token>', 'Twitter auth_token cookie')
|
|
31
|
+
.option('--ct0 <token>', 'Twitter ct0 cookie')
|
|
32
|
+
.option('--timeout <ms>', 'Request timeout in milliseconds');
|
|
33
|
+
// ─── Helper to create client ──────────────────────────────────
|
|
34
|
+
async function createClient(opts) {
|
|
35
|
+
const { cookies, warnings } = await resolveCookies({
|
|
36
|
+
authToken: opts.authToken,
|
|
37
|
+
ct0: opts.ct0,
|
|
38
|
+
});
|
|
39
|
+
for (const w of warnings) {
|
|
40
|
+
console.error(`⚠️ ${w}`);
|
|
41
|
+
}
|
|
42
|
+
if (!cookies.authToken || !cookies.ct0) {
|
|
43
|
+
console.error('❌ Missing credentials. Run `x-reader setup` or set AUTH_TOKEN and CT0 env vars.');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
return new XReaderClient({
|
|
47
|
+
cookies,
|
|
48
|
+
timeoutMs: opts.timeout ? parseInt(opts.timeout, 10) : undefined,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// ─── search ─────────────────────────────────────────────────────
|
|
52
|
+
program
|
|
53
|
+
.command('search <query>')
|
|
54
|
+
.description('Search for tweets')
|
|
55
|
+
.option('-n, --count <number>', 'Number of tweets', '10')
|
|
56
|
+
.option('--format <type>', 'Output format: json or text', 'text')
|
|
57
|
+
.action(async (query, cmdOpts) => {
|
|
58
|
+
const opts = program.opts();
|
|
59
|
+
const client = await createClient(opts);
|
|
60
|
+
const count = parseInt(cmdOpts.count, 10);
|
|
61
|
+
const result = await client.searchAll(query, count);
|
|
62
|
+
if (!result.success) {
|
|
63
|
+
console.error(`❌ Search failed: ${result.error}`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
const isJson = cmdOpts.format === 'json';
|
|
67
|
+
console.log(formatTweets(result.tweets ?? [], { json: isJson }));
|
|
68
|
+
});
|
|
69
|
+
// ─── user-tweets ────────────────────────────────────────────────
|
|
70
|
+
program
|
|
71
|
+
.command('user-tweets <handle>')
|
|
72
|
+
.description('Get tweets from a user')
|
|
73
|
+
.option('-n, --count <number>', 'Number of tweets', '20')
|
|
74
|
+
.option('--format <type>', 'Output format: json or text', 'text')
|
|
75
|
+
.action(async (handle, cmdOpts) => {
|
|
76
|
+
const opts = program.opts();
|
|
77
|
+
const client = await createClient(opts);
|
|
78
|
+
const username = normalizeUsername(handle);
|
|
79
|
+
const count = parseInt(cmdOpts.count, 10);
|
|
80
|
+
// Look up user ID first
|
|
81
|
+
console.error(`ℹ️ Looking up @${username}...`);
|
|
82
|
+
const user = await client.getUserByUsername(username);
|
|
83
|
+
if (!user.success || !user.userId) {
|
|
84
|
+
console.error(`❌ ${user.error || `User @${username} not found`}`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
console.error(`ℹ️ Fetching tweets from ${user.name} (@${user.username})...`);
|
|
88
|
+
const result = await client.getUserTweetsAll(user.userId, count);
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
console.error(`❌ Failed: ${result.error}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
const isJson = cmdOpts.format === 'json';
|
|
94
|
+
console.log(formatTweets(result.tweets ?? [], { json: isJson, emptyMessage: `No tweets found for @${username}.` }));
|
|
95
|
+
});
|
|
96
|
+
// ─── read ───────────────────────────────────────────────────────
|
|
97
|
+
program
|
|
98
|
+
.command('read <tweet-id-or-url>')
|
|
99
|
+
.description('Read a single tweet')
|
|
100
|
+
.option('--format <type>', 'Output format: json or text', 'text')
|
|
101
|
+
.action(async (input, cmdOpts) => {
|
|
102
|
+
const opts = program.opts();
|
|
103
|
+
const client = await createClient(opts);
|
|
104
|
+
let tweetId;
|
|
105
|
+
try {
|
|
106
|
+
tweetId = extractTweetId(input);
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
console.error(`❌ ${e instanceof Error ? e.message : e}`);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
const result = await client.getTweet(tweetId);
|
|
113
|
+
if (!result.success || !result.tweet) {
|
|
114
|
+
console.error(`❌ ${result.error || 'Tweet not found'}`);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
if (cmdOpts.format === 'json') {
|
|
118
|
+
console.log(JSON.stringify(result.tweet, null, 2));
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
console.log(formatTweet(result.tweet, false));
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
// ─── replies ────────────────────────────────────────────────────
|
|
125
|
+
program
|
|
126
|
+
.command('replies <tweet-id-or-url>')
|
|
127
|
+
.description('Get replies to a tweet')
|
|
128
|
+
.option('--format <type>', 'Output format: json or text', 'text')
|
|
129
|
+
.action(async (input, cmdOpts) => {
|
|
130
|
+
const opts = program.opts();
|
|
131
|
+
const client = await createClient(opts);
|
|
132
|
+
let tweetId;
|
|
133
|
+
try {
|
|
134
|
+
tweetId = extractTweetId(input);
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
console.error(`❌ ${e instanceof Error ? e.message : e}`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
const result = await client.getReplies(tweetId);
|
|
141
|
+
if (!result.success) {
|
|
142
|
+
console.error(`❌ ${result.error || 'Failed to fetch replies'}`);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
const isJson = cmdOpts.format === 'json';
|
|
146
|
+
console.log(formatTweets(result.tweets ?? [], { json: isJson, emptyMessage: 'No replies found.' }));
|
|
147
|
+
});
|
|
148
|
+
// ─── bookmarks ──────────────────────────────────────────────────
|
|
149
|
+
program
|
|
150
|
+
.command('bookmarks')
|
|
151
|
+
.description('Get your bookmarked tweets')
|
|
152
|
+
.option('-n, --count <number>', 'Number of bookmarks', '20')
|
|
153
|
+
.option('--all', 'Fetch all bookmarks')
|
|
154
|
+
.option('--format <type>', 'Output format: json or text', 'text')
|
|
155
|
+
.action(async (cmdOpts) => {
|
|
156
|
+
const opts = program.opts();
|
|
157
|
+
const client = await createClient(opts);
|
|
158
|
+
const count = cmdOpts.all ? Infinity : parseInt(cmdOpts.count, 10);
|
|
159
|
+
const result = await client.getBookmarksAll(count);
|
|
160
|
+
if (!result.success) {
|
|
161
|
+
console.error(`❌ ${result.error || 'Failed to fetch bookmarks'}`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
const isJson = cmdOpts.format === 'json';
|
|
165
|
+
console.log(formatTweets(result.tweets ?? [], { json: isJson, emptyMessage: 'No bookmarks found.' }));
|
|
166
|
+
});
|
|
167
|
+
// ─── user-lookup ────────────────────────────────────────────────
|
|
168
|
+
program
|
|
169
|
+
.command('user-lookup <handle>')
|
|
170
|
+
.description('Look up user information')
|
|
171
|
+
.option('--format <type>', 'Output format: json or text', 'text')
|
|
172
|
+
.action(async (handle, cmdOpts) => {
|
|
173
|
+
const opts = program.opts();
|
|
174
|
+
const client = await createClient(opts);
|
|
175
|
+
const username = normalizeUsername(handle);
|
|
176
|
+
const result = await client.getUserByUsername(username);
|
|
177
|
+
if (!result.success) {
|
|
178
|
+
console.error(`❌ ${result.error || `User @${username} not found`}`);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
if (cmdOpts.format === 'json') {
|
|
182
|
+
console.log(JSON.stringify(result, null, 2));
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
console.log(`👤 @${result.username} (${result.name})`);
|
|
186
|
+
console.log(`🆔 User ID: ${result.userId}`);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
// ─── query-ids ──────────────────────────────────────────────────
|
|
190
|
+
program
|
|
191
|
+
.command('query-ids')
|
|
192
|
+
.description('Show or refresh cached query IDs')
|
|
193
|
+
.option('--refresh', 'Force refresh from x.com')
|
|
194
|
+
.option('--format <type>', 'Output format: json or text', 'text')
|
|
195
|
+
.action(async (cmdOpts) => {
|
|
196
|
+
if (cmdOpts.refresh) {
|
|
197
|
+
console.error('ℹ️ Refreshing query IDs from x.com JS bundles...');
|
|
198
|
+
await refreshQueryIds({ force: true });
|
|
199
|
+
console.error('✅ Done.');
|
|
200
|
+
}
|
|
201
|
+
const info = await getSnapshotInfo();
|
|
202
|
+
if (!info) {
|
|
203
|
+
console.error('⚠️ No cached query IDs. Run: x-reader query-ids --refresh');
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (cmdOpts.format === 'json') {
|
|
207
|
+
console.log(JSON.stringify({
|
|
208
|
+
cachePath: info.cachePath,
|
|
209
|
+
fetchedAt: info.snapshot.fetchedAt,
|
|
210
|
+
isFresh: info.isFresh,
|
|
211
|
+
ageMs: info.ageMs,
|
|
212
|
+
ids: info.snapshot.ids,
|
|
213
|
+
}, null, 2));
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
console.log(`✅ Query IDs cached`);
|
|
217
|
+
console.log(`📁 Path: ${info.cachePath}`);
|
|
218
|
+
console.log(`📅 Fetched: ${info.snapshot.fetchedAt}`);
|
|
219
|
+
console.log(`🟢 Fresh: ${info.isFresh ? 'yes' : 'no'}`);
|
|
220
|
+
console.log(`📊 Operations: ${Object.keys(info.snapshot.ids).length}`);
|
|
221
|
+
console.log('');
|
|
222
|
+
for (const [op, qid] of Object.entries(info.snapshot.ids)) {
|
|
223
|
+
console.log(` ${op}: ${qid}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
// ─── setup ──────────────────────────────────────────────────────
|
|
228
|
+
program
|
|
229
|
+
.command('setup')
|
|
230
|
+
.description('Configure x-reader authentication')
|
|
231
|
+
.action(async () => {
|
|
232
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
233
|
+
const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
234
|
+
console.log('🔧 x-reader setup');
|
|
235
|
+
console.log('');
|
|
236
|
+
console.log('You need two cookies from x.com:');
|
|
237
|
+
console.log('1. Open x.com in your browser and log in');
|
|
238
|
+
console.log('2. Open DevTools → Application → Cookies → x.com');
|
|
239
|
+
console.log('3. Copy the values of auth_token and ct0');
|
|
240
|
+
console.log('');
|
|
241
|
+
const authToken = await ask('auth_token: ');
|
|
242
|
+
const ct0 = await ask('ct0: ');
|
|
243
|
+
rl.close();
|
|
244
|
+
if (!authToken.trim() || !ct0.trim()) {
|
|
245
|
+
console.error('❌ Both values are required.');
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
const configDir = join(homedir(), '.config', 'x-reader');
|
|
249
|
+
const configFile = join(configDir, 'config.json');
|
|
250
|
+
await mkdir(configDir, { recursive: true });
|
|
251
|
+
await writeFile(configFile, JSON.stringify({ auth_token: authToken.trim(), ct0: ct0.trim() }, null, 2) + '\n', 'utf8');
|
|
252
|
+
console.log(`✅ Config saved to ${configFile}`);
|
|
253
|
+
console.log('');
|
|
254
|
+
console.log('Test it: x-reader search "hello"');
|
|
255
|
+
});
|
|
256
|
+
// ─── Parse and run ──────────────────────────────────────────────
|
|
257
|
+
program.parse();
|
|
258
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** x-reader — Read-only Twitter/X API client */
|
|
2
|
+
export { XReaderClient } from './api/client.js';
|
|
3
|
+
export type { Tweet, TweetMedia, User, Cookies, ClientOptions, TweetResult, TweetsResult, UserResult, } from './api/types.js';
|
|
4
|
+
export { resolveCookies } from './utils/auth.js';
|
|
5
|
+
export { formatTweets, formatTweet, extractTweetId } from './utils/format.js';
|
|
6
|
+
export { getQueryId, refreshQueryIds, getSnapshotInfo } from './api/query-ids.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** x-reader — Read-only Twitter/X API client */
|
|
2
|
+
export { XReaderClient } from './api/client.js';
|
|
3
|
+
export { resolveCookies } from './utils/auth.js';
|
|
4
|
+
export { formatTweets, formatTweet, extractTweetId } from './utils/format.js';
|
|
5
|
+
export { getQueryId, refreshQueryIds, getSnapshotInfo } from './api/query-ids.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAWhD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication utilities — resolve cookies from Chrome, env, or config file.
|
|
3
|
+
*/
|
|
4
|
+
import type { Cookies } from '../api/types.js';
|
|
5
|
+
interface ResolvedCookies {
|
|
6
|
+
cookies: Cookies;
|
|
7
|
+
warnings: string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolve cookies from all sources. Priority:
|
|
11
|
+
* 1. CLI flags (--auth-token, --ct0)
|
|
12
|
+
* 2. Environment variables (AUTH_TOKEN, CT0)
|
|
13
|
+
* 3. x-reader config file
|
|
14
|
+
* 4. Bird CLI config file (migration)
|
|
15
|
+
* 5. Chrome cookies (macOS only)
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveCookies(flags?: {
|
|
18
|
+
authToken?: string;
|
|
19
|
+
ct0?: string;
|
|
20
|
+
}): Promise<ResolvedCookies>;
|
|
21
|
+
export {};
|