From 93ee81f05e1cb90c79949d5c57b1d7e3c272dd02 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Sun, 26 Mar 2023 22:53:49 +0200 Subject: Implement "verify" API. The verify API call returns a full channel object, including the corresponding xchan. I've added the xchan as a field in the Channel object, instead of having all the fields in one object like it is returned from the API. --- src/bin/zot/main.rs | 21 +++++++ src/lib.rs | 2 + src/verify.rs | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 src/verify.rs diff --git a/src/bin/zot/main.rs b/src/bin/zot/main.rs index a8451b2..70a7984 100644 --- a/src/bin/zot/main.rs +++ b/src/bin/zot/main.rs @@ -34,6 +34,10 @@ async fn main() { (version: crate_version!()) (author: crate_authors!()) (about: "zotapi command line client") + (@subcommand verify => + (about: "Verify") + (@arg raw: --raw "Display raw json payload") + ) (@subcommand channel => (about: "Fetch the channel stream") (@arg raw: --raw "Display raw json payload") @@ -72,12 +76,29 @@ async fn main() { (@arg ATTACH: --attach [FILE] "Attach a file or image to the post") (@arg GROUP: --group [groups] "Limit distribution to the specified group(s) separated by comma") ) + (@subcommand photos => + (about: "Post or get photos or albums") + (@arg UPLOAD: --upload [FILE] requires[ALBUM] "Upload a photo") + (@arg ALBUM: --album +takes_value "The album to upload the photo to") + (@arg DESC: --description +takes_value "A description/title for the photo") + (@arg BODY: --body +takes_value "A longer description/body text") + (@arg POST: --post "Post the photo to the timeline") + (@arg GROUP: --group [groups] "Limit distribution to the specified group(s) separated by comma") + ) ) .get_matches(); let client = zotapi::client(&site, &user, &password); match matches.subcommand() { + ("verify", Some(m)) => { + let r = zotapi::Channel::z(); + if m.is_present("raw") { + println!("{}", r.fetch_raw(&client).await.unwrap()); + } else { + println!("{:?}", r.fetch(&client).await); + } + } ("channel", Some(m)) => { let raw = m.is_present("raw"); zot::channel_stream::fetch(&client, raw).await; diff --git a/src/lib.rs b/src/lib.rs index 357591d..11ca297 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ mod error; mod group; mod item; mod network_stream; +mod verify; mod xchan; pub use abconfig::ABConfig; @@ -32,6 +33,7 @@ pub use error::Error; pub use group::{group, group_members}; pub use item::item; pub use network_stream::network_stream; +pub use verify::Channel; pub use xchan::XChan; #[cfg(test)] diff --git a/src/verify.rs b/src/verify.rs new file mode 100644 index 0000000..8edb2f1 --- /dev/null +++ b/src/verify.rs @@ -0,0 +1,161 @@ +// zotapi - Rust wrapper for the 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::{client::Client, error::Error, XChan}; +use serde::Deserialize; +use std::convert::TryFrom; + +#[derive(Deserialize, Debug)] +pub struct Channel { + #[serde(alias = "channel_id")] + pub id: u32, + + #[serde(alias = "channel_account_id")] + pub account_id: u32, + + #[serde(alias = "channel_primary")] + pub primary: char, + + #[serde(alias = "channel_name")] + pub name: String, + + #[serde(alias = "channel_address")] + pub address: String, + + #[serde(alias = "channel_guid")] + pub guid: String, + + #[serde(alias = "channel_guid_sig")] + pub guid_sig: String, + + #[serde(alias = "channel_hash")] + pub hash: String, + + #[serde(alias = "channel_timezone")] + pub timezone: String, + + #[serde(alias = "channel_location")] + pub location: String, + + #[serde(alias = "channel_theme")] + pub theme: String, + + #[serde(alias = "channel_startpage")] + pub startpage: String, + + #[serde(alias = "channel_pubkey")] + pub pubkey: String, + + #[serde(alias = "channel_prvkey")] + pub prvkey: String, + + #[serde(alias = "channel_notifyflags")] + pub notifyflags: u32, + + #[serde(alias = "channel_pageflags")] + pub pageflags: u32, + + #[serde(alias = "channel_dirdate")] + pub dirdate: String, + + #[serde(alias = "channel_lastpost")] + pub lastpost: String, + + #[serde(alias = "channel_deleted")] + pub deleted: String, + + #[serde(alias = "channel_active")] + pub active: String, + + #[serde(alias = "channel_max_anon_mail")] + pub max_anon_mail: u32, + + #[serde(alias = "channel_max_friend_req")] + pub max_friend_req: u32, + + #[serde(alias = "channel_expire_days")] + pub expire_days: u32, + + #[serde(alias = "channel_passwd_reset")] + pub passwd_reset: String, + + #[serde(alias = "channel_default_group")] + pub default_group: String, + + #[serde(alias = "channel_allow_cid")] + pub allow_cid: String, + + #[serde(alias = "channel_allow_gid")] + pub allow_gid: String, + + #[serde(alias = "channel_deny_cid")] + pub deny_cid: String, + + #[serde(alias = "channel_deny_gid")] + pub deny_gid: String, + + #[serde(alias = "channel_removed")] + pub removed: u32, + + #[serde(alias = "channel_system")] + pub system: u32, + + #[serde(alias = "channel_moved")] + pub moved: String, + + #[serde(alias = "channel_password")] + pub password: String, + + #[serde(alias = "channel_salt")] + pub salt: String, + + #[serde(alias = "channel_portable_id")] + pub portable_id: String, + + #[serde(alias = "channel_xchan", skip)] + pub xchan: XChan, +} + +impl Channel { + pub fn z() -> ChannelRequest { + ChannelRequest::default() + } +} + +impl<'a> TryFrom<&'a str> for Channel { + type Error = Error; + + fn try_from(s: &'a str) -> Result { + Ok(serde_json::from_str(s)?) + } +} + +#[derive(Default)] +pub struct ChannelRequest; + +impl ChannelRequest { + pub async fn fetch_raw(&self, client: &Client) -> Result { + Ok(client.get("verify").send().await?.text().await?) + } + + pub async fn fetch(&self, client: &Client) -> Result { + let raw = self.fetch_raw(&client).await?; + let mut channel: Channel = serde_json::from_str(&raw)?; + channel.xchan = serde_json::from_str(&raw)?; + + Ok(channel) + } +} -- cgit v1.2.3