use crate::models::{CreateMemoRequest, ListMemosResponse, Memo}; use anyhow::Result; use reqwest::Client; #[derive(Clone)] pub struct MemosClient { client: Client, base_url: String, user_token: String, } impl MemosClient { pub fn new(base_url: &str, user_token: &str) -> Result { let base_url = base_url.trim_end_matches('/'); Ok(Self { client: Client::new(), base_url: base_url.to_string(), user_token: user_token.to_string(), }) } pub async fn create_memo(&self, content: &str, visibility: Option<&str>) -> Result { let url = format!("{}/api/v1/memos", self.base_url); let visibility_str = visibility.map(|v| v.to_string()); let request = CreateMemoRequest { content: content.to_string(), state: "STATE_UNSPECIFIED".to_string(), visibility: visibility_str, }; let response = self .client .post(&url) .header("Authorization", format!("Bearer {}", self.user_token)) .header("Content-Type", "application/json") .json(&request) .send() .await?; if !response.status().is_success() { let status = response.status(); let error_text = response.text().await.unwrap_or_default(); anyhow::bail!("Failed to create memo: {} - {}", status, error_text); } let mut memo: Memo = response.json().await?; memo.id = Memo::extract_id(&memo.name); Ok(memo) } pub async fn list_memos(&self, page_size: Option, page_token: Option<&str>) -> Result> { let url = format!("{}/api/v1/memos", self.base_url); let mut request = self .client .get(&url) .header("Authorization", format!("Bearer {}", self.user_token)); if let Some(ps) = page_size { request = request.query(&[("pageSize", ps.to_string())]); } if let Some(token) = page_token { request = request.query(&[("pageToken", token)]); } let response = request.send().await?; if !response.status().is_success() { let status = response.status(); let error_text = response.text().await.unwrap_or_default(); anyhow::bail!("Failed to list memos: {} - {}", status, error_text); } let result: ListMemosResponse = response.json().await?; Ok(result.memos) } pub async fn list_memos_with_token(&self, page_size: Option, page_token: Option<&str>) -> Result { let url = format!("{}/api/v1/memos", self.base_url); let mut request = self .client .get(&url) .header("Authorization", format!("Bearer {}", self.user_token)); if let Some(ps) = page_size { request = request.query(&[("pageSize", ps.to_string())]); } if let Some(token) = page_token { request = request.query(&[("pageToken", token)]); } let response = request.send().await?; if !response.status().is_success() { let status = response.status(); let error_text = response.text().await.unwrap_or_default(); anyhow::bail!("Failed to list memos: {} - {}", status, error_text); } let result: ListMemosResponse = response.json().await?; Ok(result) } pub async fn list_all_memos(&self) -> Result> { let mut all_memos = Vec::new(); let mut page_token: Option = None; let page_size = 100; loop { let response = self.list_memos_with_token(Some(page_size), page_token.as_deref()).await?; let memos = response.memos; if memos.is_empty() { break; } all_memos.extend(memos); page_token = response.next_page_token; if page_token.is_none() || page_token.as_ref().map_or(true, |t| t.is_empty()) { break; } } Ok(all_memos) } }