// zotapi - Rust wrapper for Zot API as implemented by Hubzilla // Copyright (C) 2023 Harald Eilertsen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . use crate::{ Channel, Error, }; use url::Url; use reqwest::{ self, header::{ACCEPT}, }; use serde::Serialize; #[derive(Debug)] pub struct ZotApi { client: reqwest::Client, base_url: Url, channel: String, pw: String, } pub fn new(url: &str, channel: &str, pw: &str) -> ZotApi { ZotApi { client: reqwest::Client::new(), base_url: Url::parse(url).unwrap().join("api/z/1.0/").unwrap(), channel: String::from(channel), pw: String::from(pw), } } impl ZotApi { /** * Returns the channel object of the logged in channel. */ pub async fn verify(&self) -> Result> { let raw = self.get("verify").send().await?.text().await?; let mut channel: Channel = serde_json::from_str(&raw)?; channel.xchan = serde_json::from_str(&raw)?; Ok(channel) } /** * Returns the version of the server. * * This API can be invoked without authentication. */ pub async fn version(&self) -> Result> { Ok(self.get("version").send().await?.text().await?) } /** * Returns the list of channels for this account. */ pub async fn channel_list(&self) -> Result, Box> { let json = self.get("channel/list") .send().await? .text().await?; Ok(serde_json::from_str(&json)?) } /** * Return the channel stream as json. */ pub async fn channel_stream(&self) -> Result { let response = self.get("channel/stream").send().await?; if response.status().is_success() { Ok(response.text().await?) } else { Err(response.status().into()) } } /** * Return all data from channel for export. */ pub async fn channel_export(&self) -> Result> { Ok(self.get("channel/export/basic").send().await?.text().await?) } pub async fn abook_list(&self) -> Result { Ok(self.get("abook").send().await?.text().await?) } /// Return a RequestBuilder object that's set up with the correct /// path and headers for performing a zot api request. pub fn get(&self, path: &str) -> reqwest::RequestBuilder { self.client.get(&self.url(path, &())) .header(ACCEPT, "application/json") .basic_auth(self.channel.clone(), Some(self.pw.clone())) } fn url(&self, path: &str, args: &T) -> String where T: Serialize + std::fmt::Debug, { let mut r = self.base_url.clone().join(path).unwrap(); if let Ok(a) = serde_qs::to_string(dbg!(args)) { r.set_query(Some(&a)); } r.to_string() } }