From e0b960db1a204475583b6ae044fbc1ad8c170740 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 12 Jan 2026 05:09:28 +0000 Subject: [PATCH] fix: repair search and user-tweets requests --- src/lib/twitter-client-features.ts | 1 + src/lib/twitter-client-search.ts | 38 +++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/lib/twitter-client-features.ts b/src/lib/twitter-client-features.ts index 1c5d7ac..64849cc 100644 --- a/src/lib/twitter-client-features.ts +++ b/src/lib/twitter-client-features.ts @@ -248,6 +248,7 @@ export function buildUserTweetsFeatures(): Record { responsive_web_grok_analyze_button_fetch_trends_enabled: false, responsive_web_grok_analyze_post_followups_enabled: true, responsive_web_jetfuel_frame: true, + post_ctas_fetch_enabled: true, responsive_web_grok_share_attachment_enabled: true, responsive_web_grok_annotations_enabled: false, articles_preview_enabled: true, diff --git a/src/lib/twitter-client-search.ts b/src/lib/twitter-client-search.ts index 769315a..0469de6 100644 --- a/src/lib/twitter-client-search.ts +++ b/src/lib/twitter-client-search.ts @@ -14,6 +14,27 @@ export interface TwitterClientSearchMethods { search(query: string, count?: number, options?: SearchFetchOptions): Promise; } +function isQueryIdMismatch(payload: string): boolean { + try { + const parsed = JSON.parse(payload) as { + errors?: Array<{ message?: string; path?: string[]; extensions?: { code?: string } }>; + }; + return ( + parsed.errors?.some((error) => { + if (error?.extensions?.code === 'GRAPHQL_VALIDATION_FAILED') { + return true; + } + if (error?.path?.includes('rawQuery') && /must be defined/i.test(error.message ?? '')) { + return true; + } + return false; + }) ?? false + ); + } catch { + return false; + } +} + export function withSearch>( Base: TBase, ): Mixin { @@ -69,7 +90,13 @@ export function withSearch> if (!response.ok) { const text = await response.text(); - return { success: false as const, error: `HTTP ${response.status}: ${text.slice(0, 200)}`, had404 }; + const shouldRefreshQueryIds = + (response.status === 400 || response.status === 422) && isQueryIdMismatch(text); + return { + success: false as const, + error: `HTTP ${response.status}: ${text.slice(0, 200)}`, + had404: had404 || shouldRefreshQueryIds, + }; } const data = (await response.json()) as { @@ -112,11 +139,16 @@ export function withSearch> }; }; }; - errors?: Array<{ message: string }>; + errors?: Array<{ message: string; extensions?: { code?: string } }>; }; if (data.errors && data.errors.length > 0) { - return { success: false as const, error: data.errors.map((e) => e.message).join(', '), had404 }; + const shouldRefreshQueryIds = data.errors.some((error) => error?.extensions?.code === 'GRAPHQL_VALIDATION_FAILED'); + return { + success: false as const, + error: data.errors.map((e) => e.message).join(', '), + had404: had404 || shouldRefreshQueryIds, + }; } const instructions = data.data?.search_by_raw_query?.search_timeline?.timeline?.instructions;