any_type 0.5.0

A library for the Anytype API
Documentation
use crate::api::RequestFailure;
use crate::icons::Icon;
use crate::node;
use serde_json::{Map, Value};

#[derive(Debug, Clone)]
pub enum MemberRole {
    Viewer,
    Editor,
    Owner,
    NoPermission,
    Undefined,
}
impl MemberRole {
    pub fn to_string(&self) -> String {
        match self {
            MemberRole::Editor => "editor".to_string(),
            MemberRole::Owner => "owner".to_string(),
            MemberRole::Viewer => "viewer".to_string(),
            MemberRole::NoPermission => "no_permission".to_string(),
            MemberRole::Undefined => "UNDEFINED".to_string(),
        }
    }
    pub fn from_str(s: &str) -> MemberRole {
        match s {
            "editor" => MemberRole::Editor,
            "owner" => MemberRole::Owner,
            "viewer" => MemberRole::Viewer,
            "no_permission" => MemberRole::NoPermission,
            _ => MemberRole::Undefined,
        }
    }
}

#[derive(Debug, Clone)]
pub enum MemberStatus {
    Active,
    Canceled,
    Declined,
    Joining,
    Removed,
    Removing,
    Undefined,
}
impl MemberStatus {
    pub fn to_string(&self) -> String {
        match self {
            MemberStatus::Active => "active".to_string(),
            MemberStatus::Canceled => "canceled".to_string(),
            MemberStatus::Declined => "declined".to_string(),
            MemberStatus::Joining => "joining".to_string(),
            MemberStatus::Removed => "removed".to_string(),
            MemberStatus::Removing => "removing".to_string(),
            MemberStatus::Undefined => "UNDEFINED".to_string(),
        }
    }
    pub fn from_str(s: &str) -> MemberStatus {
        match s {
            "active" => MemberStatus::Active,
            "canceled" => MemberStatus::Canceled,
            "declined" => MemberStatus::Declined,
            "joining" => MemberStatus::Joining,
            "removed" => MemberStatus::Removed,
            "removing" => MemberStatus::Removing,
            _ => MemberStatus::Undefined,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Member {
    pub global_name: String,
    pub icon: Option<Icon>,
    pub id: String,
    pub identity: String,
    pub name: String,
    pub object: String,
    pub role: MemberRole,
    pub status: MemberStatus,
}
impl Member {
    pub fn to_json(&self) -> Value {
        let mut values = Map::new();
        values.insert(
            "global_name".to_string(),
            Value::String(self.global_name.clone()),
        );
        let icon = Value::Null;
        if self.icon.is_some() {
            self.icon.clone().unwrap().to_json();
        }
        values.insert("icon".to_string(), icon);
        values.insert("id".to_string(), Value::String(self.id.clone()));
        values.insert("name".to_string(), Value::String(self.name.clone()));
        values.insert("object".to_string(), Value::String(self.object.clone()));
        values.insert("role".to_string(), Value::String(self.role.to_string()));
        values.insert("status".to_string(), Value::String(self.status.to_string()));
        Value::Object(values)
    }
    pub(crate) fn from_json(json: Value) -> Self {
        let global_name = json["global_name"].as_str().unwrap().to_string();
        let icon = Icon::from_json(json["icon"].clone());
        let id = json["id"].as_str().unwrap().to_string();
        let identity = json["identity"].as_str().unwrap().to_string();
        let name = json["name"].as_str().unwrap().to_string();
        let object = json["object"].as_str().unwrap().to_string();
        let role = json["role"].as_str().unwrap().to_string();
        let status = json["status"].as_str().unwrap().to_string();
        Member {
            global_name,
            icon,
            id,
            identity,
            name,
            object,
            role: MemberRole::from_str(&role),
            status: MemberStatus::from_str(&status),
        }
    }
    pub(crate) async fn from_response(response: reqwest::Response) -> Self {
        let json_input = response.text().await.unwrap();
        let json: serde_json::Value = serde_json::from_str(json_input.as_ref()).unwrap();
        let t = json["member"].clone();
        Member::from_json(t)
    }
}

#[derive(Debug)]
pub struct ListOfMembers {
    pub members: Vec<Member>,
    pub has_more: bool,
    pub next_offset: usize,
    pub offset: usize,
    pub limit: usize,
    pub total: usize,
}

#[derive(Debug)]
pub struct GetMemberRequest<'a> {
    api_key: &'a str,
    server: &'a str,
    space_id: &'a str,
    member_id: &'a str,
}
impl<'a> GetMemberRequest<'a> {
    pub fn new(api_key: &'a str, server: &'a str) -> Self {
        GetMemberRequest {
            api_key,
            server,
            member_id: "",
            space_id: "",
        }
    }
    pub fn member_id(mut self, member_id: &'a str) -> Self {
        self.member_id = member_id;
        self
    }
    pub fn space_id(mut self, space_id: &'a str) -> Self {
        self.space_id = space_id;
        self
    }
    pub async fn send(&self) -> Result<Member, RequestFailure> {
        let endpoint = format!("/v1/spaces/{}/members/{}", self.space_id, self.member_id);
        match node::get(self.api_key, self.server, &endpoint).await {
            Ok(response) => {
                if response.status() == http::StatusCode::OK {
                    return Ok(Member::from_response(response).await);
                } else {
                    let possible_status: Vec<http::StatusCode> = Vec::from([
                        http::StatusCode::UNAUTHORIZED,
                        http::StatusCode::INTERNAL_SERVER_ERROR,
                    ]);
                    return Err(RequestFailure::api_error(response, possible_status).await);
                }
            }
            Err(e) => Err(RequestFailure::reqwest_error(e)),
        }
    }
}

#[derive(Debug)]
pub struct ListMembersRequest<'a> {
    api_key: &'a str,
    limit: u32,
    offset: u32,
    server: &'a str,
    space_id: &'a str,
}
impl<'a> ListMembersRequest<'a> {
    pub fn new(api_key: &'a str, server: &'a str) -> Self {
        ListMembersRequest {
            api_key,
            limit: 100,
            offset: 0,
            server,
            space_id: "",
        }
    }
    pub fn offset(mut self, offset: u32) -> Self {
        self.offset = offset;
        self
    }
    pub fn limit(mut self, limit: u32) -> Self {
        self.limit = limit;
        self
    }
    pub fn space_id(mut self, space_id: &'a str) -> Self {
        self.space_id = space_id;
        self
    }
    pub async fn send(&self) -> Result<ListOfMembers, RequestFailure> {
        let endpoint = format!(
            "/v1/spaces/{}/members?offset={}&limit={}",
            self.space_id, self.offset, self.limit
        );
        match node::get(self.api_key, self.server, &endpoint).await {
            Ok(response) => {
                if response.status() == http::StatusCode::OK {
                    return Ok(self.response_to_list(response).await);
                } else {
                    let possible_status: Vec<http::StatusCode> = Vec::from([
                        http::StatusCode::UNAUTHORIZED,
                        http::StatusCode::INTERNAL_SERVER_ERROR,
                    ]);
                    return Err(RequestFailure::api_error(response, possible_status).await);
                }
            }
            Err(e) => Err(RequestFailure::reqwest_error(e)),
        }
    }
    async fn response_to_list(&self, response: reqwest::Response) -> ListOfMembers {
        let json_input = response.text().await.unwrap();
        let json: serde_json::Value = serde_json::from_str(json_input.as_ref()).unwrap();
        let received = json["data"].as_array().unwrap();
        let mut data: Vec<Member> = Vec::new();
        for t in 0..received.len() {
            let member_obj = Member::from_json(received[t].clone());
            data.push(member_obj);
        }
        let has_more: bool = json["pagination"]["has_more"].as_bool().unwrap();
        let total = json["pagination"]["total"].as_u64().unwrap() as usize;
        let offset = json["pagination"]["offset"].as_u64().unwrap() as usize;
        let limit = json["pagination"]["limit"].as_u64().unwrap() as usize;
        let next_offset = (offset as usize) + received.len();

        ListOfMembers {
            members: data,
            has_more,
            next_offset,
            offset,
            limit,
            total,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    pub fn test_list_members_request() {
        let request = ListMembersRequest::new("secret_api_key", "server_url")
            .offset(0)
            .limit(42)
            .space_id("lost_in_space");
        let internals = format!("{:#?}", request);
        assert!(internals.contains("api_key: \"secret_api_key"));
        assert!(internals.contains("offset: 0"));
        assert!(internals.contains("limit: 42"));
        assert!(internals.contains("space_id: \"lost_in_space"));
        assert!(internals.contains("server: \"server_url"));
        println!("{}", internals);
    }
}