@antcoder/birdxtwittercli 0.8.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.
Files changed (214) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/LICENSE +21 -0
  3. package/README.md +388 -0
  4. package/dist/cli/pagination.d.ts +35 -0
  5. package/dist/cli/pagination.d.ts.map +1 -0
  6. package/dist/cli/pagination.js +43 -0
  7. package/dist/cli/pagination.js.map +1 -0
  8. package/dist/cli/program.d.ts +5 -0
  9. package/dist/cli/program.d.ts.map +1 -0
  10. package/dist/cli/program.js +113 -0
  11. package/dist/cli/program.js.map +1 -0
  12. package/dist/cli/shared.d.ts +77 -0
  13. package/dist/cli/shared.d.ts.map +1 -0
  14. package/dist/cli/shared.js +327 -0
  15. package/dist/cli/shared.js.map +1 -0
  16. package/dist/cli.d.ts +12 -0
  17. package/dist/cli.d.ts.map +1 -0
  18. package/dist/cli.js +29 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/commands/bookmarks.d.ts +4 -0
  21. package/dist/commands/bookmarks.d.ts.map +1 -0
  22. package/dist/commands/bookmarks.js +189 -0
  23. package/dist/commands/bookmarks.js.map +1 -0
  24. package/dist/commands/check.d.ts +4 -0
  25. package/dist/commands/check.d.ts.map +1 -0
  26. package/dist/commands/check.js +43 -0
  27. package/dist/commands/check.js.map +1 -0
  28. package/dist/commands/follow.d.ts +4 -0
  29. package/dist/commands/follow.d.ts.map +1 -0
  30. package/dist/commands/follow.js +91 -0
  31. package/dist/commands/follow.js.map +1 -0
  32. package/dist/commands/help.d.ts +4 -0
  33. package/dist/commands/help.d.ts.map +1 -0
  34. package/dist/commands/help.js +19 -0
  35. package/dist/commands/help.js.map +1 -0
  36. package/dist/commands/home.d.ts +4 -0
  37. package/dist/commands/home.d.ts.map +1 -0
  38. package/dist/commands/home.js +43 -0
  39. package/dist/commands/home.js.map +1 -0
  40. package/dist/commands/lists.d.ts +4 -0
  41. package/dist/commands/lists.d.ts.map +1 -0
  42. package/dist/commands/lists.js +213 -0
  43. package/dist/commands/lists.js.map +1 -0
  44. package/dist/commands/news.d.ts +4 -0
  45. package/dist/commands/news.d.ts.map +1 -0
  46. package/dist/commands/news.js +131 -0
  47. package/dist/commands/news.js.map +1 -0
  48. package/dist/commands/post.d.ts +4 -0
  49. package/dist/commands/post.d.ts.map +1 -0
  50. package/dist/commands/post.js +101 -0
  51. package/dist/commands/post.js.map +1 -0
  52. package/dist/commands/query-ids.d.ts +4 -0
  53. package/dist/commands/query-ids.d.ts.map +1 -0
  54. package/dist/commands/query-ids.js +80 -0
  55. package/dist/commands/query-ids.js.map +1 -0
  56. package/dist/commands/read.d.ts +4 -0
  57. package/dist/commands/read.d.ts.map +1 -0
  58. package/dist/commands/read.js +152 -0
  59. package/dist/commands/read.js.map +1 -0
  60. package/dist/commands/search.d.ts +4 -0
  61. package/dist/commands/search.d.ts.map +1 -0
  62. package/dist/commands/search.js +115 -0
  63. package/dist/commands/search.js.map +1 -0
  64. package/dist/commands/unbookmark.d.ts +4 -0
  65. package/dist/commands/unbookmark.d.ts.map +1 -0
  66. package/dist/commands/unbookmark.js +36 -0
  67. package/dist/commands/unbookmark.js.map +1 -0
  68. package/dist/commands/user-tweets.d.ts +4 -0
  69. package/dist/commands/user-tweets.d.ts.map +1 -0
  70. package/dist/commands/user-tweets.js +109 -0
  71. package/dist/commands/user-tweets.js.map +1 -0
  72. package/dist/commands/users.d.ts +4 -0
  73. package/dist/commands/users.d.ts.map +1 -0
  74. package/dist/commands/users.js +295 -0
  75. package/dist/commands/users.js.map +1 -0
  76. package/dist/index.d.ts +2 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +2 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/lib/cli-args.d.ts +7 -0
  81. package/dist/lib/cli-args.d.ts.map +1 -0
  82. package/dist/lib/cli-args.js +25 -0
  83. package/dist/lib/cli-args.js.map +1 -0
  84. package/dist/lib/cookies.d.ts +31 -0
  85. package/dist/lib/cookies.d.ts.map +1 -0
  86. package/dist/lib/cookies.js +173 -0
  87. package/dist/lib/cookies.js.map +1 -0
  88. package/dist/lib/extract-bookmark-folder-id.d.ts +2 -0
  89. package/dist/lib/extract-bookmark-folder-id.d.ts.map +1 -0
  90. package/dist/lib/extract-bookmark-folder-id.js +20 -0
  91. package/dist/lib/extract-bookmark-folder-id.js.map +1 -0
  92. package/dist/lib/extract-list-id.d.ts +2 -0
  93. package/dist/lib/extract-list-id.d.ts.map +1 -0
  94. package/dist/lib/extract-list-id.js +19 -0
  95. package/dist/lib/extract-list-id.js.map +1 -0
  96. package/dist/lib/extract-tweet-id.d.ts +2 -0
  97. package/dist/lib/extract-tweet-id.d.ts.map +1 -0
  98. package/dist/lib/extract-tweet-id.js +14 -0
  99. package/dist/lib/extract-tweet-id.js.map +1 -0
  100. package/dist/lib/features.json +17 -0
  101. package/dist/lib/index.d.ts +10 -0
  102. package/dist/lib/index.d.ts.map +1 -0
  103. package/dist/lib/index.js +4 -0
  104. package/dist/lib/index.js.map +1 -0
  105. package/dist/lib/normalize-handle.d.ts +6 -0
  106. package/dist/lib/normalize-handle.d.ts.map +1 -0
  107. package/dist/lib/normalize-handle.js +31 -0
  108. package/dist/lib/normalize-handle.js.map +1 -0
  109. package/dist/lib/output.d.ts +29 -0
  110. package/dist/lib/output.d.ts.map +1 -0
  111. package/dist/lib/output.js +88 -0
  112. package/dist/lib/output.js.map +1 -0
  113. package/dist/lib/paginate-cursor.d.ts +27 -0
  114. package/dist/lib/paginate-cursor.d.ts.map +1 -0
  115. package/dist/lib/paginate-cursor.js +37 -0
  116. package/dist/lib/paginate-cursor.js.map +1 -0
  117. package/dist/lib/query-ids.json +20 -0
  118. package/dist/lib/runtime-features.d.ts +19 -0
  119. package/dist/lib/runtime-features.d.ts.map +1 -0
  120. package/dist/lib/runtime-features.js +151 -0
  121. package/dist/lib/runtime-features.js.map +1 -0
  122. package/dist/lib/runtime-query-ids.d.ts +33 -0
  123. package/dist/lib/runtime-query-ids.d.ts.map +1 -0
  124. package/dist/lib/runtime-query-ids.js +264 -0
  125. package/dist/lib/runtime-query-ids.js.map +1 -0
  126. package/dist/lib/thread-filters.d.ts +8 -0
  127. package/dist/lib/thread-filters.d.ts.map +1 -0
  128. package/dist/lib/thread-filters.js +124 -0
  129. package/dist/lib/thread-filters.js.map +1 -0
  130. package/dist/lib/twitter-client-base.d.ts +38 -0
  131. package/dist/lib/twitter-client-base.d.ts.map +1 -0
  132. package/dist/lib/twitter-client-base.js +129 -0
  133. package/dist/lib/twitter-client-base.js.map +1 -0
  134. package/dist/lib/twitter-client-bookmarks.d.ts +7 -0
  135. package/dist/lib/twitter-client-bookmarks.d.ts.map +1 -0
  136. package/dist/lib/twitter-client-bookmarks.js +61 -0
  137. package/dist/lib/twitter-client-bookmarks.js.map +1 -0
  138. package/dist/lib/twitter-client-constants.d.ts +44 -0
  139. package/dist/lib/twitter-client-constants.d.ts.map +1 -0
  140. package/dist/lib/twitter-client-constants.js +51 -0
  141. package/dist/lib/twitter-client-constants.js.map +1 -0
  142. package/dist/lib/twitter-client-engagement.d.ts +16 -0
  143. package/dist/lib/twitter-client-engagement.d.ts.map +1 -0
  144. package/dist/lib/twitter-client-engagement.js +81 -0
  145. package/dist/lib/twitter-client-engagement.js.map +1 -0
  146. package/dist/lib/twitter-client-features.d.ts +14 -0
  147. package/dist/lib/twitter-client-features.d.ts.map +1 -0
  148. package/dist/lib/twitter-client-features.js +347 -0
  149. package/dist/lib/twitter-client-features.js.map +1 -0
  150. package/dist/lib/twitter-client-follow.d.ts +8 -0
  151. package/dist/lib/twitter-client-follow.d.ts.map +1 -0
  152. package/dist/lib/twitter-client-follow.js +178 -0
  153. package/dist/lib/twitter-client-follow.js.map +1 -0
  154. package/dist/lib/twitter-client-home.d.ts +13 -0
  155. package/dist/lib/twitter-client-home.d.ts.map +1 -0
  156. package/dist/lib/twitter-client-home.js +138 -0
  157. package/dist/lib/twitter-client-home.js.map +1 -0
  158. package/dist/lib/twitter-client-lists.d.ts +12 -0
  159. package/dist/lib/twitter-client-lists.d.ts.map +1 -0
  160. package/dist/lib/twitter-client-lists.js +390 -0
  161. package/dist/lib/twitter-client-lists.js.map +1 -0
  162. package/dist/lib/twitter-client-media.d.ts +11 -0
  163. package/dist/lib/twitter-client-media.d.ts.map +1 -0
  164. package/dist/lib/twitter-client-media.js +136 -0
  165. package/dist/lib/twitter-client-media.js.map +1 -0
  166. package/dist/lib/twitter-client-news.d.ts +47 -0
  167. package/dist/lib/twitter-client-news.d.ts.map +1 -0
  168. package/dist/lib/twitter-client-news.js +283 -0
  169. package/dist/lib/twitter-client-news.js.map +1 -0
  170. package/dist/lib/twitter-client-posting.d.ts +8 -0
  171. package/dist/lib/twitter-client-posting.d.ts.map +1 -0
  172. package/dist/lib/twitter-client-posting.js +218 -0
  173. package/dist/lib/twitter-client-posting.js.map +1 -0
  174. package/dist/lib/twitter-client-search.d.ts +19 -0
  175. package/dist/lib/twitter-client-search.d.ts.map +1 -0
  176. package/dist/lib/twitter-client-search.js +157 -0
  177. package/dist/lib/twitter-client-search.js.map +1 -0
  178. package/dist/lib/twitter-client-timelines.d.ts +23 -0
  179. package/dist/lib/twitter-client-timelines.d.ts.map +1 -0
  180. package/dist/lib/twitter-client-timelines.js +471 -0
  181. package/dist/lib/twitter-client-timelines.js.map +1 -0
  182. package/dist/lib/twitter-client-tweet-detail.d.ts +25 -0
  183. package/dist/lib/twitter-client-tweet-detail.d.ts.map +1 -0
  184. package/dist/lib/twitter-client-tweet-detail.js +295 -0
  185. package/dist/lib/twitter-client-tweet-detail.js.map +1 -0
  186. package/dist/lib/twitter-client-types.d.ts +407 -0
  187. package/dist/lib/twitter-client-types.d.ts.map +1 -0
  188. package/dist/lib/twitter-client-types.js +2 -0
  189. package/dist/lib/twitter-client-types.js.map +1 -0
  190. package/dist/lib/twitter-client-user-lookup.d.ts +16 -0
  191. package/dist/lib/twitter-client-user-lookup.d.ts.map +1 -0
  192. package/dist/lib/twitter-client-user-lookup.js +224 -0
  193. package/dist/lib/twitter-client-user-lookup.js.map +1 -0
  194. package/dist/lib/twitter-client-user-tweets.d.ts +22 -0
  195. package/dist/lib/twitter-client-user-tweets.d.ts.map +1 -0
  196. package/dist/lib/twitter-client-user-tweets.js +154 -0
  197. package/dist/lib/twitter-client-user-tweets.js.map +1 -0
  198. package/dist/lib/twitter-client-users.d.ts +9 -0
  199. package/dist/lib/twitter-client-users.d.ts.map +1 -0
  200. package/dist/lib/twitter-client-users.js +358 -0
  201. package/dist/lib/twitter-client-users.js.map +1 -0
  202. package/dist/lib/twitter-client-utils.d.ts +173 -0
  203. package/dist/lib/twitter-client-utils.d.ts.map +1 -0
  204. package/dist/lib/twitter-client-utils.js +511 -0
  205. package/dist/lib/twitter-client-utils.js.map +1 -0
  206. package/dist/lib/twitter-client.d.ts +23 -0
  207. package/dist/lib/twitter-client.d.ts.map +1 -0
  208. package/dist/lib/twitter-client.js +21 -0
  209. package/dist/lib/twitter-client.js.map +1 -0
  210. package/dist/lib/version.d.ts +6 -0
  211. package/dist/lib/version.d.ts.map +1 -0
  212. package/dist/lib/version.js +174 -0
  213. package/dist/lib/version.js.map +1 -0
  214. package/package.json +61 -0
@@ -0,0 +1,264 @@
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import path from 'node:path';
4
+ const DEFAULT_CACHE_FILENAME = 'query-ids-cache.json';
5
+ const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
6
+ const DISCOVERY_PAGES = [
7
+ 'https://x.com/?lang=en',
8
+ 'https://x.com/explore',
9
+ 'https://x.com/notifications',
10
+ 'https://x.com/settings/profile',
11
+ ];
12
+ const BUNDLE_URL_REGEX = /https:\/\/abs\.twimg\.com\/responsive-web\/client-web(?:-legacy)?\/[A-Za-z0-9.-]+\.js/g;
13
+ const QUERY_ID_REGEX = /^[a-zA-Z0-9_-]+$/;
14
+ const OPERATION_PATTERNS = [
15
+ {
16
+ regex: /e\.exports=\{queryId\s*:\s*["']([^"']+)["']\s*,\s*operationName\s*:\s*["']([^"']+)["']/gs,
17
+ operationGroup: 2,
18
+ queryIdGroup: 1,
19
+ },
20
+ {
21
+ regex: /e\.exports=\{operationName\s*:\s*["']([^"']+)["']\s*,\s*queryId\s*:\s*["']([^"']+)["']/gs,
22
+ operationGroup: 1,
23
+ queryIdGroup: 2,
24
+ },
25
+ {
26
+ regex: /operationName\s*[:=]\s*["']([^"']+)["'](.{0,4000}?)queryId\s*[:=]\s*["']([^"']+)["']/gs,
27
+ operationGroup: 1,
28
+ queryIdGroup: 3,
29
+ },
30
+ {
31
+ regex: /queryId\s*[:=]\s*["']([^"']+)["'](.{0,4000}?)operationName\s*[:=]\s*["']([^"']+)["']/gs,
32
+ operationGroup: 3,
33
+ queryIdGroup: 1,
34
+ },
35
+ ];
36
+ const HEADERS = {
37
+ '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',
38
+ Accept: 'text/html,application/json;q=0.9,*/*;q=0.8',
39
+ 'Accept-Language': 'en-US,en;q=0.9',
40
+ };
41
+ async function fetchText(fetchImpl, url) {
42
+ const response = await fetchImpl(url, { headers: HEADERS });
43
+ if (!response.ok) {
44
+ const body = await response.text().catch(() => '');
45
+ throw new Error(`HTTP ${response.status} for ${url}: ${body.slice(0, 120)}`);
46
+ }
47
+ return response.text();
48
+ }
49
+ function resolveDefaultCachePath() {
50
+ const override = process.env.BIRD_QUERY_IDS_CACHE;
51
+ if (override && override.trim().length > 0) {
52
+ return path.resolve(override.trim());
53
+ }
54
+ return path.join(homedir(), '.config', 'bird', DEFAULT_CACHE_FILENAME);
55
+ }
56
+ function parseSnapshot(raw) {
57
+ if (!raw || typeof raw !== 'object') {
58
+ return null;
59
+ }
60
+ const record = raw;
61
+ const fetchedAt = typeof record.fetchedAt === 'string' ? record.fetchedAt : null;
62
+ const ttlMs = typeof record.ttlMs === 'number' && Number.isFinite(record.ttlMs) ? record.ttlMs : null;
63
+ const ids = record.ids && typeof record.ids === 'object' ? record.ids : null;
64
+ const discovery = record.discovery && typeof record.discovery === 'object' ? record.discovery : null;
65
+ if (!fetchedAt || !ttlMs || !ids || !discovery) {
66
+ return null;
67
+ }
68
+ const pages = Array.isArray(discovery.pages) ? discovery.pages : null;
69
+ const bundles = Array.isArray(discovery.bundles) ? discovery.bundles : null;
70
+ if (!pages || !bundles) {
71
+ return null;
72
+ }
73
+ const normalizedIds = {};
74
+ for (const [key, value] of Object.entries(ids)) {
75
+ if (typeof value === 'string' && value.trim().length > 0) {
76
+ normalizedIds[key] = value.trim();
77
+ }
78
+ }
79
+ return {
80
+ fetchedAt,
81
+ ttlMs,
82
+ ids: normalizedIds,
83
+ discovery: {
84
+ pages: pages.filter((p) => typeof p === 'string'),
85
+ bundles: bundles.filter((b) => typeof b === 'string'),
86
+ },
87
+ };
88
+ }
89
+ async function readSnapshotFromDisk(cachePath) {
90
+ try {
91
+ const raw = await readFile(cachePath, 'utf8');
92
+ return parseSnapshot(JSON.parse(raw));
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ async function writeSnapshotToDisk(cachePath, snapshot) {
99
+ await mkdir(path.dirname(cachePath), { recursive: true });
100
+ await writeFile(cachePath, `${JSON.stringify(snapshot, null, 2)}\n`, 'utf8');
101
+ }
102
+ async function discoverBundles(fetchImpl) {
103
+ const bundles = new Set();
104
+ for (const page of DISCOVERY_PAGES) {
105
+ try {
106
+ const html = await fetchText(fetchImpl, page);
107
+ for (const match of html.matchAll(BUNDLE_URL_REGEX)) {
108
+ bundles.add(match[0]);
109
+ }
110
+ }
111
+ catch {
112
+ // ignore discovery page failures; other pages often work
113
+ }
114
+ }
115
+ const discovered = [...bundles];
116
+ if (discovered.length === 0) {
117
+ throw new Error('No client bundles discovered; x.com layout may have changed.');
118
+ }
119
+ return discovered;
120
+ }
121
+ function extractOperations(bundleContents, bundleLabel, targets, discovered) {
122
+ for (const pattern of OPERATION_PATTERNS) {
123
+ pattern.regex.lastIndex = 0;
124
+ while (true) {
125
+ const match = pattern.regex.exec(bundleContents);
126
+ if (match === null) {
127
+ break;
128
+ }
129
+ const operationName = match[pattern.operationGroup];
130
+ const queryId = match[pattern.queryIdGroup];
131
+ if (!operationName || !queryId) {
132
+ continue;
133
+ }
134
+ if (!targets.has(operationName)) {
135
+ continue;
136
+ }
137
+ if (!QUERY_ID_REGEX.test(queryId)) {
138
+ continue;
139
+ }
140
+ if (discovered.has(operationName)) {
141
+ continue;
142
+ }
143
+ discovered.set(operationName, { queryId, bundle: bundleLabel });
144
+ if (discovered.size === targets.size) {
145
+ return;
146
+ }
147
+ }
148
+ }
149
+ }
150
+ async function fetchAndExtract(fetchImpl, bundleUrls, targets) {
151
+ const discovered = new Map();
152
+ const CONCURRENCY = 6;
153
+ for (let i = 0; i < bundleUrls.length; i += CONCURRENCY) {
154
+ const chunk = bundleUrls.slice(i, i + CONCURRENCY);
155
+ await Promise.all(chunk.map(async (url) => {
156
+ if (discovered.size === targets.size) {
157
+ return;
158
+ }
159
+ const label = url.split('/').at(-1) ?? url;
160
+ try {
161
+ const js = await fetchText(fetchImpl, url);
162
+ extractOperations(js, label, targets, discovered);
163
+ }
164
+ catch {
165
+ // ignore failed bundles
166
+ }
167
+ }));
168
+ if (discovered.size === targets.size) {
169
+ break;
170
+ }
171
+ }
172
+ return discovered;
173
+ }
174
+ export function createRuntimeQueryIdStore(options = {}) {
175
+ const fetchImpl = options.fetchImpl ?? fetch;
176
+ const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
177
+ const cachePath = options.cachePath ? path.resolve(options.cachePath) : resolveDefaultCachePath();
178
+ let memorySnapshot = null;
179
+ let loadOnce = null;
180
+ let refreshInFlight = null;
181
+ const loadSnapshot = async () => {
182
+ if (memorySnapshot) {
183
+ return memorySnapshot;
184
+ }
185
+ if (!loadOnce) {
186
+ loadOnce = (async () => {
187
+ const fromDisk = await readSnapshotFromDisk(cachePath);
188
+ memorySnapshot = fromDisk;
189
+ return fromDisk;
190
+ })();
191
+ }
192
+ return loadOnce;
193
+ };
194
+ const getSnapshotInfo = async () => {
195
+ const snapshot = await loadSnapshot();
196
+ if (!snapshot) {
197
+ return null;
198
+ }
199
+ const fetchedAtMs = new Date(snapshot.fetchedAt).getTime();
200
+ const ageMs = Number.isFinite(fetchedAtMs) ? Math.max(0, Date.now() - fetchedAtMs) : Number.POSITIVE_INFINITY;
201
+ const effectiveTtl = Number.isFinite(snapshot.ttlMs) ? snapshot.ttlMs : ttlMs;
202
+ const isFresh = ageMs <= effectiveTtl;
203
+ return { snapshot, cachePath, ageMs, isFresh };
204
+ };
205
+ const getQueryId = async (operationName) => {
206
+ const info = await getSnapshotInfo();
207
+ if (!info) {
208
+ return null;
209
+ }
210
+ return info.snapshot.ids[operationName] ?? null;
211
+ };
212
+ const refresh = async (operationNames, opts = {}) => {
213
+ if (refreshInFlight) {
214
+ return refreshInFlight;
215
+ }
216
+ refreshInFlight = (async () => {
217
+ const current = await getSnapshotInfo();
218
+ if (!opts.force && current?.isFresh) {
219
+ return current;
220
+ }
221
+ const targets = new Set(operationNames);
222
+ const bundleUrls = await discoverBundles(fetchImpl);
223
+ const discovered = await fetchAndExtract(fetchImpl, bundleUrls, targets);
224
+ if (discovered.size === 0) {
225
+ return current ?? null;
226
+ }
227
+ const ids = {};
228
+ for (const name of operationNames) {
229
+ const entry = discovered.get(name);
230
+ if (entry?.queryId) {
231
+ ids[name] = entry.queryId;
232
+ }
233
+ }
234
+ const snapshot = {
235
+ fetchedAt: new Date().toISOString(),
236
+ ttlMs,
237
+ ids,
238
+ discovery: {
239
+ pages: [...DISCOVERY_PAGES],
240
+ bundles: bundleUrls.map((url) => url.split('/').at(-1) ?? url),
241
+ },
242
+ };
243
+ await writeSnapshotToDisk(cachePath, snapshot);
244
+ memorySnapshot = snapshot;
245
+ return getSnapshotInfo();
246
+ })().finally(() => {
247
+ refreshInFlight = null;
248
+ });
249
+ return refreshInFlight;
250
+ };
251
+ return {
252
+ cachePath,
253
+ ttlMs,
254
+ getSnapshotInfo,
255
+ getQueryId,
256
+ refresh,
257
+ clearMemory() {
258
+ memorySnapshot = null;
259
+ loadOnce = null;
260
+ },
261
+ };
262
+ }
263
+ export const runtimeQueryIds = createRuntimeQueryIdStore();
264
+ //# sourceMappingURL=runtime-query-ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-query-ids.js","sourceRoot":"","sources":["../../src/lib/runtime-query-ids.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { TweetData, TweetWithMeta } from './twitter-client-types.js';
2
+ export declare function filterAuthorChain(tweets: TweetData[], bookmarkedTweet: TweetData): TweetData[];
3
+ export declare function filterAuthorOnly(tweets: TweetData[], bookmarkedTweet: TweetData): TweetData[];
4
+ export declare function filterFullChain(tweets: TweetData[], bookmarkedTweet: TweetData, options?: {
5
+ includeAncestorBranches?: boolean;
6
+ }): TweetData[];
7
+ export declare function addThreadMetadata(tweet: TweetData, allConversationTweets: TweetData[]): TweetWithMeta;
8
+ //# sourceMappingURL=thread-filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-filters.d.ts","sourceRoot":"","sources":["../../src/lib/thread-filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAS1E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,eAAe,EAAE,SAAS,GAAG,SAAS,EAAE,CAqC9F;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,eAAe,EAAE,SAAS,GAAG,SAAS,EAAE,CAG7F;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EAAE,EACnB,eAAe,EAAE,SAAS,EAC1B,OAAO,GAAE;IAAE,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAAO,GAClD,SAAS,EAAE,CA4Db;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,SAAS,EAAE,GAAG,aAAa,CA0BrG"}
@@ -0,0 +1,124 @@
1
+ const sortByCreatedAt = (tweets) => tweets.slice().sort((a, b) => {
2
+ const aTime = a.createdAt ? Date.parse(a.createdAt) : 0;
3
+ const bTime = b.createdAt ? Date.parse(b.createdAt) : 0;
4
+ return aTime - bTime;
5
+ });
6
+ export function filterAuthorChain(tweets, bookmarkedTweet) {
7
+ const author = bookmarkedTweet.author.username;
8
+ const byId = new Map(tweets.map((tweet) => [tweet.id, tweet]));
9
+ const chainIds = new Set();
10
+ let current = bookmarkedTweet;
11
+ while (current && current.author.username === author) {
12
+ chainIds.add(current.id);
13
+ const parentId = current.inReplyToStatusId;
14
+ if (!parentId) {
15
+ break;
16
+ }
17
+ const parent = byId.get(parentId);
18
+ if (!parent || parent.author.username !== author) {
19
+ break;
20
+ }
21
+ current = parent;
22
+ }
23
+ let changed = true;
24
+ while (changed) {
25
+ changed = false;
26
+ for (const tweet of tweets) {
27
+ if (tweet.author.username !== author) {
28
+ continue;
29
+ }
30
+ if (chainIds.has(tweet.id)) {
31
+ continue;
32
+ }
33
+ if (tweet.inReplyToStatusId && chainIds.has(tweet.inReplyToStatusId)) {
34
+ chainIds.add(tweet.id);
35
+ changed = true;
36
+ }
37
+ }
38
+ }
39
+ return sortByCreatedAt(tweets.filter((tweet) => chainIds.has(tweet.id)));
40
+ }
41
+ export function filterAuthorOnly(tweets, bookmarkedTweet) {
42
+ const author = bookmarkedTweet.author.username;
43
+ return tweets.filter((tweet) => tweet.author.username === author);
44
+ }
45
+ export function filterFullChain(tweets, bookmarkedTweet, options = {}) {
46
+ const byId = new Map(tweets.map((tweet) => [tweet.id, tweet]));
47
+ const repliesByParent = new Map();
48
+ for (const tweet of tweets) {
49
+ if (!tweet.inReplyToStatusId) {
50
+ continue;
51
+ }
52
+ const list = repliesByParent.get(tweet.inReplyToStatusId) ?? [];
53
+ list.push(tweet);
54
+ repliesByParent.set(tweet.inReplyToStatusId, list);
55
+ }
56
+ const chainIds = new Set();
57
+ const ancestorIds = [];
58
+ chainIds.add(bookmarkedTweet.id);
59
+ let current = bookmarkedTweet;
60
+ while (current?.inReplyToStatusId) {
61
+ const parent = byId.get(current.inReplyToStatusId);
62
+ if (!parent) {
63
+ break;
64
+ }
65
+ if (!chainIds.has(parent.id)) {
66
+ chainIds.add(parent.id);
67
+ ancestorIds.push(parent.id);
68
+ }
69
+ current = parent;
70
+ }
71
+ const addDescendants = (startIds) => {
72
+ const queue = [...startIds];
73
+ while (queue.length > 0) {
74
+ const currentId = queue.shift();
75
+ if (!currentId) {
76
+ continue;
77
+ }
78
+ if (!chainIds.has(currentId)) {
79
+ chainIds.add(currentId);
80
+ }
81
+ const replies = repliesByParent.get(currentId) ?? [];
82
+ for (const reply of replies) {
83
+ if (chainIds.has(reply.id)) {
84
+ continue;
85
+ }
86
+ chainIds.add(reply.id);
87
+ queue.push(reply.id);
88
+ }
89
+ }
90
+ };
91
+ addDescendants([bookmarkedTweet.id]);
92
+ if (options.includeAncestorBranches) {
93
+ for (const ancestorId of ancestorIds) {
94
+ addDescendants([ancestorId]);
95
+ }
96
+ }
97
+ return sortByCreatedAt(tweets.filter((tweet) => chainIds.has(tweet.id)));
98
+ }
99
+ export function addThreadMetadata(tweet, allConversationTweets) {
100
+ const author = tweet.author.username;
101
+ const hasSelfReplies = allConversationTweets.some((candidate) => candidate.inReplyToStatusId === tweet.id && candidate.author.username === author);
102
+ const isRoot = !tweet.inReplyToStatusId;
103
+ let threadPosition;
104
+ if (isRoot && !hasSelfReplies) {
105
+ threadPosition = 'standalone';
106
+ }
107
+ else if (isRoot && hasSelfReplies) {
108
+ threadPosition = 'root';
109
+ }
110
+ else if (!isRoot && hasSelfReplies) {
111
+ threadPosition = 'middle';
112
+ }
113
+ else {
114
+ threadPosition = 'end';
115
+ }
116
+ return {
117
+ ...tweet,
118
+ isThread: hasSelfReplies || !isRoot,
119
+ threadPosition,
120
+ hasSelfReplies,
121
+ threadRootId: tweet.conversationId ?? null,
122
+ };
123
+ }
124
+ //# sourceMappingURL=thread-filters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-filters.js","sourceRoot":"","sources":["../../src/lib/thread-filters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { type OperationName } from './twitter-client-constants.js';
2
+ import type { CurrentUserResult, TwitterClientOptions } from './twitter-client-types.js';
3
+ export type Constructor<T = object> = new (...args: any[]) => T;
4
+ export type AbstractConstructor<T = object> = abstract new (...args: any[]) => T;
5
+ export type Mixin<TBase extends AbstractConstructor<TwitterClientBase>, TAdded> = abstract new (...args: ConstructorParameters<TBase>) => TwitterClientBase & TAdded;
6
+ export declare abstract class TwitterClientBase {
7
+ protected authToken: string;
8
+ protected ct0: string;
9
+ protected cookieHeader: string;
10
+ protected userAgent: string;
11
+ protected timeoutMs?: number;
12
+ protected quoteDepth: number;
13
+ protected clientUuid: string;
14
+ protected clientDeviceId: string;
15
+ protected clientUserId?: string;
16
+ constructor(options: TwitterClientOptions);
17
+ protected abstract getCurrentUser(): Promise<CurrentUserResult>;
18
+ protected sleep(ms: number): Promise<void>;
19
+ protected getQueryId(operationName: OperationName): Promise<string>;
20
+ protected refreshQueryIds(): Promise<void>;
21
+ protected withRefreshedQueryIdsOn404<T extends {
22
+ success: boolean;
23
+ had404?: boolean;
24
+ }>(attempt: () => Promise<T>): Promise<{
25
+ result: T;
26
+ refreshed: boolean;
27
+ }>;
28
+ protected getTweetDetailQueryIds(): Promise<string[]>;
29
+ protected getSearchTimelineQueryIds(): Promise<string[]>;
30
+ protected fetchWithTimeout(url: string, init: RequestInit): Promise<Response>;
31
+ protected getHeaders(): Record<string, string>;
32
+ protected createTransactionId(): string;
33
+ protected getBaseHeaders(): Record<string, string>;
34
+ protected getJsonHeaders(): Record<string, string>;
35
+ protected getUploadHeaders(): Record<string, string>;
36
+ protected ensureClientUserId(): Promise<void>;
37
+ }
38
+ //# sourceMappingURL=twitter-client-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-base.d.ts","sourceRoot":"","sources":["../../src/lib/twitter-client-base.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAyC,MAAM,+BAA+B,CAAC;AAC1G,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAIzF,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAEhE,MAAM,MAAM,mBAAmB,CAAC,CAAC,GAAG,MAAM,IAAI,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AACjF,MAAM,MAAM,KAAK,CAAC,KAAK,SAAS,mBAAmB,CAAC,iBAAiB,CAAC,EAAE,MAAM,IAAI,QAAQ,MACxF,GAAG,IAAI,EAAE,qBAAqB,CAAC,KAAK,CAAC,KAClC,iBAAiB,GAAG,MAAM,CAAC;AAEhC,8BAAsB,iBAAiB;IACrC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;gBAEpB,OAAO,EAAE,oBAAoB;IAgBzC,SAAS,CAAC,QAAQ,CAAC,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC;cAE/C,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;cAIhC,UAAU,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;cAKzD,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;cAWhC,0BAA0B,CAAC,CAAC,SAAS;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EACzF,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC;QAAE,MAAM,EAAE,CAAC,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;cAU7B,sBAAsB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;cAK3C,yBAAyB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;cAK9C,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;IAcnF,SAAS,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAI9C,SAAS,CAAC,mBAAmB,IAAI,MAAM;IAIvC,SAAS,CAAC,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IA0BlD,SAAS,CAAC,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAOlD,SAAS,CAAC,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;cAKpC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;CAYpD"}
@@ -0,0 +1,129 @@
1
+ import { randomBytes, randomUUID } from 'node:crypto';
2
+ import { runtimeQueryIds } from './runtime-query-ids.js';
3
+ import { QUERY_IDS, TARGET_QUERY_ID_OPERATIONS } from './twitter-client-constants.js';
4
+ import { normalizeQuoteDepth } from './twitter-client-utils.js';
5
+ export class TwitterClientBase {
6
+ authToken;
7
+ ct0;
8
+ cookieHeader;
9
+ userAgent;
10
+ timeoutMs;
11
+ quoteDepth;
12
+ clientUuid;
13
+ clientDeviceId;
14
+ clientUserId;
15
+ constructor(options) {
16
+ if (!options.cookies.authToken || !options.cookies.ct0) {
17
+ throw new Error('Both authToken and ct0 cookies are required');
18
+ }
19
+ this.authToken = options.cookies.authToken;
20
+ this.ct0 = options.cookies.ct0;
21
+ this.cookieHeader = options.cookies.cookieHeader || `auth_token=${this.authToken}; ct0=${this.ct0}`;
22
+ this.userAgent =
23
+ options.userAgent ||
24
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
25
+ this.timeoutMs = options.timeoutMs;
26
+ this.quoteDepth = normalizeQuoteDepth(options.quoteDepth);
27
+ this.clientUuid = randomUUID();
28
+ this.clientDeviceId = randomUUID();
29
+ }
30
+ async sleep(ms) {
31
+ await new Promise((resolve) => setTimeout(resolve, ms));
32
+ }
33
+ async getQueryId(operationName) {
34
+ const cached = await runtimeQueryIds.getQueryId(operationName);
35
+ return cached ?? QUERY_IDS[operationName];
36
+ }
37
+ async refreshQueryIds() {
38
+ if (process.env.NODE_ENV === 'test') {
39
+ return;
40
+ }
41
+ try {
42
+ await runtimeQueryIds.refresh(TARGET_QUERY_ID_OPERATIONS, { force: true });
43
+ }
44
+ catch {
45
+ // ignore refresh failures; callers will fall back to baked-in IDs
46
+ }
47
+ }
48
+ async withRefreshedQueryIdsOn404(attempt) {
49
+ const firstAttempt = await attempt();
50
+ if (firstAttempt.success || !firstAttempt.had404) {
51
+ return { result: firstAttempt, refreshed: false };
52
+ }
53
+ await this.refreshQueryIds();
54
+ const secondAttempt = await attempt();
55
+ return { result: secondAttempt, refreshed: true };
56
+ }
57
+ async getTweetDetailQueryIds() {
58
+ const primary = await this.getQueryId('TweetDetail');
59
+ return Array.from(new Set([primary, '97JF30KziU00483E_8elBA', 'aFvUsJm2c-oDkJV75blV6g']));
60
+ }
61
+ async getSearchTimelineQueryIds() {
62
+ const primary = await this.getQueryId('SearchTimeline');
63
+ return Array.from(new Set([primary, 'M1jEez78PEfVfbQLvlWMvQ', '5h0kNbk3ii97rmfY6CdgAA', 'Tp1sewRU1AsZpBWhqCZicQ']));
64
+ }
65
+ async fetchWithTimeout(url, init) {
66
+ if (!this.timeoutMs || this.timeoutMs <= 0) {
67
+ return fetch(url, init);
68
+ }
69
+ const controller = new AbortController();
70
+ const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
71
+ try {
72
+ return await fetch(url, { ...init, signal: controller.signal });
73
+ }
74
+ finally {
75
+ clearTimeout(timeoutId);
76
+ }
77
+ }
78
+ getHeaders() {
79
+ return this.getJsonHeaders();
80
+ }
81
+ createTransactionId() {
82
+ return randomBytes(16).toString('hex');
83
+ }
84
+ getBaseHeaders() {
85
+ const headers = {
86
+ accept: '*/*',
87
+ 'accept-language': 'en-US,en;q=0.9',
88
+ authorization: 'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA',
89
+ 'x-csrf-token': this.ct0,
90
+ 'x-twitter-auth-type': 'OAuth2Session',
91
+ 'x-twitter-active-user': 'yes',
92
+ 'x-twitter-client-language': 'en',
93
+ 'x-client-uuid': this.clientUuid,
94
+ 'x-twitter-client-deviceid': this.clientDeviceId,
95
+ 'x-client-transaction-id': this.createTransactionId(),
96
+ cookie: this.cookieHeader,
97
+ 'user-agent': this.userAgent,
98
+ origin: 'https://x.com',
99
+ referer: 'https://x.com/',
100
+ };
101
+ if (this.clientUserId) {
102
+ headers['x-twitter-client-user-id'] = this.clientUserId;
103
+ }
104
+ return headers;
105
+ }
106
+ getJsonHeaders() {
107
+ return {
108
+ ...this.getBaseHeaders(),
109
+ 'content-type': 'application/json',
110
+ };
111
+ }
112
+ getUploadHeaders() {
113
+ // Note: do not set content-type; URLSearchParams/FormData need to set it (incl boundary) themselves.
114
+ return this.getBaseHeaders();
115
+ }
116
+ async ensureClientUserId() {
117
+ if (process.env.NODE_ENV === 'test') {
118
+ return;
119
+ }
120
+ if (this.clientUserId) {
121
+ return;
122
+ }
123
+ const result = await this.getCurrentUser();
124
+ if (result.success && result.user?.id) {
125
+ this.clientUserId = result.user.id;
126
+ }
127
+ }
128
+ }
129
+ //# sourceMappingURL=twitter-client-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-base.js","sourceRoot":"","sources":["../../src/lib/twitter-client-base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AbstractConstructor, Mixin, TwitterClientBase } from './twitter-client-base.js';
2
+ import type { BookmarkMutationResult } from './twitter-client-types.js';
3
+ export interface TwitterClientBookmarkMethods {
4
+ unbookmark(tweetId: string): Promise<BookmarkMutationResult>;
5
+ }
6
+ export declare function withBookmarks<TBase extends AbstractConstructor<TwitterClientBase>>(Base: TBase): Mixin<TBase, TwitterClientBookmarkMethods>;
7
+ //# sourceMappingURL=twitter-client-bookmarks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-bookmarks.d.ts","sourceRoot":"","sources":["../../src/lib/twitter-client-bookmarks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE9F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAExE,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC9D;AAED,wBAAgB,aAAa,CAAC,KAAK,SAAS,mBAAmB,CAAC,iBAAiB,CAAC,EAChF,IAAI,EAAE,KAAK,GACV,KAAK,CAAC,KAAK,EAAE,4BAA4B,CAAC,CAqE5C"}