@the-convocation/twitter-scraper
Advanced tools
Comparing version 0.8.0 to 0.8.1
@@ -1,2 +0,1 @@ | ||
import { TwitterAuth } from './auth'; | ||
type FetchParameters = [input: RequestInfo | URL, init?: RequestInit]; | ||
@@ -31,45 +30,4 @@ export interface FetchTransformOptions { | ||
}; | ||
/** | ||
* Used internally to send HTTP requests to the Twitter API. | ||
* @internal | ||
* | ||
* @param url - The URL to send the request to. | ||
* @param auth - The instance of {@link TwitterAuth} that will be used to authorize this request. | ||
* @param method - The HTTP method used when sending this request. | ||
*/ | ||
export declare function requestApi<T>(url: string, auth: TwitterAuth, method?: 'GET' | 'POST'): Promise<RequestApiResult<T>>; | ||
/** | ||
* @internal | ||
*/ | ||
export declare function addApiFeatures(o: object): { | ||
rweb_lists_timeline_redesign_enabled: boolean; | ||
responsive_web_graphql_exclude_directive_enabled: boolean; | ||
verified_phone_label_enabled: boolean; | ||
creator_subscriptions_tweet_preview_api_enabled: boolean; | ||
responsive_web_graphql_timeline_navigation_enabled: boolean; | ||
responsive_web_graphql_skip_user_profile_image_extensions_enabled: boolean; | ||
tweetypie_unmention_optimization_enabled: boolean; | ||
responsive_web_edit_tweet_api_enabled: boolean; | ||
graphql_is_translatable_rweb_tweet_is_translatable_enabled: boolean; | ||
view_counts_everywhere_api_enabled: boolean; | ||
longform_notetweets_consumption_enabled: boolean; | ||
tweet_awards_web_tipping_enabled: boolean; | ||
freedom_of_speech_not_reach_fetch_enabled: boolean; | ||
standardized_nudges_misinfo: boolean; | ||
longform_notetweets_rich_text_read_enabled: boolean; | ||
responsive_web_enhance_cards_enabled: boolean; | ||
subscriptions_verification_info_enabled: boolean; | ||
subscriptions_verification_info_reason_enabled: boolean; | ||
subscriptions_verification_info_verified_since_enabled: boolean; | ||
super_follow_badge_privacy_enabled: boolean; | ||
super_follow_exclusive_tweet_notifications_enabled: boolean; | ||
super_follow_tweet_api_enabled: boolean; | ||
super_follow_user_api_enabled: boolean; | ||
android_graphql_skip_api_media_color_palette: boolean; | ||
creator_subscriptions_subscription_count_enabled: boolean; | ||
blue_business_profile_image_shape_enabled: boolean; | ||
unified_cards_ad_metadata_container_dynamic_card_content_query_enabled: boolean; | ||
}; | ||
export declare function addApiParams(params: URLSearchParams, includeTweetReplies: boolean): URLSearchParams; | ||
export {}; | ||
//# sourceMappingURL=api.d.ts.map |
@@ -11,3 +11,2 @@ "use strict"; | ||
* @internal | ||
* | ||
* @param url - The URL to send the request to. | ||
@@ -71,5 +70,3 @@ * @param auth - The instance of {@link TwitterAuth} that will be used to authorize this request. | ||
exports.requestApi = requestApi; | ||
/** | ||
* @internal | ||
*/ | ||
/** @internal */ | ||
function addApiFeatures(o) { | ||
@@ -76,0 +73,0 @@ return { |
@@ -36,8 +36,2 @@ import { Cookie } from 'tough-cookie'; | ||
/** | ||
* Initializes auth properties using a guest token. | ||
* Used when creating a new instance of this class, and when logging out. | ||
* @internal | ||
*/ | ||
private useGuestAuth; | ||
/** | ||
* Fetches a Twitter profile. | ||
@@ -44,0 +38,0 @@ * @param username The Twitter username of the profile to fetch, without an `@` at the beginning. |
@@ -213,3 +213,8 @@ "use strict"; | ||
getTweet(id) { | ||
return (0, tweets_1.getTweet)(id, this.auth); | ||
if (this.auth instanceof auth_user_1.TwitterUserAuth) { | ||
return (0, tweets_1.getTweet)(id, this.auth); | ||
} | ||
else { | ||
return (0, tweets_1.getTweetAnonymous)(id, this.auth); | ||
} | ||
} | ||
@@ -216,0 +221,0 @@ /** |
@@ -10,2 +10,3 @@ import { LegacyUserRaw } from './profile'; | ||
export interface TimelineEntryItemContentRaw { | ||
itemType?: string; | ||
tweetDisplayType?: string; | ||
@@ -15,2 +16,5 @@ tweetResult?: { | ||
}; | ||
tweet_results?: { | ||
result?: TimelineResultRaw; | ||
}; | ||
userDisplayType?: string; | ||
@@ -31,3 +35,3 @@ user_results?: { | ||
}[]; | ||
content?: TimelineEntryItemContentRaw; | ||
itemContent?: TimelineEntryItemContentRaw; | ||
}; | ||
@@ -62,3 +66,3 @@ } | ||
export interface TimelineInstruction { | ||
entries: TimelineEntryRaw[]; | ||
entries?: TimelineEntryRaw[]; | ||
entry?: TimelineEntryRaw; | ||
@@ -71,5 +75,5 @@ type?: string; | ||
result?: { | ||
timeline_response?: { | ||
timeline_v2?: { | ||
timeline?: { | ||
instructions: TimelineInstruction[]; | ||
instructions?: TimelineInstruction[]; | ||
}; | ||
@@ -83,3 +87,3 @@ }; | ||
data?: { | ||
timeline_response?: { | ||
threaded_conversation_with_injections_v2?: { | ||
instructions?: TimelineInstruction[]; | ||
@@ -86,0 +90,0 @@ }; |
@@ -141,4 +141,3 @@ "use strict"; | ||
const tweets = []; | ||
const instructions = timeline.data?.user?.result?.timeline_response?.timeline?.instructions ?? | ||
[]; | ||
const instructions = timeline.data?.user?.result?.timeline_v2?.timeline?.instructions ?? []; | ||
for (const instruction of instructions) { | ||
@@ -162,4 +161,4 @@ const entries = instruction.entries ?? []; | ||
} | ||
if (entryContent.content) { | ||
parseAndPush(tweets, entryContent.content, idStr); | ||
if (entryContent.itemContent) { | ||
parseAndPush(tweets, entryContent.itemContent, idStr); | ||
} | ||
@@ -172,3 +171,3 @@ } | ||
function parseTimelineEntryItemContentRaw(content, entryId, isConversation = false) { | ||
const result = content.tweetResult?.result; | ||
const result = content.tweet_results?.result ?? content.tweetResult?.result; | ||
if (result?.__typename === 'Tweet') { | ||
@@ -201,7 +200,8 @@ if (result.legacy) { | ||
const tweets = []; | ||
const instructions = conversation.data?.timeline_response?.instructions ?? []; | ||
const instructions = conversation.data?.threaded_conversation_with_injections_v2?.instructions ?? | ||
[]; | ||
for (const instruction of instructions) { | ||
const entries = instruction.entries ?? []; | ||
for (const entry of entries) { | ||
const entryContent = entry.content?.content; | ||
const entryContent = entry.content?.itemContent; | ||
if (entryContent) { | ||
@@ -208,0 +208,0 @@ parseAndPush(tweets, entryContent, entry.entryId, true); |
@@ -109,2 +109,3 @@ import { TwitterAuth } from './auth'; | ||
export declare function getTweet(id: string, auth: TwitterAuth): Promise<Tweet | null>; | ||
export declare function getTweetAnonymous(id: string, auth: TwitterAuth): Promise<Tweet | null>; | ||
//# sourceMappingURL=tweets.d.ts.map |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getTweet = exports.getLatestTweet = exports.getTweetsWhere = exports.getTweetWhere = exports.getTweetsByUserId = exports.getTweets = exports.fetchTweets = exports.features = void 0; | ||
exports.getTweetAnonymous = exports.getTweet = exports.getLatestTweet = exports.getTweetsWhere = exports.getTweetWhere = exports.getTweetsByUserId = exports.getTweets = exports.fetchTweets = exports.features = void 0; | ||
const api_1 = require("./api"); | ||
@@ -11,3 +8,3 @@ const profile_1 = require("./profile"); | ||
const timeline_async_1 = require("./timeline-async"); | ||
const json_stable_stringify_1 = __importDefault(require("json-stable-stringify")); | ||
const api_data_1 = require("./api-data"); | ||
exports.features = (0, api_1.addApiFeatures)({ | ||
@@ -24,38 +21,10 @@ interactive_text_enabled: true, | ||
} | ||
const variables = { | ||
userId: userId, | ||
count: maxTweets, | ||
includePromotedContent: false, | ||
withQuickPromoteEligibilityTweetFields: true, | ||
withVoice: true, | ||
withV2Timeline: true, | ||
}; | ||
const userTweetsRequest = api_data_1.apiRequestFactory.createUserTweetsRequest(); | ||
userTweetsRequest.variables.userId = userId; | ||
userTweetsRequest.variables.count = maxTweets; | ||
userTweetsRequest.variables.includePromotedContent = false; // true on the website | ||
if (cursor != null && cursor != '') { | ||
variables['cursor'] = cursor; | ||
userTweetsRequest.variables['cursor'] = cursor; | ||
} | ||
const params = new URLSearchParams(); | ||
params.set('variables', (0, json_stable_stringify_1.default)(variables)); | ||
params.set('features', (0, json_stable_stringify_1.default)({ | ||
rweb_lists_timeline_redesign_enabled: true, | ||
responsive_web_graphql_exclude_directive_enabled: true, | ||
verified_phone_label_enabled: false, | ||
creator_subscriptions_tweet_preview_api_enabled: true, | ||
responsive_web_graphql_timeline_navigation_enabled: true, | ||
responsive_web_graphql_skip_user_profile_image_extensions_enabled: false, | ||
tweetypie_unmention_optimization_enabled: true, | ||
responsive_web_edit_tweet_api_enabled: true, | ||
graphql_is_translatable_rweb_tweet_is_translatable_enabled: true, | ||
view_counts_everywhere_api_enabled: true, | ||
longform_notetweets_consumption_enabled: true, | ||
responsive_web_twitter_article_tweet_consumption_enabled: false, | ||
tweet_awards_web_tipping_enabled: false, | ||
freedom_of_speech_not_reach_fetch_enabled: true, | ||
standardized_nudges_misinfo: true, | ||
tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true, | ||
longform_notetweets_rich_text_read_enabled: true, | ||
longform_notetweets_inline_media_enabled: true, | ||
responsive_web_media_download_video_enabled: false, | ||
responsive_web_enhance_cards_enabled: false, | ||
})); | ||
const res = await (0, api_1.requestApi)(`https://twitter.com/i/api/graphql/XicnWRbyQ3WgVY__VataBQ/UserTweets?${params.toString()}`, auth); | ||
const res = await (0, api_1.requestApi)(userTweetsRequest.toRequestUrl(), auth); | ||
if (!res.success) { | ||
@@ -124,35 +93,22 @@ throw res.err; | ||
async function getTweet(id, auth) { | ||
const variables = { | ||
tweetId: id, | ||
withCommunity: false, | ||
includePromotedContent: false, | ||
withVoice: false, | ||
}; | ||
const params = new URLSearchParams(); | ||
params.set('features', (0, json_stable_stringify_1.default)({ | ||
creator_subscriptions_tweet_preview_api_enabled: true, | ||
tweetypie_unmention_optimization_enabled: true, | ||
responsive_web_edit_tweet_api_enabled: true, | ||
graphql_is_translatable_rweb_tweet_is_translatable_enabled: true, | ||
view_counts_everywhere_api_enabled: true, | ||
longform_notetweets_consumption_enabled: true, | ||
responsive_web_twitter_article_tweet_consumption_enabled: false, | ||
tweet_awards_web_tipping_enabled: false, | ||
freedom_of_speech_not_reach_fetch_enabled: true, | ||
standardized_nudges_misinfo: true, | ||
tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true, | ||
longform_notetweets_rich_text_read_enabled: true, | ||
longform_notetweets_inline_media_enabled: true, | ||
responsive_web_graphql_exclude_directive_enabled: true, | ||
verified_phone_label_enabled: false, | ||
responsive_web_media_download_video_enabled: false, | ||
responsive_web_graphql_skip_user_profile_image_extensions_enabled: false, | ||
responsive_web_graphql_timeline_navigation_enabled: true, | ||
responsive_web_enhance_cards_enabled: false, | ||
})); | ||
params.set('variables', (0, json_stable_stringify_1.default)(variables)); | ||
const res = await (0, api_1.requestApi)(`https://twitter.com/i/api/graphql/0hWvDhmW8YQ-S_ib3azIrw/TweetResultByRestId?${params.toString()}`, auth); | ||
const tweetDetailRequest = api_data_1.apiRequestFactory.createTweetDetailRequest(); | ||
tweetDetailRequest.variables.focalTweetId = id; | ||
const res = await (0, api_1.requestApi)(tweetDetailRequest.toRequestUrl(), auth); | ||
if (!res.success) { | ||
throw res.err; | ||
} | ||
if (!res.value) { | ||
return null; | ||
} | ||
const tweets = (0, timeline_v2_1.parseThreadedConversation)(res.value); | ||
return tweets.find((tweet) => tweet.id === id) ?? null; | ||
} | ||
exports.getTweet = getTweet; | ||
async function getTweetAnonymous(id, auth) { | ||
const tweetResultByRestIdRequest = api_data_1.apiRequestFactory.createTweetResultByRestIdRequest(); | ||
tweetResultByRestIdRequest.variables.tweetId = id; | ||
const res = await (0, api_1.requestApi)(tweetResultByRestIdRequest.toRequestUrl(), auth); | ||
if (!res.success) { | ||
throw res.err; | ||
} | ||
if (!res.value.data) { | ||
@@ -163,3 +119,3 @@ return null; | ||
} | ||
exports.getTweet = getTweet; | ||
exports.getTweetAnonymous = getTweetAnonymous; | ||
//# sourceMappingURL=tweets.js.map |
@@ -5,3 +5,3 @@ { | ||
"keywords": ["x", "twitter", "scraper"], | ||
"version": "0.8.0", | ||
"version": "0.8.1", | ||
"main": "dist/_module.js", | ||
@@ -8,0 +8,0 @@ "repository": "https://github.com/the-convocation/twitter-scraper.git", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
230728
83
3210
4