twitter_internal_api/api/params/
search_time_line.rs1use crate::utils::headers::RateLimitHeaders;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5#[derive(Clone, Serialize, Deserialize, Default)]
6#[serde(rename_all = "camelCase")]
7pub struct SearchTimelineParams {
8 pub variables: Variables,
9 pub features: Features,
10 pub field_toggles: FieldToggles,
11}
12#[derive(Clone, Serialize, Deserialize)]
13pub struct Features(Value);
14
15impl Default for Features {
16 fn default() -> Self {
17 Self(serde_json::json!({
18 "articles_preview_enabled": true,
19 "c9s_tweet_anatomy_moderator_badge_enabled": true,
20 "communities_web_enable_tweet_community_results_fetch": true,
21 "creator_subscriptions_quote_tweet_preview_enabled": false,
22 "creator_subscriptions_tweet_preview_api_enabled": true,
23 "freedom_of_speech_not_reach_fetch_enabled": true,
24 "graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
25 "longform_notetweets_consumption_enabled": true,
26 "longform_notetweets_inline_media_enabled": true,
27 "longform_notetweets_rich_text_read_enabled": true,
28 "payments_enabled": false,
29 "premium_content_api_read_enabled": false,
30 "profile_label_improvements_pcf_label_in_post_enabled": true,
31 "responsive_web_edit_tweet_api_enabled": true,
32 "responsive_web_enhance_cards_enabled": false,
33 "responsive_web_graphql_exclude_directive_enabled": true,
34 "responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
35 "responsive_web_graphql_timeline_navigation_enabled": true,
36 "responsive_web_grok_analysis_button_from_backend": true,
37 "responsive_web_grok_analyze_button_fetch_trends_enabled": false,
38 "responsive_web_grok_analyze_post_followups_enabled": true,
39 "responsive_web_grok_image_annotation_enabled": true,
40 "responsive_web_grok_share_attachment_enabled": true,
41 "responsive_web_grok_show_grok_translated_post": false,
42 "responsive_web_jetfuel_frame": false,
43 "responsive_web_media_download_video_enabled": false,
44 "responsive_web_twitter_article_tweet_consumption_enabled": false,
45 "responsive_web_twitter_article_tweet_consumption_enabled": true,
46 "rweb_lists_timeline_redesign_enabled": true,
47 "rweb_tipjar_consumption_enabled": true,
48 "rweb_video_screen_enabled": false,
49 "standardized_nudges_misinfo": true,
50 "tweet_awards_web_tipping_enabled": false,
51 "tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
52 "tweetypie_unmention_optimization_enabled": true,
53 "verified_phone_label_enabled": false,
54 "view_counts_everywhere_api_enabled": true,
55 }))
56 }
57}
58
59#[derive(Clone, Serialize, Deserialize)]
60#[serde(rename_all = "camelCase")]
61#[derive(Default)]
62pub struct FieldToggles {
63 pub with_article_rich_content_state: bool,
64}
65
66#[derive(Clone, Serialize, Deserialize, Default)]
67#[serde(rename_all = "camelCase")]
68pub struct Variables {
69 pub raw_query: String,
70 pub count: u32,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 pub cursor: Option<String>,
73 pub query_source: QuerySource,
74 pub product: Product,
75}
76
77#[derive(Clone, Serialize, Deserialize, Default)]
78pub enum QuerySource {
79 #[serde(rename = "typed_query")]
80 #[default]
81 TypedQuery,
82}
83
84#[derive(Clone, Serialize, Deserialize, Default, Debug, strum::EnumString, strum::Display)]
85pub enum Product {
86 #[default]
87 #[serde(rename = "Top")]
88 Top,
89 #[serde(rename = "Latest")]
90 Latest,
91 #[serde(rename = "Photos")]
92 Photos,
93 #[serde(rename = "People")]
94 People,
95 #[serde(rename = "Videos")]
96 Videos,
97}
98
99impl SearchTimelineParams {
100 pub fn params(&self) -> anyhow::Result<Vec<(&str, String)>> {
101 let params = &[
102 ("variables", serde_json::to_string(&self.variables)?),
103 ("features", serde_json::to_string(&self.features)?),
104 ("fieldToggles", serde_json::to_string(&self.field_toggles)?),
105 ];
106 Ok(params.to_vec())
107 }
108
109 pub fn update_cursor(&mut self, cursor: Option<String>) {
110 if let Some(cursor) = cursor {
111 self.variables.cursor = Some(cursor);
112 }
113 }
114
115 pub fn update_raw_query(&mut self, raw_query: &str) {
116 self.variables.raw_query = raw_query.to_string();
117 }
118
119 pub fn update_count(&mut self, count: u32) {
120 if count > 50 {
121 self.variables.count = 50
122 } else {
123 self.variables.count = count;
124 }
125 }
126
127 pub fn update_product(&mut self, product: Product) {
128 self.variables.product = product;
129 }
130}
131
132#[derive(Deserialize, Serialize, Debug)]
133pub enum SearchTimeLineResponseType {
134 Success,
135 AuthError,
136 RateLimit,
137}
138
139#[derive(Deserialize, Serialize, Debug)]
140pub struct SearchTimeLineResponse {
141 pub response_type: SearchTimeLineResponseType,
142 pub response_content: Option<Value>,
143 pub response_headers: RateLimitHeaders,
144}