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)]
78struct FlickrAPIData {
79 client: reqwest::Client,
80 key: ApiKey,
81 token: Option<OauthToken>,
82}
83
84pub struct FlickrAPI {
86 data: Rc<FlickrAPIData>,
87}
88
89pub struct PhotoRequestBuilder {
90 handle: Rc<FlickrAPIData>,
91}
92
93pub struct TestRequestBuilder {
94 handle: Rc<FlickrAPIData>,
95}
96
97impl FlickrAPI {
98 pub fn new(key: ApiKey) -> Self {
99 let data = Rc::new(FlickrAPIData {
100 client: reqwest::Client::new(),
101 key,
102 token: None,
103 });
104
105 FlickrAPI { data }
106 }
107
108 pub fn with_token(self, token: OauthToken) -> Self {
109 let mut data = (*self.data).clone();
110 data.token = Some(token);
111
112 FlickrAPI {
113 data: Rc::new(data),
114 }
115 }
116
117 pub fn token(&self) -> Option<OauthToken> {
118 self.data.token.clone()
119 }
120
121 pub fn photos(&self) -> PhotoRequestBuilder {
122 PhotoRequestBuilder {
123 handle: self.data.clone(),
124 }
125 }
126
127 pub fn test(&self) -> TestRequestBuilder {
128 TestRequestBuilder {
129 handle: self.data.clone(),
130 }
131 }
132}