1use crate::api::client::TwitterClient;
2use crate::auth::user_auth::TwitterUserAuth;
3use crate::constants::BEARER_TOKEN;
4use crate::error::Result;
5use crate::error::TwitterError;
6use crate::models::{Profile, Tweet};
7use crate::search::{fetch_search_tweets, SearchMode};
8use crate::timeline::v1::{QueryProfilesResponse, QueryTweetsResponse};
9use crate::timeline::v2::QueryTweetsResponse as V2QueryTweetsResponse;
10use serde_json::Value;
11use crate::messages::DirectMessagesResponse;
12
13pub struct Scraper {
14 pub twitter_client: TwitterClient,
15}
16
17impl Scraper {
18 pub async fn new() -> Result<Self> {
19 let auth = Box::new(TwitterUserAuth::new(BEARER_TOKEN.to_string()).await?);
20 let twitter_client = TwitterClient::new(auth.clone())?;
21 Ok(Self { twitter_client })
22 }
23
24 pub async fn login(
25 &mut self,
26 username: String,
27 password: String,
28 email: Option<String>,
29 two_factor_secret: Option<String>,
30 ) -> Result<()> {
31 if let Some(user_auth) = self.twitter_client.auth.as_any().downcast_ref::<TwitterUserAuth>() {
32 let mut auth = user_auth.clone();
33 auth.login(
34 &self.twitter_client.client,
35 &username,
36 &password,
37 email.as_deref(),
38 two_factor_secret.as_deref(),
39 )
40 .await?;
41
42 self.twitter_client.auth = Box::new(auth.clone());
43 Ok(())
45 } else {
46 Err(TwitterError::Auth("Invalid auth type".into()))
47 }
48 }
49
50 pub async fn get_profile(&self, username: &str) -> Result<crate::models::Profile> {
51 crate::profile::get_profile(&self.twitter_client, username).await
52 }
53 pub async fn send_tweet(
54 &self,
55 text: &str,
56 reply_to: Option<&str>,
57 media_data: Option<Vec<(Vec<u8>, String)>>,
58 ) -> Result<Value> {
59 crate::tweets::create_tweet_request(&self.twitter_client, text, reply_to, media_data).await
60 }
61
62 pub async fn get_home_timeline(
63 &self,
64 count: i32,
65 seen_tweet_ids: Vec<String>,
66 ) -> Result<Vec<Value>> {
67 crate::timeline::home::fetch_home_timeline(&self.twitter_client, count, seen_tweet_ids).await
68 }
69
70 pub async fn save_cookies(&self, cookie_file: &str) -> Result<()> {
71 if let Some(user_auth) = self.twitter_client.auth.as_any().downcast_ref::<TwitterUserAuth>() {
72 user_auth.save_cookies_to_file(cookie_file).await
73 } else {
74 Err(TwitterError::Auth("Invalid auth type".into()))
75 }
76 }
77
78 pub async fn get_cookie_string(&self) -> Result<String> {
79 if let Some(user_auth) = self.twitter_client.auth.as_any().downcast_ref::<TwitterUserAuth>() {
80 user_auth.get_cookie_string().await
81 } else {
82 Err(TwitterError::Auth("Invalid auth type".into()))
83 }
84 }
85
86 pub async fn set_cookies(&mut self, json_str: &str) -> Result<()> {
87 if let Some(user_auth) = self.twitter_client.auth.as_any().downcast_ref::<TwitterUserAuth>() {
88 let mut auth = user_auth.clone();
89 auth.set_cookies(json_str).await?;
90
91 self.twitter_client.auth = Box::new(auth.clone());
92 self.twitter_client = TwitterClient::new(Box::new(auth))?;
93 Ok(())
94 } else {
95 Err(TwitterError::Auth("Invalid auth type".into()))
96 }
97 }
98
99 pub async fn set_from_cookie_string(&mut self, cookie_string: &str) -> Result<()> {
100 if let Some(user_auth) = self.twitter_client.auth.as_any().downcast_ref::<TwitterUserAuth>() {
101 let mut auth = user_auth.clone();
102 auth.set_from_cookie_string(cookie_string).await?;
103
104 self.twitter_client.auth = Box::new(auth.clone());
105 self.twitter_client = TwitterClient::new(Box::new(auth))?;
106 Ok(())
107 } else {
108 Err(TwitterError::Auth("Invalid auth type".into()))
109 }
110 }
111
112 pub async fn get_followers(
113 &self,
114 user_id: &str,
115 count: i32,
116 cursor: Option<String>,
117 ) -> Result<(Vec<Profile>, Option<String>)> {
118 crate::relationships::get_followers(&self.twitter_client, user_id, count, cursor).await
119 }
120
121 pub async fn get_following(
122 &self,
123 user_id: &str,
124 count: i32,
125 cursor: Option<String>,
126 ) -> Result<(Vec<Profile>, Option<String>)> {
127 crate::relationships::get_following(&self.twitter_client, user_id, count, cursor).await
128 }
129
130 pub async fn follow_user(&self, username: &str) -> Result<()> {
131 crate::relationships::follow_user(&self.twitter_client, username).await
132 }
133
134 pub async fn unfollow_user(&self, username: &str) -> Result<()> {
135 crate::relationships::unfollow_user(&self.twitter_client, username).await
136 }
137
138 pub async fn send_quote_tweet(
139 &self,
140 text: &str,
141 quoted_tweet_id: &str,
142 media_data: Option<Vec<(Vec<u8>, String)>>,
143 ) -> Result<Value> {
144 crate::tweets::create_quote_tweet(&self.twitter_client, text, quoted_tweet_id, media_data).await
145 }
146
147 pub async fn fetch_tweets_and_replies(
148 &self,
149 username: &str,
150 max_tweets: i32,
151 cursor: Option<&str>,
152 ) -> Result<V2QueryTweetsResponse> {
153 crate::tweets::fetch_tweets_and_replies(&self.twitter_client, username, max_tweets, cursor).await
154 }
155 pub async fn fetch_tweets_and_replies_by_user_id(
156 &self,
157 user_id: &str,
158 max_tweets: i32,
159 cursor: Option<&str>,
160 ) -> Result<V2QueryTweetsResponse> {
161 crate::tweets::fetch_tweets_and_replies_by_user_id(&self.twitter_client, user_id, max_tweets, cursor).await
162 }
163 pub async fn fetch_list_tweets(
164 &self,
165 list_id: &str,
166 max_tweets: i32,
167 cursor: Option<&str>,
168 ) -> Result<Value> {
169 crate::tweets::fetch_list_tweets(&self.twitter_client, list_id, max_tweets, cursor).await
170 }
171
172 pub async fn like_tweet(&self, tweet_id: &str) -> Result<Value> {
173 crate::tweets::like_tweet(&self.twitter_client, tweet_id).await
174 }
175
176 pub async fn retweet(&self, tweet_id: &str) -> Result<Value> {
177 crate::tweets::retweet(&self.twitter_client, tweet_id).await
178 }
179
180 pub async fn create_long_tweet(
181 &self,
182 text: &str,
183 reply_to: Option<&str>,
184 media_ids: Option<Vec<String>>,
185 ) -> Result<Value> {
186 crate::tweets::create_long_tweet(&self.twitter_client, text, reply_to, media_ids).await
187 }
188
189 pub async fn get_tweet(&self, id: &str) -> Result<Tweet> {
190 crate::tweets::get_tweet(&self.twitter_client, id).await
191 }
192
193 pub async fn search_tweets(
194 &self,
195 query: &str,
196 max_tweets: i32,
197 search_mode: SearchMode,
198 cursor: Option<String>,
199 ) -> Result<QueryTweetsResponse> {
200 fetch_search_tweets(&self.twitter_client, query, max_tweets, search_mode, cursor).await
201 }
202
203 pub async fn search_profiles(
204 &self,
205 query: &str,
206 max_profiles: i32,
207 cursor: Option<String>,
208 ) -> Result<QueryProfilesResponse> {
209 crate::search::search_profiles(&self.twitter_client, query, max_profiles, cursor).await
210 }
211
212 pub async fn get_user_tweets(
213 &self,
214 user_id: &str,
215 count: i32,
216 cursor: Option<String>,
217 ) -> Result<V2QueryTweetsResponse> {
218 crate::tweets::fetch_user_tweets(&self.twitter_client, user_id, count, cursor.as_deref()).await
219 }
220
221 pub async fn get_direct_message_conversations(
222 &self,
223 screen_name: &str,
224 cursor: Option<&str>,
225 ) -> Result<DirectMessagesResponse> {
226 crate::messages::get_direct_message_conversations(&self.twitter_client, screen_name, cursor).await
227 }
228
229 pub async fn send_direct_message(
230 &self,
231 conversation_id: &str,
232 text: &str,
233 ) -> Result<Value> {
234 crate::messages::send_direct_message(&self.twitter_client, conversation_id, text).await
235 }
236}