Skip to main content

archive_it_client/
partner.rs

1use 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}