1pub mod atp_agent {
2 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
3 pub struct Session {
4 #[serde(rename = "accessJwt")]
5 access_jwt: String,
6 did: String,
7 handle: String,
9 #[serde(rename = "refreshJwt")]
10 refresh_jwt: String,
11 }
12
13 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
14 struct RefreshSession {
15 #[serde(rename = "accessJwt")]
16 access_jwt: String,
17 #[serde(rename = "refreshJwt")]
18 refresh_jwt: String,
19 did: String,
20 handle: String,
21 }
22
23 #[derive(serde::Serialize)]
24 struct Auth {
25 identifier: String,
26 password: String,
27 }
28
29 #[derive(Debug, Clone)]
30 pub struct AtpAgent {
31 pub service: String,
32 pub session: Option<Session>,
33 }
34
35 #[async_trait::async_trait]
36 pub trait Agent: Sized {
37 fn new(url: String) -> AtpAgent;
39 async fn login(
40 mut self,
41 identifier: String,
42 password: String,
43 ) -> Result<AtpAgent, Box<dyn std::error::Error>>;
44 async fn refresh_session(mut self) -> Result<(), Box<dyn std::error::Error>>;
45 async fn get(
46 mut self,
47 lexicon: String,
48 parameters: serde_json::Value,
49 ) -> Result<serde_json::Value, Box<dyn std::error::Error>>;
50 }
51
52 #[async_trait::async_trait]
53 impl Agent for AtpAgent {
54 fn new(url: String) -> AtpAgent {
68 AtpAgent {
69 service: crate::tools::validate_url(&url),
70 session: None,
71 }
72 }
73
74 async fn login(
76 mut self,
77 identifier: String,
78 password: String,
79 ) -> Result<AtpAgent, Box<dyn std::error::Error>> {
80 let service = &self.service;
81
82 let client = reqwest::Client::builder().build()?;
83
84 let auth = Auth {
85 identifier: identifier.into(),
86 password: password.into(),
87 };
88
89 let session = client
90 .post(format!("{service}xrpc/com.atproto.server.createSession"))
91 .header("User-Agent", "atproto_api/0.1.0")
92 .json(&auth)
93 .send()
94 .await?
95 .json::<serde_json::Value>()
96 .await?;
97
98 let res = match &session.get("error") {
99 Some(x) if !x.is_null() => {
100 let error = &session.get("error").unwrap().to_string().replace("\"", "");
101 let message = &session
102 .get("message")
103 .unwrap()
104 .to_string()
105 .replace("\"", "");
106 panic!(
107 "{}",
108 format!("{service} returns error {error}: {message}").to_string()
109 )
110 }
111 _ => session,
112 };
113
114 let session: Session = serde_json::from_value(res).unwrap();
115
116 self.session = Some(session);
117 Ok(self)
118 }
119
120 async fn refresh_session(mut self) -> Result<(), Box<dyn std::error::Error>> {
122 let session = self.session.unwrap();
123 let refresh = RefreshSession {
124 access_jwt: session.access_jwt,
125 refresh_jwt: session.refresh_jwt,
126 did: session.did,
127 handle: session.handle,
128 };
129 let jwt = &refresh.refresh_jwt;
130 let service = &self.service;
131 let client = reqwest::Client::builder().build()?;
132 let session = client
133 .post(format!("{service}xrpc/com.atproto.server.refreshSession"))
134 .header("User-Agent", "atproto_api/0.1.0")
135 .header("Authorization", format!("Bearer {jwt}"))
136 .query(&refresh)
137 .send()
138 .await?
139 .json::<serde_json::Value>()
140 .await?;
141
142 let res = match &session.get("error") {
143 Some(x) if !x.is_null() => {
144 let error = &session.get("error").unwrap().to_string().replace("\"", "");
145 let message = &session
146 .get("message")
147 .unwrap()
148 .to_string()
149 .replace("\"", "");
150 panic!("{}", format!("{service} returns error {error}: {message}"))
151 }
152 _ => session,
153 };
154
155 let refreshed_session: Session = serde_json::from_value(res).unwrap();
156
157 self.session = Some(refreshed_session);
158 Ok(())
159 }
160
161 async fn get(
162 mut self,
163 lexicon: String,
164 parameters: serde_json::Value,
165 ) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
166 let service = &self.service;
167 let session = &self.session.as_mut().unwrap();
168 let jwt = &session.access_jwt;
169 let client = reqwest::Client::builder().build()?;
170 let res = client
171 .get(format!("{service}xrpc/{lexicon}"))
172 .header("User-Agent", "atproto_api/0.1.0")
173 .header("Authorization", format!("Bearer {jwt}"))
174 .query(¶meters)
175 .send()
176 .await?
177 .json::<serde_json::Value>()
178 .await?;
179
180 let res = match &res.get("error") {
181 Some(x) if !x.is_null() => {
182 let error = &res.get("error").unwrap().to_string().replace("\"", "");
183 let message = &res.get("message").unwrap().to_string().replace("\"", "");
184 panic!("{}", format!("{service} returns error {error}: {message}"))
185 }
186 _ => res,
187 };
188
189 let _refresh_session = self.refresh_session();
190
191 Ok(res)
192 }
193 }
194}