1#![allow(dead_code)]
2use image::io::Reader;
3use serde::{Deserialize, Deserializer, Serialize};
4use serde_json::Value;
5use std::error::Error;
6use std::io::Cursor;
7use std::rc::Rc;
8use warp::hyper::body::Bytes;
9
10mod oauth;
11pub use oauth::{ApiKey, Token as OauthToken};
12
13pub mod get_info;
14pub mod get_sizes;
15pub mod login;
16pub mod test_login;
17pub mod upload_photo;
18
19static URL_ACCESS: &str = "https://www.flickr.com/services/oauth/access_token";
20static URL_AUTHORIZE: &str = "https://www.flickr.com/services/oauth/authorize";
21static URL_REQUEST: &str = "https://www.flickr.com/services/oauth/request_token";
22
23static URL_API: &str = "https://api.flickr.com/services/rest/";
24
25static URL_UPLOAD: &str = "https://up.flickr.com/services/upload/";
26
27pub use get_sizes::FlickrSize;
28pub use test_login::UserData;
29
30fn deserialize_content<'de, D>(deserializer: D) -> Result<String, D::Error>
42where
43 D: Deserializer<'de>,
44{
45 let v: Value = Deserialize::deserialize(deserializer)?;
46 Ok(v["_content"].as_str().unwrap_or("").to_string())
47}
48
49trait Resultable<T, E> {
50 fn to_result(self) -> Result<T, E>;
51}
52
53#[derive(Deserialize, Debug, Hash)]
55pub struct FlickrError {
56 pub stat: String,
57 pub code: u32,
58 pub message: String,
59}
60
61impl std::error::Error for FlickrError {}
62
63use std::fmt::Display;
64impl Display for FlickrError {
65 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
66 write!(formatter, "{} (code {})", self.message, self.code)
67 }
68}
69
70pub async fn download_image(url: &String) -> Result<Reader<Cursor<Bytes>>, Box<dyn Error>> {
72 let res = reqwest::get(url).await?;
73
74 Ok(Reader::new(Cursor::new(res.bytes().await?)))
75}
76
77#[derive(Clone, Debug)]
78struct FlickrAPIData {
79 client: reqwest::Client,
80 key: ApiKey,
81 token: Option<OauthToken>,
82}
83
84#[derive(Clone, Debug)]
86pub struct FlickrAPI {
87 data: Rc<FlickrAPIData>,
88}
89
90pub struct PhotoRequestBuilder {
91 handle: Rc<FlickrAPIData>,
92}
93
94pub struct TestRequestBuilder {
95 handle: Rc<FlickrAPIData>,
96}
97
98impl FlickrAPI {
99 pub fn new(key: ApiKey) -> Self {
100 let data = Rc::new(FlickrAPIData {
101 client: reqwest::Client::new(),
102 key,
103 token: None,
104 });
105
106 FlickrAPI { data }
107 }
108
109 pub fn with_token(self, token: OauthToken) -> Self {
110 let mut data = (*self.data).clone();
111 data.token = Some(token);
112
113 FlickrAPI {
114 data: Rc::new(data),
115 }
116 }
117
118 pub fn token(&self) -> Option<OauthToken> {
119 self.data.token.clone()
120 }
121
122 pub fn photos(&self) -> PhotoRequestBuilder {
123 PhotoRequestBuilder {
124 handle: self.data.clone(),
125 }
126 }
127
128 pub fn test(&self) -> TestRequestBuilder {
129 TestRequestBuilder {
130 handle: self.data.clone(),
131 }
132 }
133}