@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,61 @@
1
+ import { TWITTER_API_BASE, TWITTER_GRAPHQL_POST_URL } from './twitter-client-constants.js';
2
+ export function withBookmarks(Base) {
3
+ class TwitterClientBookmarks extends Base {
4
+ // biome-ignore lint/complexity/noUselessConstructor lint/suspicious/noExplicitAny: TS mixin constructor requirement.
5
+ constructor(...args) {
6
+ super(...args);
7
+ }
8
+ async unbookmark(tweetId) {
9
+ // TODO: verify if DeleteBookmark requires client user ID or additional payload fields; add ensureClientUserId() if needed (needs live API test).
10
+ const variables = { tweet_id: tweetId };
11
+ let queryId = await this.getQueryId('DeleteBookmark');
12
+ let urlWithOperation = `${TWITTER_API_BASE}/${queryId}/DeleteBookmark`;
13
+ const buildBody = () => JSON.stringify({ variables, queryId });
14
+ const buildHeaders = () => ({ ...this.getHeaders(), referer: `https://x.com/i/status/${tweetId}` });
15
+ let body = buildBody();
16
+ const parseResponse = async (response) => {
17
+ if (!response.ok) {
18
+ const text = await response.text();
19
+ return { success: false, error: `HTTP ${response.status}: ${text.slice(0, 200)}` };
20
+ }
21
+ const data = (await response.json());
22
+ if (data.errors && data.errors.length > 0) {
23
+ return { success: false, error: data.errors.map((e) => e.message).join(', ') };
24
+ }
25
+ return { success: true };
26
+ };
27
+ try {
28
+ let response = await this.fetchWithTimeout(urlWithOperation, {
29
+ method: 'POST',
30
+ headers: buildHeaders(),
31
+ body,
32
+ });
33
+ if (response.status === 404) {
34
+ await this.refreshQueryIds();
35
+ queryId = await this.getQueryId('DeleteBookmark');
36
+ urlWithOperation = `${TWITTER_API_BASE}/${queryId}/DeleteBookmark`;
37
+ body = buildBody();
38
+ response = await this.fetchWithTimeout(urlWithOperation, {
39
+ method: 'POST',
40
+ headers: buildHeaders(),
41
+ body,
42
+ });
43
+ if (response.status === 404) {
44
+ const retry = await this.fetchWithTimeout(TWITTER_GRAPHQL_POST_URL, {
45
+ method: 'POST',
46
+ headers: buildHeaders(),
47
+ body,
48
+ });
49
+ return parseResponse(retry);
50
+ }
51
+ }
52
+ return parseResponse(response);
53
+ }
54
+ catch (error) {
55
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
56
+ }
57
+ }
58
+ }
59
+ return TwitterClientBookmarks;
60
+ }
61
+ //# sourceMappingURL=twitter-client-bookmarks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-bookmarks.js","sourceRoot":"","sources":["../../src/lib/twitter-client-bookmarks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export declare const TWITTER_API_BASE = "https://x.com/i/api/graphql";
2
+ export declare const TWITTER_GRAPHQL_POST_URL = "https://x.com/i/api/graphql";
3
+ export declare const TWITTER_UPLOAD_URL = "https://upload.twitter.com/i/media/upload.json";
4
+ export declare const TWITTER_MEDIA_METADATA_URL = "https://x.com/i/api/1.1/media/metadata/create.json";
5
+ export declare const TWITTER_STATUS_UPDATE_URL = "https://x.com/i/api/1.1/statuses/update.json";
6
+ export declare const SETTINGS_SCREEN_NAME_REGEX: RegExp;
7
+ export declare const SETTINGS_USER_ID_REGEX: RegExp;
8
+ export declare const SETTINGS_NAME_REGEX: RegExp;
9
+ export declare const FALLBACK_QUERY_IDS: {
10
+ readonly CreateTweet: "TAJw1rBsjAtdNgTdlo2oeg";
11
+ readonly CreateRetweet: "ojPdsZsimiJrUGLR1sjUtA";
12
+ readonly DeleteRetweet: "iQtK4dl5hBmXewYZuEOKVw";
13
+ readonly CreateFriendship: "8h9JVdV8dlSyqyRDJEPCsA";
14
+ readonly DestroyFriendship: "ppXWuagMNXgvzx6WoXBW0Q";
15
+ readonly FavoriteTweet: "lI07N6Otwv1PhnEgXILM7A";
16
+ readonly UnfavoriteTweet: "ZYKSe-w7KEslx3JhSIk5LA";
17
+ readonly CreateBookmark: "aoDbu3RHznuiSkQ9aNM67Q";
18
+ readonly DeleteBookmark: "Wlmlj2-xzyS1GN3a6cj-mQ";
19
+ readonly TweetDetail: "97JF30KziU00483E_8elBA";
20
+ readonly SearchTimeline: "M1jEez78PEfVfbQLvlWMvQ";
21
+ readonly UserArticlesTweets: "8zBy9h4L90aDL02RsBcCFg";
22
+ readonly UserTweets: "Wms1GvIiHXAPBaCr9KblaA";
23
+ readonly Bookmarks: "RV1g3b8n_SGOHwkqKYSCFw";
24
+ readonly Following: "BEkNpEt5pNETESoqMsTEGA";
25
+ readonly Followers: "kuFUYP9eV1FPoEy4N-pi7w";
26
+ readonly Likes: "JR2gceKucIKcVNB_9JkhsA";
27
+ readonly BookmarkFolderTimeline: "KJIQpsvxrTfRIlbaRIySHQ";
28
+ readonly ListOwnerships: "wQcOSjSQ8NtgxIwvYl1lMg";
29
+ readonly ListMemberships: "BlEXXdARdSeL_0KyKHHvvg";
30
+ readonly ListLatestTweetsTimeline: "2TemLyqrMpTeAmysdbnVqw";
31
+ readonly ListMembers: "W-XE1M2yQGiNqSVr5xigKA";
32
+ readonly ListByRestId: "wXzyA5vM_aVkBL9G8Vp3kw";
33
+ readonly HomeTimeline: "edseUwk9sP5Phz__9TIRnA";
34
+ readonly HomeLatestTimeline: "iOEZpOdfekFsxSlPQCQtPg";
35
+ readonly ExploreSidebar: "lpSN4M6qpimkF4nRFPE3nQ";
36
+ readonly ExplorePage: "kheAINB_4pzRDqkzG3K-ng";
37
+ readonly GenericTimelineById: "uGSr7alSjR9v6QJAIaqSKQ";
38
+ readonly TrendHistory: "Sj4T-jSB9pr0Mxtsc1UKZQ";
39
+ readonly AboutAccountQuery: "zs_jFPFT78rBpXv9Z3U2YQ";
40
+ };
41
+ export type OperationName = keyof typeof FALLBACK_QUERY_IDS;
42
+ export declare const QUERY_IDS: Record<OperationName, string>;
43
+ export declare const TARGET_QUERY_ID_OPERATIONS: Array<OperationName>;
44
+ //# sourceMappingURL=twitter-client-constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-constants.d.ts","sourceRoot":"","sources":["../../src/lib/twitter-client-constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAC9D,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AACtE,eAAO,MAAM,kBAAkB,mDAAmD,CAAC;AACnF,eAAO,MAAM,0BAA0B,uDAAuD,CAAC;AAC/F,eAAO,MAAM,yBAAyB,iDAAiD,CAAC;AACxF,eAAO,MAAM,0BAA0B,QAA4B,CAAC;AACpE,eAAO,MAAM,sBAAsB,QAA4B,CAAC;AAChE,eAAO,MAAM,mBAAmB,QAAsC,CAAC;AAKvE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BrB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAE5D,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAGnD,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAsC,KAAK,CAAC,aAAa,CAAC,CAAC"}
@@ -0,0 +1,51 @@
1
+ // biome-ignore lint/correctness/useImportExtensions: JSON module import doesn't use .js extension.
2
+ import queryIds from './query-ids.json' with { type: 'json' };
3
+ export const TWITTER_API_BASE = 'https://x.com/i/api/graphql';
4
+ export const TWITTER_GRAPHQL_POST_URL = 'https://x.com/i/api/graphql';
5
+ export const TWITTER_UPLOAD_URL = 'https://upload.twitter.com/i/media/upload.json';
6
+ export const TWITTER_MEDIA_METADATA_URL = 'https://x.com/i/api/1.1/media/metadata/create.json';
7
+ export const TWITTER_STATUS_UPDATE_URL = 'https://x.com/i/api/1.1/statuses/update.json';
8
+ export const SETTINGS_SCREEN_NAME_REGEX = /"screen_name":"([^"]+)"/;
9
+ export const SETTINGS_USER_ID_REGEX = /"user_id"\s*:\s*"(\d+)"/;
10
+ export const SETTINGS_NAME_REGEX = /"name":"([^"\\]*(?:\\.[^"\\]*)*)"/;
11
+ // Query IDs rotate frequently; the values in query-ids.json are refreshed by
12
+ // scripts/update-query-ids.ts. The fallback values keep the client usable if
13
+ // the file is missing or incomplete.
14
+ export const FALLBACK_QUERY_IDS = {
15
+ CreateTweet: 'TAJw1rBsjAtdNgTdlo2oeg',
16
+ CreateRetweet: 'ojPdsZsimiJrUGLR1sjUtA',
17
+ DeleteRetweet: 'iQtK4dl5hBmXewYZuEOKVw',
18
+ CreateFriendship: '8h9JVdV8dlSyqyRDJEPCsA',
19
+ DestroyFriendship: 'ppXWuagMNXgvzx6WoXBW0Q',
20
+ FavoriteTweet: 'lI07N6Otwv1PhnEgXILM7A',
21
+ UnfavoriteTweet: 'ZYKSe-w7KEslx3JhSIk5LA',
22
+ CreateBookmark: 'aoDbu3RHznuiSkQ9aNM67Q',
23
+ DeleteBookmark: 'Wlmlj2-xzyS1GN3a6cj-mQ',
24
+ TweetDetail: '97JF30KziU00483E_8elBA',
25
+ SearchTimeline: 'M1jEez78PEfVfbQLvlWMvQ',
26
+ UserArticlesTweets: '8zBy9h4L90aDL02RsBcCFg',
27
+ UserTweets: 'Wms1GvIiHXAPBaCr9KblaA',
28
+ Bookmarks: 'RV1g3b8n_SGOHwkqKYSCFw',
29
+ Following: 'BEkNpEt5pNETESoqMsTEGA',
30
+ Followers: 'kuFUYP9eV1FPoEy4N-pi7w',
31
+ Likes: 'JR2gceKucIKcVNB_9JkhsA',
32
+ BookmarkFolderTimeline: 'KJIQpsvxrTfRIlbaRIySHQ',
33
+ ListOwnerships: 'wQcOSjSQ8NtgxIwvYl1lMg',
34
+ ListMemberships: 'BlEXXdARdSeL_0KyKHHvvg',
35
+ ListLatestTweetsTimeline: '2TemLyqrMpTeAmysdbnVqw',
36
+ ListMembers: 'W-XE1M2yQGiNqSVr5xigKA',
37
+ ListByRestId: 'wXzyA5vM_aVkBL9G8Vp3kw',
38
+ HomeTimeline: 'edseUwk9sP5Phz__9TIRnA',
39
+ HomeLatestTimeline: 'iOEZpOdfekFsxSlPQCQtPg',
40
+ ExploreSidebar: 'lpSN4M6qpimkF4nRFPE3nQ',
41
+ ExplorePage: 'kheAINB_4pzRDqkzG3K-ng',
42
+ GenericTimelineById: 'uGSr7alSjR9v6QJAIaqSKQ',
43
+ TrendHistory: 'Sj4T-jSB9pr0Mxtsc1UKZQ',
44
+ AboutAccountQuery: 'zs_jFPFT78rBpXv9Z3U2YQ',
45
+ };
46
+ export const QUERY_IDS = {
47
+ ...FALLBACK_QUERY_IDS,
48
+ ...queryIds,
49
+ };
50
+ export const TARGET_QUERY_ID_OPERATIONS = Object.keys(FALLBACK_QUERY_IDS);
51
+ //# sourceMappingURL=twitter-client-constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-constants.js","sourceRoot":"","sources":["../../src/lib/twitter-client-constants.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,OAAO,QAAQ,MAAM,kBAAkB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAE9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,6BAA6B,CAAC;AAC9D,MAAM,CAAC,MAAM,wBAAwB,GAAG,6BAA6B,CAAC;AACtE,MAAM,CAAC,MAAM,kBAAkB,GAAG,gDAAgD,CAAC;AACnF,MAAM,CAAC,MAAM,0BAA0B,GAAG,oDAAoD,CAAC;AAC/F,MAAM,CAAC,MAAM,yBAAyB,GAAG,8CAA8C,CAAC;AACxF,MAAM,CAAC,MAAM,0BAA0B,GAAG,yBAAyB,CAAC;AACpE,MAAM,CAAC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAAG,mCAAmC,CAAC;AAEvE,6EAA6E;AAC7E,6EAA6E;AAC7E,qCAAqC;AACrC,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,WAAW,EAAE,wBAAwB;IACrC,aAAa,EAAE,wBAAwB;IACvC,aAAa,EAAE,wBAAwB;IACvC,gBAAgB,EAAE,wBAAwB;IAC1C,iBAAiB,EAAE,wBAAwB;IAC3C,aAAa,EAAE,wBAAwB;IACvC,eAAe,EAAE,wBAAwB;IACzC,cAAc,EAAE,wBAAwB;IACxC,cAAc,EAAE,wBAAwB;IACxC,WAAW,EAAE,wBAAwB;IACrC,cAAc,EAAE,wBAAwB;IACxC,kBAAkB,EAAE,wBAAwB;IAC5C,UAAU,EAAE,wBAAwB;IACpC,SAAS,EAAE,wBAAwB;IACnC,SAAS,EAAE,wBAAwB;IACnC,SAAS,EAAE,wBAAwB;IACnC,KAAK,EAAE,wBAAwB;IAC/B,sBAAsB,EAAE,wBAAwB;IAChD,cAAc,EAAE,wBAAwB;IACxC,eAAe,EAAE,wBAAwB;IACzC,wBAAwB,EAAE,wBAAwB;IAClD,WAAW,EAAE,wBAAwB;IACrC,YAAY,EAAE,wBAAwB;IACtC,YAAY,EAAE,wBAAwB;IACtC,kBAAkB,EAAE,wBAAwB;IAC5C,cAAc,EAAE,wBAAwB;IACxC,WAAW,EAAE,wBAAwB;IACrC,mBAAmB,EAAE,wBAAwB;IAC7C,YAAY,EAAE,wBAAwB;IACtC,iBAAiB,EAAE,wBAAwB;CACnC,CAAC;AAIX,MAAM,CAAC,MAAM,SAAS,GAAkC;IACtD,GAAG,kBAAkB;IACrB,GAAI,QAAmD;CACxD,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAyB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { AbstractConstructor, Mixin, TwitterClientBase } from './twitter-client-base.js';
2
+ import type { BookmarkMutationResult } from './twitter-client-types.js';
3
+ export interface TwitterClientEngagementMethods {
4
+ /** Like a tweet. */
5
+ like(tweetId: string): Promise<BookmarkMutationResult>;
6
+ /** Remove a like from a tweet. */
7
+ unlike(tweetId: string): Promise<BookmarkMutationResult>;
8
+ /** Retweet a tweet. */
9
+ retweet(tweetId: string): Promise<BookmarkMutationResult>;
10
+ /** Remove a retweet. */
11
+ unretweet(tweetId: string): Promise<BookmarkMutationResult>;
12
+ /** Bookmark a tweet. */
13
+ bookmark(tweetId: string): Promise<BookmarkMutationResult>;
14
+ }
15
+ export declare function withEngagement<TBase extends AbstractConstructor<TwitterClientBase>>(Base: TBase): Mixin<TBase, TwitterClientEngagementMethods>;
16
+ //# sourceMappingURL=twitter-client-engagement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-engagement.d.ts","sourceRoot":"","sources":["../../src/lib/twitter-client-engagement.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,8BAA8B;IAC7C,oBAAoB;IACpB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACvD,kCAAkC;IAClC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACzD,uBAAuB;IACvB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC1D,wBAAwB;IACxB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC5D,wBAAwB;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC5D;AAED,wBAAgB,cAAc,CAAC,KAAK,SAAS,mBAAmB,CAAC,iBAAiB,CAAC,EACjF,IAAI,EAAE,KAAK,GACV,KAAK,CAAC,KAAK,EAAE,8BAA8B,CAAC,CAkG9C"}
@@ -0,0 +1,81 @@
1
+ import { TWITTER_API_BASE, TWITTER_GRAPHQL_POST_URL } from './twitter-client-constants.js';
2
+ export function withEngagement(Base) {
3
+ class TwitterClientEngagement extends Base {
4
+ // biome-ignore lint/complexity/noUselessConstructor lint/suspicious/noExplicitAny: TS mixin constructor requirement.
5
+ constructor(...args) {
6
+ super(...args);
7
+ }
8
+ async performEngagementMutation(operationName, tweetId) {
9
+ await this.ensureClientUserId();
10
+ const variables = operationName === 'DeleteRetweet' ? { tweet_id: tweetId, source_tweet_id: tweetId } : { tweet_id: tweetId };
11
+ let queryId = await this.getQueryId(operationName);
12
+ let urlWithOperation = `${TWITTER_API_BASE}/${queryId}/${operationName}`;
13
+ const buildBody = () => JSON.stringify({ variables, queryId });
14
+ const buildHeaders = () => ({ ...this.getHeaders(), referer: `https://x.com/i/status/${tweetId}` });
15
+ let body = buildBody();
16
+ const parseResponse = async (response) => {
17
+ if (!response.ok) {
18
+ const text = await response.text();
19
+ return { success: false, error: `HTTP ${response.status}: ${text.slice(0, 200)}` };
20
+ }
21
+ const data = (await response.json());
22
+ if (data.errors && data.errors.length > 0) {
23
+ return { success: false, error: data.errors.map((e) => e.message).join(', ') };
24
+ }
25
+ return { success: true };
26
+ };
27
+ try {
28
+ let response = await this.fetchWithTimeout(urlWithOperation, {
29
+ method: 'POST',
30
+ headers: buildHeaders(),
31
+ body,
32
+ });
33
+ if (response.status === 404) {
34
+ await this.refreshQueryIds();
35
+ queryId = await this.getQueryId(operationName);
36
+ urlWithOperation = `${TWITTER_API_BASE}/${queryId}/${operationName}`;
37
+ body = buildBody();
38
+ response = await this.fetchWithTimeout(urlWithOperation, {
39
+ method: 'POST',
40
+ headers: buildHeaders(),
41
+ body,
42
+ });
43
+ if (response.status === 404) {
44
+ const retry = await this.fetchWithTimeout(TWITTER_GRAPHQL_POST_URL, {
45
+ method: 'POST',
46
+ headers: buildHeaders(),
47
+ body,
48
+ });
49
+ return parseResponse(retry);
50
+ }
51
+ }
52
+ return parseResponse(response);
53
+ }
54
+ catch (error) {
55
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
56
+ }
57
+ }
58
+ /** Like a tweet. */
59
+ async like(tweetId) {
60
+ return this.performEngagementMutation('FavoriteTweet', tweetId);
61
+ }
62
+ /** Remove a like from a tweet. */
63
+ async unlike(tweetId) {
64
+ return this.performEngagementMutation('UnfavoriteTweet', tweetId);
65
+ }
66
+ /** Retweet a tweet. */
67
+ async retweet(tweetId) {
68
+ return this.performEngagementMutation('CreateRetweet', tweetId);
69
+ }
70
+ /** Remove a retweet. */
71
+ async unretweet(tweetId) {
72
+ return this.performEngagementMutation('DeleteRetweet', tweetId);
73
+ }
74
+ /** Bookmark a tweet. */
75
+ async bookmark(tweetId) {
76
+ return this.performEngagementMutation('CreateBookmark', tweetId);
77
+ }
78
+ }
79
+ return TwitterClientEngagement;
80
+ }
81
+ //# sourceMappingURL=twitter-client-engagement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-engagement.js","sourceRoot":"","sources":["../../src/lib/twitter-client-engagement.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare function buildArticleFeatures(): Record<string, boolean>;
2
+ export declare function buildTweetDetailFeatures(): Record<string, boolean>;
3
+ export declare function buildArticleFieldToggles(): Record<string, boolean>;
4
+ export declare function buildSearchFeatures(): Record<string, boolean>;
5
+ export declare function buildTweetCreateFeatures(): Record<string, boolean>;
6
+ export declare function buildTimelineFeatures(): Record<string, boolean>;
7
+ export declare function buildBookmarksFeatures(): Record<string, boolean>;
8
+ export declare function buildLikesFeatures(): Record<string, boolean>;
9
+ export declare function buildListsFeatures(): Record<string, boolean>;
10
+ export declare function buildHomeTimelineFeatures(): Record<string, boolean>;
11
+ export declare function buildUserTweetsFeatures(): Record<string, boolean>;
12
+ export declare function buildFollowingFeatures(): Record<string, boolean>;
13
+ export declare function buildExploreFeatures(): Record<string, boolean>;
14
+ //# sourceMappingURL=twitter-client-features.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-client-features.d.ts","sourceRoot":"","sources":["../../src/lib/twitter-client-features.ts"],"names":[],"mappings":"AAEA,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwC9D;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAelE;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASlE;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyC7D;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuClE;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAY/D;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKhE;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE5D;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA6C5D;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAInE;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuCjE;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuChE;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0C9D"}
@@ -0,0 +1,347 @@
1
+ import { applyFeatureOverrides } from './runtime-features.js';
2
+ export function buildArticleFeatures() {
3
+ return applyFeatureOverrides('article', {
4
+ rweb_video_screen_enabled: true,
5
+ profile_label_improvements_pcf_label_in_post_enabled: true,
6
+ responsive_web_profile_redirect_enabled: true,
7
+ rweb_tipjar_consumption_enabled: true,
8
+ verified_phone_label_enabled: false,
9
+ creator_subscriptions_tweet_preview_api_enabled: true,
10
+ responsive_web_graphql_timeline_navigation_enabled: true,
11
+ responsive_web_graphql_exclude_directive_enabled: true,
12
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
13
+ premium_content_api_read_enabled: false,
14
+ communities_web_enable_tweet_community_results_fetch: true,
15
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
16
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
17
+ responsive_web_grok_analyze_post_followups_enabled: false,
18
+ responsive_web_grok_annotations_enabled: false,
19
+ responsive_web_jetfuel_frame: true,
20
+ post_ctas_fetch_enabled: true,
21
+ responsive_web_grok_share_attachment_enabled: true,
22
+ articles_preview_enabled: true,
23
+ responsive_web_edit_tweet_api_enabled: true,
24
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
25
+ view_counts_everywhere_api_enabled: true,
26
+ longform_notetweets_consumption_enabled: true,
27
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
28
+ tweet_awards_web_tipping_enabled: false,
29
+ responsive_web_grok_show_grok_translated_post: false,
30
+ responsive_web_grok_analysis_button_from_backend: true,
31
+ creator_subscriptions_quote_tweet_preview_enabled: false,
32
+ freedom_of_speech_not_reach_fetch_enabled: true,
33
+ standardized_nudges_misinfo: true,
34
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
35
+ longform_notetweets_rich_text_read_enabled: true,
36
+ longform_notetweets_inline_media_enabled: true,
37
+ responsive_web_grok_image_annotation_enabled: true,
38
+ responsive_web_grok_imagine_annotation_enabled: true,
39
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
40
+ responsive_web_enhance_cards_enabled: false,
41
+ });
42
+ }
43
+ export function buildTweetDetailFeatures() {
44
+ return applyFeatureOverrides('tweetDetail', {
45
+ ...buildArticleFeatures(),
46
+ responsive_web_graphql_exclude_directive_enabled: true,
47
+ communities_web_enable_tweet_community_results_fetch: true,
48
+ responsive_web_twitter_article_plain_text_enabled: true,
49
+ responsive_web_twitter_article_seed_tweet_detail_enabled: true,
50
+ responsive_web_twitter_article_seed_tweet_summary_enabled: true,
51
+ longform_notetweets_rich_text_read_enabled: true,
52
+ longform_notetweets_inline_media_enabled: true,
53
+ responsive_web_edit_tweet_api_enabled: true,
54
+ tweet_awards_web_tipping_enabled: false,
55
+ creator_subscriptions_quote_tweet_preview_enabled: false,
56
+ verified_phone_label_enabled: false,
57
+ });
58
+ }
59
+ export function buildArticleFieldToggles() {
60
+ return {
61
+ withPayments: false,
62
+ withAuxiliaryUserLabels: false,
63
+ withArticleRichContentState: true,
64
+ withArticlePlainText: true,
65
+ withGrokAnalyze: false,
66
+ withDisallowedReplyControls: false,
67
+ };
68
+ }
69
+ export function buildSearchFeatures() {
70
+ return applyFeatureOverrides('search', {
71
+ rweb_video_screen_enabled: true,
72
+ profile_label_improvements_pcf_label_in_post_enabled: true,
73
+ responsive_web_profile_redirect_enabled: true,
74
+ rweb_tipjar_consumption_enabled: true,
75
+ verified_phone_label_enabled: false,
76
+ creator_subscriptions_tweet_preview_api_enabled: true,
77
+ responsive_web_graphql_timeline_navigation_enabled: true,
78
+ responsive_web_graphql_exclude_directive_enabled: true,
79
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
80
+ premium_content_api_read_enabled: false,
81
+ communities_web_enable_tweet_community_results_fetch: true,
82
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
83
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
84
+ responsive_web_grok_analyze_post_followups_enabled: false,
85
+ responsive_web_grok_annotations_enabled: false,
86
+ responsive_web_jetfuel_frame: true,
87
+ post_ctas_fetch_enabled: true,
88
+ responsive_web_grok_share_attachment_enabled: true,
89
+ responsive_web_edit_tweet_api_enabled: true,
90
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
91
+ view_counts_everywhere_api_enabled: true,
92
+ longform_notetweets_consumption_enabled: true,
93
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
94
+ tweet_awards_web_tipping_enabled: false,
95
+ responsive_web_grok_show_grok_translated_post: false,
96
+ responsive_web_grok_analysis_button_from_backend: true,
97
+ creator_subscriptions_quote_tweet_preview_enabled: false,
98
+ freedom_of_speech_not_reach_fetch_enabled: true,
99
+ standardized_nudges_misinfo: true,
100
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
101
+ rweb_video_timestamps_enabled: true,
102
+ longform_notetweets_rich_text_read_enabled: true,
103
+ longform_notetweets_inline_media_enabled: true,
104
+ responsive_web_grok_image_annotation_enabled: true,
105
+ responsive_web_grok_imagine_annotation_enabled: true,
106
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
107
+ articles_preview_enabled: true,
108
+ responsive_web_enhance_cards_enabled: false,
109
+ });
110
+ }
111
+ export function buildTweetCreateFeatures() {
112
+ return applyFeatureOverrides('tweetCreate', {
113
+ rweb_video_screen_enabled: true,
114
+ creator_subscriptions_tweet_preview_api_enabled: true,
115
+ premium_content_api_read_enabled: false,
116
+ communities_web_enable_tweet_community_results_fetch: true,
117
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
118
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
119
+ responsive_web_grok_analyze_post_followups_enabled: false,
120
+ responsive_web_grok_annotations_enabled: false,
121
+ responsive_web_jetfuel_frame: true,
122
+ post_ctas_fetch_enabled: true,
123
+ responsive_web_grok_share_attachment_enabled: true,
124
+ responsive_web_edit_tweet_api_enabled: true,
125
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
126
+ view_counts_everywhere_api_enabled: true,
127
+ longform_notetweets_consumption_enabled: true,
128
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
129
+ tweet_awards_web_tipping_enabled: false,
130
+ responsive_web_grok_show_grok_translated_post: false,
131
+ responsive_web_grok_analysis_button_from_backend: true,
132
+ creator_subscriptions_quote_tweet_preview_enabled: false,
133
+ longform_notetweets_rich_text_read_enabled: true,
134
+ longform_notetweets_inline_media_enabled: true,
135
+ profile_label_improvements_pcf_label_in_post_enabled: true,
136
+ responsive_web_profile_redirect_enabled: false,
137
+ rweb_tipjar_consumption_enabled: true,
138
+ verified_phone_label_enabled: false,
139
+ articles_preview_enabled: true,
140
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
141
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
142
+ freedom_of_speech_not_reach_fetch_enabled: true,
143
+ standardized_nudges_misinfo: true,
144
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
145
+ responsive_web_grok_image_annotation_enabled: true,
146
+ responsive_web_grok_imagine_annotation_enabled: true,
147
+ responsive_web_graphql_timeline_navigation_enabled: true,
148
+ responsive_web_enhance_cards_enabled: false,
149
+ });
150
+ }
151
+ export function buildTimelineFeatures() {
152
+ return applyFeatureOverrides('timeline', {
153
+ ...buildSearchFeatures(),
154
+ blue_business_profile_image_shape_enabled: true,
155
+ responsive_web_text_conversations_enabled: false,
156
+ tweetypie_unmention_optimization_enabled: true,
157
+ vibe_api_enabled: true,
158
+ responsive_web_twitter_blue_verified_badge_is_enabled: true,
159
+ interactive_text_enabled: true,
160
+ longform_notetweets_richtext_consumption_enabled: true,
161
+ responsive_web_media_download_video_enabled: false,
162
+ });
163
+ }
164
+ export function buildBookmarksFeatures() {
165
+ return applyFeatureOverrides('bookmarks', {
166
+ ...buildTimelineFeatures(),
167
+ graphql_timeline_v2_bookmark_timeline: true,
168
+ });
169
+ }
170
+ export function buildLikesFeatures() {
171
+ return applyFeatureOverrides('likes', buildTimelineFeatures());
172
+ }
173
+ export function buildListsFeatures() {
174
+ return applyFeatureOverrides('lists', {
175
+ rweb_video_screen_enabled: true,
176
+ profile_label_improvements_pcf_label_in_post_enabled: true,
177
+ responsive_web_profile_redirect_enabled: true,
178
+ rweb_tipjar_consumption_enabled: true,
179
+ verified_phone_label_enabled: false,
180
+ creator_subscriptions_tweet_preview_api_enabled: true,
181
+ responsive_web_graphql_timeline_navigation_enabled: true,
182
+ responsive_web_graphql_exclude_directive_enabled: true,
183
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
184
+ premium_content_api_read_enabled: false,
185
+ communities_web_enable_tweet_community_results_fetch: true,
186
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
187
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
188
+ responsive_web_grok_analyze_post_followups_enabled: false,
189
+ responsive_web_grok_annotations_enabled: false,
190
+ responsive_web_jetfuel_frame: true,
191
+ post_ctas_fetch_enabled: true,
192
+ responsive_web_grok_share_attachment_enabled: true,
193
+ articles_preview_enabled: true,
194
+ responsive_web_edit_tweet_api_enabled: true,
195
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
196
+ view_counts_everywhere_api_enabled: true,
197
+ longform_notetweets_consumption_enabled: true,
198
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
199
+ tweet_awards_web_tipping_enabled: false,
200
+ responsive_web_grok_show_grok_translated_post: false,
201
+ responsive_web_grok_analysis_button_from_backend: true,
202
+ creator_subscriptions_quote_tweet_preview_enabled: false,
203
+ freedom_of_speech_not_reach_fetch_enabled: true,
204
+ standardized_nudges_misinfo: true,
205
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
206
+ longform_notetweets_rich_text_read_enabled: true,
207
+ longform_notetweets_inline_media_enabled: true,
208
+ responsive_web_grok_image_annotation_enabled: true,
209
+ responsive_web_grok_imagine_annotation_enabled: true,
210
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
211
+ responsive_web_enhance_cards_enabled: false,
212
+ blue_business_profile_image_shape_enabled: false,
213
+ responsive_web_text_conversations_enabled: false,
214
+ tweetypie_unmention_optimization_enabled: true,
215
+ vibe_api_enabled: false,
216
+ interactive_text_enabled: false,
217
+ });
218
+ }
219
+ export function buildHomeTimelineFeatures() {
220
+ return applyFeatureOverrides('homeTimeline', {
221
+ ...buildTimelineFeatures(),
222
+ });
223
+ }
224
+ export function buildUserTweetsFeatures() {
225
+ return applyFeatureOverrides('userTweets', {
226
+ rweb_video_screen_enabled: false,
227
+ profile_label_improvements_pcf_label_in_post_enabled: true,
228
+ responsive_web_profile_redirect_enabled: false,
229
+ rweb_tipjar_consumption_enabled: true,
230
+ verified_phone_label_enabled: false,
231
+ creator_subscriptions_tweet_preview_api_enabled: true,
232
+ responsive_web_graphql_timeline_navigation_enabled: true,
233
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
234
+ premium_content_api_read_enabled: false,
235
+ communities_web_enable_tweet_community_results_fetch: true,
236
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
237
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
238
+ responsive_web_grok_analyze_post_followups_enabled: true,
239
+ responsive_web_jetfuel_frame: true,
240
+ post_ctas_fetch_enabled: true,
241
+ responsive_web_grok_share_attachment_enabled: true,
242
+ responsive_web_grok_annotations_enabled: false,
243
+ articles_preview_enabled: true,
244
+ responsive_web_edit_tweet_api_enabled: true,
245
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
246
+ view_counts_everywhere_api_enabled: true,
247
+ longform_notetweets_consumption_enabled: true,
248
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
249
+ tweet_awards_web_tipping_enabled: false,
250
+ responsive_web_grok_show_grok_translated_post: true,
251
+ responsive_web_grok_analysis_button_from_backend: true,
252
+ creator_subscriptions_quote_tweet_preview_enabled: false,
253
+ freedom_of_speech_not_reach_fetch_enabled: true,
254
+ standardized_nudges_misinfo: true,
255
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
256
+ longform_notetweets_rich_text_read_enabled: true,
257
+ longform_notetweets_inline_media_enabled: true,
258
+ responsive_web_grok_image_annotation_enabled: true,
259
+ responsive_web_grok_imagine_annotation_enabled: true,
260
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
261
+ responsive_web_enhance_cards_enabled: false,
262
+ });
263
+ }
264
+ export function buildFollowingFeatures() {
265
+ return applyFeatureOverrides('following', {
266
+ rweb_video_screen_enabled: true,
267
+ profile_label_improvements_pcf_label_in_post_enabled: false,
268
+ responsive_web_profile_redirect_enabled: true,
269
+ rweb_tipjar_consumption_enabled: true,
270
+ verified_phone_label_enabled: false,
271
+ creator_subscriptions_tweet_preview_api_enabled: true,
272
+ responsive_web_graphql_timeline_navigation_enabled: true,
273
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
274
+ premium_content_api_read_enabled: true,
275
+ communities_web_enable_tweet_community_results_fetch: true,
276
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
277
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
278
+ responsive_web_grok_analyze_post_followups_enabled: false,
279
+ responsive_web_grok_annotations_enabled: false,
280
+ responsive_web_jetfuel_frame: false,
281
+ post_ctas_fetch_enabled: true,
282
+ responsive_web_grok_share_attachment_enabled: false,
283
+ articles_preview_enabled: true,
284
+ responsive_web_edit_tweet_api_enabled: true,
285
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
286
+ view_counts_everywhere_api_enabled: true,
287
+ longform_notetweets_consumption_enabled: true,
288
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
289
+ tweet_awards_web_tipping_enabled: true,
290
+ responsive_web_grok_show_grok_translated_post: false,
291
+ responsive_web_grok_analysis_button_from_backend: false,
292
+ creator_subscriptions_quote_tweet_preview_enabled: false,
293
+ freedom_of_speech_not_reach_fetch_enabled: true,
294
+ standardized_nudges_misinfo: true,
295
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
296
+ longform_notetweets_rich_text_read_enabled: true,
297
+ longform_notetweets_inline_media_enabled: true,
298
+ responsive_web_grok_image_annotation_enabled: false,
299
+ responsive_web_grok_imagine_annotation_enabled: false,
300
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
301
+ responsive_web_enhance_cards_enabled: false,
302
+ });
303
+ }
304
+ export function buildExploreFeatures() {
305
+ return applyFeatureOverrides('explore', {
306
+ rweb_video_screen_enabled: true,
307
+ profile_label_improvements_pcf_label_in_post_enabled: true,
308
+ responsive_web_profile_redirect_enabled: true,
309
+ rweb_tipjar_consumption_enabled: true,
310
+ verified_phone_label_enabled: false,
311
+ creator_subscriptions_tweet_preview_api_enabled: true,
312
+ responsive_web_graphql_timeline_navigation_enabled: true,
313
+ responsive_web_graphql_exclude_directive_enabled: true,
314
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
315
+ premium_content_api_read_enabled: false,
316
+ communities_web_enable_tweet_community_results_fetch: true,
317
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
318
+ responsive_web_grok_analyze_button_fetch_trends_enabled: true,
319
+ responsive_web_grok_analyze_post_followups_enabled: true,
320
+ responsive_web_grok_annotations_enabled: true,
321
+ responsive_web_jetfuel_frame: true,
322
+ responsive_web_grok_share_attachment_enabled: true,
323
+ articles_preview_enabled: true,
324
+ responsive_web_edit_tweet_api_enabled: true,
325
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
326
+ view_counts_everywhere_api_enabled: true,
327
+ longform_notetweets_consumption_enabled: true,
328
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
329
+ tweet_awards_web_tipping_enabled: false,
330
+ responsive_web_grok_show_grok_translated_post: true,
331
+ responsive_web_grok_analysis_button_from_backend: true,
332
+ creator_subscriptions_quote_tweet_preview_enabled: false,
333
+ freedom_of_speech_not_reach_fetch_enabled: true,
334
+ standardized_nudges_misinfo: true,
335
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
336
+ longform_notetweets_rich_text_read_enabled: true,
337
+ longform_notetweets_inline_media_enabled: true,
338
+ responsive_web_grok_image_annotation_enabled: true,
339
+ responsive_web_grok_imagine_annotation_enabled: true,
340
+ responsive_web_grok_community_note_auto_translation_is_enabled: true,
341
+ responsive_web_enhance_cards_enabled: false,
342
+ // Additional features required for ExploreSidebar
343
+ post_ctas_fetch_enabled: true,
344
+ rweb_video_timestamps_enabled: true,
345
+ });
346
+ }
347
+ //# sourceMappingURL=twitter-client-features.js.map