archive_it_client/
partner.rs1use std::pin::pin;
2
3use futures_core::Stream;
4use futures_util::TryStreamExt;
5use tokio::sync::OnceCell;
6
7use crate::http::{Transport, paginated};
8use crate::models::partner::{Account, Collection};
9use crate::public::CollectionsQuery;
10use crate::{Config, Error, PageOpts};
11
12pub struct PartnerClient {
13 transport: Transport,
14 self_id: OnceCell<u64>,
15}
16
17impl PartnerClient {
18 pub fn new(username: impl Into<String>, password: impl Into<String>) -> Result<Self, Error> {
19 Self::with_config(username, password, Config::api())
20 }
21
22 pub fn with_config(
23 username: impl Into<String>,
24 password: impl Into<String>,
25 cfg: Config,
26 ) -> Result<Self, Error> {
27 Ok(Self {
28 transport: Transport::new(cfg, Some((username.into(), password.into())))?,
29 self_id: OnceCell::new(),
30 })
31 }
32
33 pub async fn my_account(&self) -> Result<Account, Error> {
34 let accounts: Vec<Account> = self.transport.get_json("account", &()).await?;
35 accounts.into_iter().next().ok_or(Error::Empty)
36 }
37
38 pub async fn list_collections(&self, opts: PageOpts) -> Result<Vec<Collection>, Error> {
39 let me = self.cached_self_id().await?;
40 self.transport
41 .get_json("collection", &CollectionsQuery::new(Some(me), opts))
42 .await
43 }
44
45 pub fn collections(&self) -> impl Stream<Item = Result<Collection, Error>> + Send + '_ {
46 paginated(move |opts| self.list_collections(opts))
47 }
48
49 pub async fn get_collection(&self, id: u64) -> Result<Option<Collection>, Error> {
50 let mut stream = pin!(self.collections());
51 while let Some(c) = stream.try_next().await? {
52 if c.id == id {
53 return Ok(Some(c));
54 }
55 }
56 Ok(None)
57 }
58
59 async fn cached_self_id(&self) -> Result<u64, Error> {
60 self.self_id
61 .get_or_try_init(|| async { self.my_account().await.map(|a| a.id) })
62 .await
63 .copied()
64 }
65}