emusks 2.0.3 → 2.0.5

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.
@@ -1,7 +1,7 @@
1
1
  import getCycleTLS from "../cycletls.js";
2
2
  import parseTweet from "../parsers/tweet.js";
3
3
 
4
- async function createPollCard(client, poll) {
4
+ async function createPollCard(instance, poll) {
5
5
  if (!poll.choices || poll.choices.length < 2)
6
6
  throw new Error("a poll must have at least 2 choices");
7
7
  if (poll.choices.length > 4)
@@ -37,7 +37,7 @@ async function createPollCard(client, poll) {
37
37
  };
38
38
 
39
39
  if (hasImages) {
40
- cardObj["twitter:card"] = `poll_choice_images`;
40
+ cardObj["twitter:card"] = "poll_choice_images";
41
41
  for (let i = 0; i < poll.choices.length; i++) {
42
42
  cardObj[`twitter:string:choice${i + 1}_label`] = labels[i];
43
43
  cardObj[`twitter:image:choice${i + 1}_image:src:id`] =
@@ -58,31 +58,31 @@ async function createPollCard(client, poll) {
58
58
  headers: {
59
59
  accept: "*/*",
60
60
  "accept-language": "en-US,en;q=0.9",
61
- authorization: `Bearer ${client.auth.client.bearer}`,
61
+ authorization: `Bearer ${instance.auth.client.bearer}`,
62
62
  "content-type": "application/x-www-form-urlencoded",
63
- "x-csrf-token": client.auth.csrfToken,
63
+ "x-csrf-token": instance.auth.csrfToken,
64
64
  "x-twitter-active-user": "yes",
65
65
  "x-twitter-auth-type": "OAuth2Session",
66
66
  "x-twitter-client-language": "en",
67
67
  priority: "u=1, i",
68
- "sec-ch-ua": '"Not(A:Brand";v="8", "Chromium";v="144"',
68
+ "sec-ch-ua": '\u0022Not(A:Brand\u0022;v=\u00228\u0022, \u0022Chromium\u0022;v=\u0022144\u0022',
69
69
  "sec-ch-ua-mobile": "?0",
70
- "sec-ch-ua-platform": '"macOS"',
70
+ "sec-ch-ua-platform": '\u0022macOS\u0022',
71
71
  "sec-fetch-dest": "empty",
72
72
  "sec-fetch-mode": "cors",
73
73
  "sec-fetch-site": "same-site",
74
74
  "sec-gpc": "1",
75
75
  cookie:
76
- client.auth.client.headers.cookie +
77
- (client.elevatedCookies ? `; ${client.elevatedCookies}` : ""),
76
+ instance.auth.client.headers.cookie +
77
+ (instance.elevatedCookies ? `; ${instance.elevatedCookies}` : ""),
78
78
  },
79
79
  body: `card_data=${encodeURIComponent(cardData)}`,
80
80
  userAgent:
81
- client.auth.client.fingerprints?.userAgent ||
82
- client.auth.client.fingerprints?.["user-agent"],
83
- ja3: client.auth.client.fingerprints?.ja3,
84
- ja4r: client.auth.client.fingerprints?.ja4r,
85
- proxy: client.proxy || undefined,
81
+ instance.auth.client.fingerprints?.userAgent ||
82
+ instance.auth.client.fingerprints?.["user-agent"],
83
+ ja3: instance.auth.client.fingerprints?.ja3,
84
+ ja4r: instance.auth.client.fingerprints?.ja4r,
85
+ proxy: instance.proxy || undefined,
86
86
  referrer: "https://x.com/",
87
87
  },
88
88
  "post",
@@ -95,309 +95,307 @@ async function createPollCard(client, poll) {
95
95
  return data.card_uri;
96
96
  }
97
97
 
98
- export default (client) => ({
99
- async create(text, opts = {}) {
100
- let cardUri = opts.cardUri;
98
+ export async function create(text, opts = {}) {
99
+ let cardUri = opts.cardUri;
101
100
 
102
- if (opts.poll) {
103
- if (cardUri)
104
- throw new Error("a tweet can't have both a poll and a cardUri");
105
- cardUri = await createPollCard(client, opts.poll);
106
- }
101
+ if (opts.poll) {
102
+ if (cardUri)
103
+ throw new Error("a tweet can\u0027t have both a poll and a cardUri");
104
+ cardUri = await createPollCard(this, opts.poll);
105
+ }
107
106
 
108
- const res = await client.graphql("CreateTweet", {
109
- body: {
110
- variables: {
111
- tweet_text: text,
112
- dark_request: false,
113
- card_uri: cardUri || undefined,
114
- media: {
115
- media_entities:
116
- opts.mediaIds?.map((id) => ({
117
- media_id: id,
118
- tagged_users: [],
119
- })) || [],
120
- possibly_sensitive: opts.sensitive || false,
121
- },
122
- semantic_annotation_ids: [],
123
- ...(opts.replyTo
124
- ? {
125
- reply: {
126
- in_reply_to_tweet_id: opts.replyTo,
127
- exclude_reply_user_ids: [],
128
- },
129
- }
130
- : {}),
131
- ...(opts.quoteTweetId
132
- ? { attachment_url: `https://x.com/i/status/${opts.quoteTweetId}` }
133
- : {}),
134
- ...(opts.conversationControl
135
- ? { conversation_control: { mode: opts.conversationControl } }
136
- : {}),
137
- ...opts.variables,
138
- },
139
- },
140
- });
141
- const tweet = res?.data?.create_tweet?.tweet_results?.result;
142
- return tweet ? parseTweet(tweet) : res;
143
- },
144
-
145
- async createNote(text, opts = {}) {
146
- const res = await client.graphql("CreateNoteTweet", {
147
- body: {
148
- variables: {
149
- tweet_text: text,
150
- dark_request: false,
151
- media: {
152
- media_entities:
153
- opts.mediaIds?.map((id) => ({
154
- media_id: id,
155
- tagged_users: [],
156
- })) || [],
157
- possibly_sensitive: opts.sensitive || false,
158
- },
159
- semantic_annotation_ids: [],
160
- richtext_options: { richtext_tags: opts.richtext_tags || [] },
161
- ...(opts.replyTo
162
- ? {
163
- reply: {
164
- in_reply_to_tweet_id: opts.replyTo,
165
- exclude_reply_user_ids: [],
166
- },
167
- }
168
- : {}),
169
- ...opts.variables,
170
- },
171
- },
172
- });
173
- const tweet = res?.data?.notetweet_create?.tweet_results?.result;
174
- return tweet ? parseTweet(tweet) : res;
175
- },
176
-
177
- async delete(tweetId) {
178
- return await client.graphql("DeleteTweet", {
179
- body: { variables: { tweet_id: tweetId, dark_request: false } },
180
- });
181
- },
182
-
183
- async like(tweetId) {
184
- return await client.graphql("FavoriteTweet", {
185
- body: { variables: { tweet_id: tweetId } },
186
- });
187
- },
188
-
189
- async unlike(tweetId) {
190
- return await client.graphql("UnfavoriteTweet", {
191
- body: { variables: { tweet_id: tweetId } },
192
- });
193
- },
194
-
195
- async retweet(tweetId) {
196
- return await client.graphql("CreateRetweet", {
197
- body: { variables: { tweet_id: tweetId, dark_request: false } },
198
- });
199
- },
200
-
201
- async unretweet(tweetId) {
202
- return await client.graphql("DeleteRetweet", {
203
- body: { variables: { source_tweet_id: tweetId, dark_request: false } },
204
- });
205
- },
206
-
207
- async pin(tweetId) {
208
- return await client.graphql("PinTweet", {
209
- body: { variables: { tweet_id: tweetId } },
210
- });
211
- },
212
-
213
- async unpin(tweetId) {
214
- return await client.graphql("UnpinTweet", {
215
- body: { variables: { tweet_id: tweetId } },
216
- });
217
- },
218
-
219
- async get(tweetId) {
220
- const res = await client.graphql("TweetResultByRestId", {
107
+ const res = await this.graphql("CreateTweet", {
108
+ body: {
221
109
  variables: {
222
- tweetId,
223
- withCommunity: false,
224
- includePromotedContent: false,
225
- withVoice: false,
226
- },
227
- fieldToggles: {
228
- withArticlePlainText: false,
229
- withArticleRichContentState: false,
230
- withAuxiliaryUserLabels: false,
110
+ tweet_text: text,
111
+ dark_request: false,
112
+ card_uri: cardUri || undefined,
113
+ media: {
114
+ media_entities:
115
+ opts.mediaIds?.map((id) => ({
116
+ media_id: id,
117
+ tagged_users: [],
118
+ })) || [],
119
+ possibly_sensitive: opts.sensitive || false,
120
+ },
121
+ semantic_annotation_ids: [],
122
+ ...(opts.replyTo
123
+ ? {
124
+ reply: {
125
+ in_reply_to_tweet_id: opts.replyTo,
126
+ exclude_reply_user_ids: [],
127
+ },
128
+ }
129
+ : {}),
130
+ ...(opts.quoteTweetId
131
+ ? { attachment_url: `https://x.com/i/status/${opts.quoteTweetId}` }
132
+ : {}),
133
+ ...(opts.conversationControl
134
+ ? { conversation_control: { mode: opts.conversationControl } }
135
+ : {}),
136
+ ...opts.variables,
231
137
  },
232
- });
233
- const tweet = res?.data?.tweetResult?.result;
234
- return tweet ? parseTweet(tweet) : res;
235
- },
138
+ },
139
+ });
140
+ const tweet = res?.data?.create_tweet?.tweet_results?.result;
141
+ return tweet ? parseTweet(tweet) : res;
142
+ }
236
143
 
237
- async getMany(tweetIds) {
238
- const res = await client.graphql("TweetResultsByRestIds", {
144
+ export async function createNote(text, opts = {}) {
145
+ const res = await this.graphql("CreateNoteTweet", {
146
+ body: {
239
147
  variables: {
240
- tweetIds,
241
- withCommunity: false,
242
- includePromotedContent: false,
243
- withVoice: false,
244
- },
245
- fieldToggles: {
246
- withArticlePlainText: false,
247
- withArticleRichContentState: false,
248
- withAuxiliaryUserLabels: false,
249
- },
250
- });
251
- const results = res?.data?.tweetResult || [];
252
- return Array.isArray(results)
253
- ? results.map((r) => (r?.result ? parseTweet(r.result) : r))
254
- : res;
255
- },
256
-
257
- async detail(tweetId, opts = {}) {
258
- return await client.graphql("TweetDetail", {
259
- variables: {
260
- focalTweetId: tweetId,
261
- with_rux_injections: false,
262
- rankingMode: "Relevance",
263
- includePromotedContent: true,
264
- withCommunity: true,
265
- withQuickPromoteEligibilityTweetFields: true,
266
- withBirdwatchNotes: true,
267
- withVoice: true,
148
+ tweet_text: text,
149
+ dark_request: false,
150
+ media: {
151
+ media_entities:
152
+ opts.mediaIds?.map((id) => ({
153
+ media_id: id,
154
+ tagged_users: [],
155
+ })) || [],
156
+ possibly_sensitive: opts.sensitive || false,
157
+ },
158
+ semantic_annotation_ids: [],
159
+ richtext_options: { richtext_tags: opts.richtext_tags || [] },
160
+ ...(opts.replyTo
161
+ ? {
162
+ reply: {
163
+ in_reply_to_tweet_id: opts.replyTo,
164
+ exclude_reply_user_ids: [],
165
+ },
166
+ }
167
+ : {}),
268
168
  ...opts.variables,
269
169
  },
270
- fieldToggles: {
271
- withArticlePlainText: false,
272
- withArticleRichContentState: false,
273
- withAuxiliaryUserLabels: false,
274
- },
275
- });
276
- },
170
+ },
171
+ });
172
+ const tweet = res?.data?.notetweet_create?.tweet_results?.result;
173
+ return tweet ? parseTweet(tweet) : res;
174
+ }
277
175
 
278
- async editHistory(tweetId) {
279
- return await client.graphql("TweetEditHistory", {
280
- variables: { tweetId, withQuickPromoteEligibilityTweetFields: true },
281
- });
282
- },
176
+ export async function remove(tweetId) {
177
+ return await this.graphql("DeleteTweet", {
178
+ body: { variables: { tweet_id: tweetId, dark_request: false } },
179
+ });
180
+ }
181
+
182
+ export async function like(tweetId) {
183
+ return await this.graphql("FavoriteTweet", {
184
+ body: { variables: { tweet_id: tweetId } },
185
+ });
186
+ }
283
187
 
284
- async retweeters(tweetId, opts = {}) {
285
- return await client.graphql("Retweeters", {
188
+ export async function unlike(tweetId) {
189
+ return await this.graphql("UnfavoriteTweet", {
190
+ body: { variables: { tweet_id: tweetId } },
191
+ });
192
+ }
193
+
194
+ export async function retweet(tweetId) {
195
+ return await this.graphql("CreateRetweet", {
196
+ body: { variables: { tweet_id: tweetId, dark_request: false } },
197
+ });
198
+ }
199
+
200
+ export async function unretweet(tweetId) {
201
+ return await this.graphql("DeleteRetweet", {
202
+ body: { variables: { source_tweet_id: tweetId, dark_request: false } },
203
+ });
204
+ }
205
+
206
+ export async function pin(tweetId) {
207
+ return await this.graphql("PinTweet", {
208
+ body: { variables: { tweet_id: tweetId } },
209
+ });
210
+ }
211
+
212
+ export async function unpin(tweetId) {
213
+ return await this.graphql("UnpinTweet", {
214
+ body: { variables: { tweet_id: tweetId } },
215
+ });
216
+ }
217
+
218
+ export async function get(tweetId) {
219
+ const res = await this.graphql("TweetResultByRestId", {
220
+ variables: {
221
+ tweetId,
222
+ withCommunity: false,
223
+ includePromotedContent: false,
224
+ withVoice: false,
225
+ },
226
+ fieldToggles: {
227
+ withArticlePlainText: false,
228
+ withArticleRichContentState: false,
229
+ withAuxiliaryUserLabels: false,
230
+ },
231
+ });
232
+ const tweet = res?.data?.tweetResult?.result;
233
+ return tweet ? parseTweet(tweet) : res;
234
+ }
235
+
236
+ export async function getMany(tweetIds) {
237
+ const res = await this.graphql("TweetResultsByRestIds", {
238
+ variables: {
239
+ tweetIds,
240
+ withCommunity: false,
241
+ includePromotedContent: false,
242
+ withVoice: false,
243
+ },
244
+ fieldToggles: {
245
+ withArticlePlainText: false,
246
+ withArticleRichContentState: false,
247
+ withAuxiliaryUserLabels: false,
248
+ },
249
+ });
250
+ const results = res?.data?.tweetResult || [];
251
+ return Array.isArray(results)
252
+ ? results.map((r) => (r?.result ? parseTweet(r.result) : r))
253
+ : res;
254
+ }
255
+
256
+ export async function detail(tweetId, opts = {}) {
257
+ return await this.graphql("TweetDetail", {
258
+ variables: {
259
+ focalTweetId: tweetId,
260
+ with_rux_injections: false,
261
+ rankingMode: "Relevance",
262
+ includePromotedContent: true,
263
+ withCommunity: true,
264
+ withQuickPromoteEligibilityTweetFields: true,
265
+ withBirdwatchNotes: true,
266
+ withVoice: true,
267
+ ...opts.variables,
268
+ },
269
+ fieldToggles: {
270
+ withArticlePlainText: false,
271
+ withArticleRichContentState: false,
272
+ withAuxiliaryUserLabels: false,
273
+ },
274
+ });
275
+ }
276
+
277
+ export async function editHistory(tweetId) {
278
+ return await this.graphql("TweetEditHistory", {
279
+ variables: { tweetId, withQuickPromoteEligibilityTweetFields: true },
280
+ });
281
+ }
282
+
283
+ export async function retweeters(tweetId, opts = {}) {
284
+ return await this.graphql("Retweeters", {
285
+ variables: {
286
+ tweetId,
287
+ count: opts.count || 20,
288
+ cursor: opts.cursor,
289
+ includePromotedContent: false,
290
+ },
291
+ });
292
+ }
293
+
294
+ export async function highlight(tweetId) {
295
+ return await this.graphql("CreateHighlight", {
296
+ body: { variables: { tweet_id: tweetId } },
297
+ });
298
+ }
299
+
300
+ export async function unhighlight(tweetId) {
301
+ return await this.graphql("DeleteHighlight", {
302
+ body: { variables: { tweet_id: tweetId } },
303
+ });
304
+ }
305
+
306
+ export async function schedule(text, scheduledAt, opts = {}) {
307
+ return await this.graphql("CreateScheduledTweet", {
308
+ body: {
286
309
  variables: {
287
- tweetId,
288
- count: opts.count || 20,
289
- cursor: opts.cursor,
290
- includePromotedContent: false,
291
- },
292
- });
293
- },
294
-
295
- async highlight(tweetId) {
296
- return await client.graphql("CreateHighlight", {
297
- body: { variables: { tweet_id: tweetId } },
298
- });
299
- },
300
-
301
- async unhighlight(tweetId) {
302
- return await client.graphql("DeleteHighlight", {
303
- body: { variables: { tweet_id: tweetId } },
304
- });
305
- },
306
-
307
- async schedule(text, scheduledAt, opts = {}) {
308
- return await client.graphql("CreateScheduledTweet", {
309
- body: {
310
- variables: {
311
- post_tweet_request: {
312
- status: text,
313
- ...(opts.mediaIds ? { media_ids: opts.mediaIds } : {}),
314
- ...(opts.replyTo ? { in_reply_to_status_id: opts.replyTo } : {}),
315
- auto_populate_reply_metadata: true,
316
- },
317
- execute_at: Math.floor(new Date(scheduledAt).getTime() / 1000),
310
+ post_tweet_request: {
311
+ status: text,
312
+ ...(opts.mediaIds ? { media_ids: opts.mediaIds } : {}),
313
+ ...(opts.replyTo ? { in_reply_to_status_id: opts.replyTo } : {}),
314
+ auto_populate_reply_metadata: true,
318
315
  },
316
+ execute_at: Math.floor(new Date(scheduledAt).getTime() / 1000),
319
317
  },
320
- });
321
- },
322
-
323
- async deleteScheduled(scheduledTweetId) {
324
- return await client.graphql("DeleteScheduledTweet", {
325
- body: { variables: { scheduled_tweet_id: scheduledTweetId } },
326
- });
327
- },
328
-
329
- async getScheduled() {
330
- return await client.graphql("FetchScheduledTweets", {
331
- variables: {},
332
- });
333
- },
334
-
335
- async moderate(tweetId) {
336
- return await client.graphql("ModerateTweet", {
337
- body: { variables: { tweet_id: tweetId } },
338
- });
339
- },
340
-
341
- async unmoderate(tweetId) {
342
- return await client.graphql("UnmoderateTweet", {
343
- body: { variables: { tweet_id: tweetId } },
344
- });
345
- },
346
-
347
- async pinReply(tweetId) {
348
- return await client.graphql("PinReply", {
349
- body: { variables: { tweet_id: tweetId } },
350
- });
351
- },
352
-
353
- async unpinReply(tweetId) {
354
- return await client.graphql("UnpinReply", {
355
- body: { variables: { tweet_id: tweetId } },
356
- });
357
- },
358
-
359
- async setConversationControl(tweetId, mode) {
360
- return await client.graphql("ConversationControlChange", {
361
- body: { variables: { tweet_id: tweetId, mode } },
362
- });
363
- },
364
-
365
- async removeConversationControl(tweetId) {
366
- return await client.graphql("ConversationControlDelete", {
367
- body: { variables: { tweet_id: tweetId } },
368
- });
369
- },
370
-
371
- async unmention(tweetId) {
372
- return await client.graphql("UnmentionUserFromConversation", {
373
- body: { variables: { tweet_id: tweetId } },
374
- });
375
- },
376
-
377
- async createThread(items) {
378
- if (!Array.isArray(items) || items.length < 2)
379
- throw new Error("a thread must have at least 2 tweets");
380
-
381
- const tweets = [];
382
- let lastId = null;
383
-
384
- for (const item of items) {
385
- const opts = typeof item === "string" ? {} : { ...item };
386
- const text = typeof item === "string" ? item : item.text;
387
-
388
- if (lastId) opts.replyTo = lastId;
389
-
390
- const tweet = await this.create(text, opts);
391
- tweets.push(tweet);
392
- lastId = tweet.id;
393
- }
318
+ },
319
+ });
320
+ }
321
+
322
+ export async function deleteScheduled(scheduledTweetId) {
323
+ return await this.graphql("DeleteScheduledTweet", {
324
+ body: { variables: { scheduled_tweet_id: scheduledTweetId } },
325
+ });
326
+ }
327
+
328
+ export async function getScheduled() {
329
+ return await this.graphql("FetchScheduledTweets", {
330
+ variables: {},
331
+ });
332
+ }
333
+
334
+ export async function moderate(tweetId) {
335
+ return await this.graphql("ModerateTweet", {
336
+ body: { variables: { tweet_id: tweetId } },
337
+ });
338
+ }
339
+
340
+ export async function unmoderate(tweetId) {
341
+ return await this.graphql("UnmoderateTweet", {
342
+ body: { variables: { tweet_id: tweetId } },
343
+ });
344
+ }
345
+
346
+ export async function pinReply(tweetId) {
347
+ return await this.graphql("PinReply", {
348
+ body: { variables: { tweet_id: tweetId } },
349
+ });
350
+ }
351
+
352
+ export async function unpinReply(tweetId) {
353
+ return await this.graphql("UnpinReply", {
354
+ body: { variables: { tweet_id: tweetId } },
355
+ });
356
+ }
357
+
358
+ export async function setConversationControl(tweetId, mode) {
359
+ return await this.graphql("ConversationControlChange", {
360
+ body: { variables: { tweet_id: tweetId, mode } },
361
+ });
362
+ }
363
+
364
+ export async function removeConversationControl(tweetId) {
365
+ return await this.graphql("ConversationControlDelete", {
366
+ body: { variables: { tweet_id: tweetId } },
367
+ });
368
+ }
369
+
370
+ export async function unmention(tweetId) {
371
+ return await this.graphql("UnmentionUserFromConversation", {
372
+ body: { variables: { tweet_id: tweetId } },
373
+ });
374
+ }
375
+
376
+ export async function createThread(items) {
377
+ if (!Array.isArray(items) || items.length < 2)
378
+ throw new Error("a thread must have at least 2 tweets");
379
+
380
+ const tweets = [];
381
+ let lastId = null;
394
382
 
395
- return tweets;
396
- },
383
+ for (const item of items) {
384
+ const opts = typeof item === "string" ? {} : { ...item };
385
+ const text = typeof item === "string" ? item : item.text;
386
+
387
+ if (lastId) opts.replyTo = lastId;
388
+
389
+ const tweet = await create.call(this, text, opts);
390
+ tweets.push(tweet);
391
+ lastId = tweet.id;
392
+ }
393
+
394
+ return tweets;
395
+ }
397
396
 
398
- async similar(tweetId) {
399
- return await client.graphql("SimilarPosts", {
400
- variables: { tweet_id: tweetId },
401
- });
402
- },
403
- });
397
+ export async function similar(tweetId) {
398
+ return await this.graphql("SimilarPosts", {
399
+ variables: { tweet_id: tweetId },
400
+ });
401
+ }