Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub enum Error {
BadMedia,
NoUserData,
TooManyRequests,
ApiError(String),
Unknown
}

Expand All @@ -16,6 +17,7 @@ impl fmt::Display for Error {
Error::Reqwest(ref err) => write!(f, "HTTP request error: {}", err),
Error::BadMedia => write!(f, "faulty media"),
Error::NoUserData => write!(f, "No user data found"),
Error::ApiError(ref str) => write!(f, "Api Error: {}", str),
Error::Unknown => write!(f, "unknown"),
Error::TooManyRequests => write!(f, "too many reqs"),
}
Expand All @@ -28,6 +30,7 @@ impl error::Error for Error {
Error::Reqwest(ref err) => Some(err),
Error::BadMedia => None,
Error::NoUserData => None,
Error::ApiError(_) => None,
Error::Unknown => None,
Error::TooManyRequests => None,
}
Expand Down
57 changes: 33 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ impl TweetBuilder {

pub mod error;
use error::Error;
use error::Error::ApiError;

#[derive(Debug, Deserialize)]
struct TwitterApiResponse {
Expand Down Expand Up @@ -160,6 +161,18 @@ impl TwitterClient {
.await?)
}

fn collect_errors(&self, response: &TwitterApiResponse) -> Vec<String> {
let mut res = vec![];
if let Some(errors) = &response.errors {
errors.iter().
for_each(|e| res.push(e.message.to_string()));
}
if let Some(detail) = &response.detail {
res.push(detail.to_string());
}
res
}

async fn _request<T: DeserializeOwned>(
&mut self,
method: &str,
Expand All @@ -181,17 +194,14 @@ impl TwitterClient {
match res.data {
Some(data) => Ok(serde_json::from_value(data).unwrap()),
None => {
if let Some(detail) = res.detail {
match detail.as_ref() {
"Too Many Requests" => Err(Error::TooManyRequests),
_ => Err(Error::Unknown),
}
} else if let Some(errors) = res.errors {
println!("got errors: {:?}", errors);
Err(Error::Unknown)
} else {
Err(Error::Unknown)
let error_strings = self.collect_errors(&res);
if error_strings.contains(&String::from("Too Many Requests")) {
return Err(Error::TooManyRequests);
}
if !error_strings.is_empty() {
return Err(ApiError(error_strings.join(" ").to_string()));
}
return Err(Error::Unknown);
}
}
}
Expand Down Expand Up @@ -219,17 +229,14 @@ impl TwitterClient {
match res.data {
Some(data) => Ok(serde_json::from_value(data).unwrap()),
None => {
if let Some(detail) = res.detail {
match detail.as_ref() {
"Too Many Requests" => Err(Error::TooManyRequests),
_ => Err(Error::Unknown),
}
} else if let Some(errors) = res.errors {
println!("got errors: {:?}", errors);
Err(Error::Unknown)
} else {
Err(Error::Unknown)
let error_strings = self.collect_errors(&res);
if error_strings.contains(&String::from("Too Many Requests")) {
return Err(Error::TooManyRequests);
}
if !error_strings.is_empty() {
return Err(ApiError(error_strings.join(" ").to_string()));
}
return Err(Error::Unknown);
}
}
}
Expand Down Expand Up @@ -277,9 +284,10 @@ impl TwitterClient {
&mut self,
path: &str,
filename: Option<String>,
mime: Option<String>
) -> Result<TwitterMediaResponse, Error> {
let file_bytes;
let mime;
let detected_mime: Option<String>;
if path.starts_with("http") {
let media = reqwest::get(path).await?;
let headers = media.headers().clone();
Expand All @@ -290,12 +298,12 @@ impl TwitterClient {
.unwrap()
.to_owned();
file_bytes = media.bytes().await?.to_vec();
mime = content_type_header;
detected_mime = Some(content_type_header);
} else {
match fs::read(path) {
Ok(bytes) => {
file_bytes = bytes;
mime = infer::get(&file_bytes).unwrap().mime_type().to_string();
detected_mime = infer::get(&file_bytes).map(|m| m.mime_type().to_string());
}
_ => return Err(Error::BadMedia),
}
Expand All @@ -319,14 +327,15 @@ impl TwitterClient {
} else {
// chunked media upload
chunked = true;
let media_type = mime.unwrap_or_else(|| detected_mime.expect("Unable to infer media_type and no mime provided"));
let init = self
._multipart_request::<TwitterMediaResponse>(
"POST",
"https://upload.twitter.com/1.1/media/upload.json",
reqwest::multipart::Form::new()
.text("command", "INIT")
.text("total_bytes", len.to_string())
.text("media_type", mime.clone()),
.text("media_type", media_type.clone()),
None,
)
.await;
Expand Down