wechaty 0.1.0-beta.1

Rust implementation of wechaty
Documentation
use std::fmt;

use log::{debug, error};
use wechaty_puppet::{PayloadType, PuppetImpl, RoomMemberQueryFilter, RoomPayload};

use crate::{Contact, Entity, WechatyContext, WechatyError};

pub type Room<T> = Entity<T, RoomPayload>;

impl<T> Room<T>
where
    T: 'static + PuppetImpl + Clone + Unpin + Send + Sync,
{
    pub(crate) fn new(id: String, ctx: WechatyContext<T>, payload: Option<RoomPayload>) -> Self {
        debug!("create room {}", id);
        let payload = match payload {
            Some(_) => payload,
            None => match ctx.rooms().get(&id) {
                Some(payload) => Some(payload.clone()),
                None => None,
            },
        };
        Self {
            id_: id,
            ctx_: ctx,
            payload_: payload,
        }
    }

    pub(crate) async fn ready(&mut self, force_sync: bool) -> Result<(), WechatyError> {
        debug!("Room.ready(id = {})", self.id_);
        if !force_sync && self.is_ready() {
            Ok(())
        } else {
            let id = self.id();
            let mut puppet = self.ctx().puppet();
            if force_sync {
                if let Err(e) = puppet.dirty_payload(PayloadType::Room, id.clone()).await {
                    error!("Error occurred while dirtying room {}: {}", id, e);
                    return Err(WechatyError::from(e));
                }
                if let Err(e) = puppet.dirty_payload(PayloadType::RoomMember, id.clone()).await {
                    error!("Error occurred while dirtying members of room {}: {}", id, e);
                    return Err(WechatyError::from(e));
                }
            }
            match puppet.room_payload(id.clone()).await {
                Ok(payload) => {
                    self.ctx().rooms().insert(id, payload.clone());
                    self.set_payload(Some(payload.clone()));
                    self.ctx().contact_load_batch(payload.member_id_list).await;
                    Ok(())
                }
                Err(e) => {
                    error!("Error occurred while syncing contact {}: {}", id, e);
                    Err(WechatyError::from(e))
                }
            }
        }
    }

    pub(crate) async fn sync(&mut self) -> Result<(), WechatyError> {
        debug!("Room.sync(id = {})", self.id_);
        self.ready(true).await
    }

    pub async fn member_find(&self, query: RoomMemberQueryFilter) -> Result<Vec<Contact<T>>, WechatyError> {
        debug!("Room.member_find(id = {}, query = {:?})", self.id_, query);
        let ctx = self.ctx();
        match ctx.puppet().room_member_search(self.id(), query).await {
            Ok(member_id_list) => Ok(ctx.contact_load_batch(member_id_list).await),
            Err(e) => Err(WechatyError::from(e)),
        }
    }

    pub async fn member_find_by_string(&self, query_str: String) -> Result<Vec<Contact<T>>, WechatyError> {
        debug!(
            "Room.member_find_by_string(id = {}, query_str = {:?})",
            self.id_, query_str
        );
        let ctx = self.ctx();
        match ctx.puppet().room_member_search_by_string(self.id(), query_str).await {
            Ok(member_id_list) => Ok(ctx.contact_load_batch(member_id_list).await),
            Err(e) => Err(WechatyError::from(e)),
        }
    }

    pub async fn member_find_all(&self) -> Result<Vec<Contact<T>>, WechatyError> {
        debug!("Room.member_find_all(id = {})", self.id_);
        let ctx = self.ctx();
        match ctx.puppet().room_member_list(self.id()).await {
            Ok(member_id_list) => Ok(ctx.contact_load_batch(member_id_list).await),
            Err(e) => Err(WechatyError::from(e)),
        }
    }
}

impl<T> fmt::Debug for Room<T>
where
    T: 'static + PuppetImpl + Clone + Unpin + Send + Sync,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "Room({})", self)
    }
}

impl<T> fmt::Display for Room<T>
where
    T: 'static + PuppetImpl + Clone + Unpin + Send + Sync,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let room_info = match &self.payload_ {
            Some(payload) => {
                if !payload.topic.is_empty() {
                    payload.topic.clone()
                } else if !self.id_.is_empty() {
                    self.id_.clone()
                } else {
                    "loading...".to_owned()
                }
            }
            None => "loading...".to_owned(),
        };
        write!(fmt, "{}", room_info)
    }
}