mutiny-rs 0.4.0

A Rust API wrapper for the Stoat chat platform.
Documentation
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::context::Context;
use crate::http::HttpError;
use crate::http::routing::Route;
use crate::model::message::Message;
use crate::model::ready::Member;
use crate::model::user::User;

pub struct FetchMessagesBuilder<'a> {
    pub(crate) limit: Option<usize>,
    pub(crate) before: Option<String>,
    pub(crate) after: Option<String>,
    pub(crate) sort: Option<Sort>,
    pub(crate) nearby: Option<String>,
    pub(crate) include_users: Option<bool>,
    pub(crate) channel_id: String,
    pub(crate) ctx: &'a Context,
}
#[derive(Serialize)]
struct FetchMessagesQuery<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    limit: Option<usize>,
    #[serde(skip_serializing_if = "Option::is_none")]
    before: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    after: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    sort: Option<Sort>,
    #[serde(skip_serializing_if = "Option::is_none")]
    nearby: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    include_users: Option<bool>,
}
#[derive(Debug, Clone, Copy, Serialize)]
pub enum Sort {
    Relevance,
    Latest,
    Oldest,
}
#[derive(Debug, Deserialize)]
pub struct MessageSearchResponse {
    pub messages: Vec<Message>,
    #[serde(default)]
    pub users: Vec<User>,
    #[serde(default)]
    pub members: Vec<Member>,
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum MessageFetchResult {
    MessagesOnly(Vec<Message>),
    WithUsersAndMembers(MessageSearchResponse),
}
impl<'a> FetchMessagesBuilder<'a> {
    pub fn limit(mut self, limit: usize) -> Self {
        self.limit = Some(limit);
        self
    }
    pub fn before(mut self, before: impl Into<String>) -> Self {
        self.before = Some(before.into());
        self
    }
    pub fn after(mut self, after: impl Into<String>) -> Self {
        self.after = Some(after.into());
        self
    }
    pub fn sort(mut self, sort: Sort) -> Self {
        self.sort = Some(sort);
        self
    }
    pub fn nearby(mut self, nearby: impl Into<String>) -> Self {
        self.nearby = Some(nearby.into());
        self
    }
    pub fn include_users(mut self, include_users: bool) -> Self {
        self.include_users = Some(include_users);
        self
    }
    pub async fn execute(&self) -> Result<Vec<Message>, HttpError> {
        let query = FetchMessagesQuery {
            limit: self.limit,
            before: self.before.as_deref(),
            after: self.after.as_deref(),
            sort: self.sort,
            nearby: self.nearby.as_deref(),
            include_users: self.include_users,
        };

        let route = Route::FetchMessages { channel_id: &self.channel_id };

        let result = self.ctx.http.request::<(), FetchMessagesQuery, MessageFetchResult>(route, None, Some(&query)).await?;

        let messages = match result {
            MessageFetchResult::MessagesOnly(list) => list,
            MessageFetchResult::WithUsersAndMembers(data) => {
                let mut messages = data.messages;

                let users_map: HashMap<String, User> = data.users.into_iter()
                    .map(|user| (user.id.clone(), user))
                    .collect();

                let members_map: HashMap<String, Member> = data.members.into_iter()
                    .map(|member| (member._id.user.clone(), member))
                    .collect();

                for message in &mut messages {
                    if let Some(user) = users_map.get(&message.author) {
                        message.user = Some(user.clone());
                    }
                    if let Some(member) = members_map.get(&message.author) {
                        message.member = Some(member.clone());
                    }
                }
                messages
            }
        };

        Ok(messages)
    }
}