aboutsummaryrefslogtreecommitdiffstats
path: root/src/zotapi.rs
blob: a15b51a8ee3be47a39b297409bdb2fa0dfbff584 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// zotapi - Rust wrapper for Zot API as implemented by Hubzilla
// Copyright (C) 2023  Harald Eilertsen <haraldei@anduin.net>
//
// 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 <https://www.gnu.org/licenses/>.

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<Channel, Box<dyn std::error::Error>> {
        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<String, Box<dyn std::error::Error>> {
        Ok(self.get("version").send().await?.text().await?)
    }

    /**
     * Returns the list of channels for this account.
     */
    pub async fn channel_list(&self) -> Result<Vec<String>, Box<dyn std::error::Error>> {
        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<String, Error> {
        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<String, Box<dyn std::error::Error>> {
        Ok(self.get("channel/export/basic").send().await?.text().await?)
    }

    pub async fn abook_list(&self) -> Result<String, Error> {
        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<T>(&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()
    }
}