rship-sdk 0.1.14

rship sdk in rust!
Documentation
use std::collections::HashSet;

use myko_rs::item::Eventable;
use myko_rs::message::MykoMessage;
use rship_entities::{
    action::Action,
    target::Target,
    target_status::{Status, TargetStatus},
};
use schemars::JsonSchema;
use serde::{de::DeserializeOwned, Serialize};
use tokio_stream::StreamExt;

use crate::{
    action::{ActionArgs, ActionProxy},
    client::SdkClient,
    emitter::{EmitterArgs, EmitterProxy},
    instance::InstanceProxy,
    types::SdkCommands,
};

#[derive(Clone)]
pub struct TargetArgs {
    pub name: String,
    pub short_id: String,
    pub category: String,
    pub parent_targets: Option<Vec<TargetProxy>>,
}

#[derive(Clone)]

pub struct TargetProxy {
    pub(crate) instance: InstanceProxy,
    pub(crate) args: TargetArgs,
    pub(crate) client: SdkClient,
    pub(crate) emitters: HashSet<String>,
    pub(crate) actions: HashSet<String>,
}

impl TargetProxy {
    pub async fn add_emitter<T: JsonSchema + Serialize + Clone>(
        &mut self,
        args: EmitterArgs<T>,
    ) -> EmitterProxy<T> {
        let p = EmitterProxy {
            target: self.clone(),
            args,
            client: self.client.clone(),
        };

        p.save().await;

        self.emitters.insert(p.id().clone());
        self.save(Status::Online).await;

        p
    }

    pub async fn rename(&mut self, name: String) {
        self.args.name = name.clone();
        self.save(Status::Online).await;
    }

    pub async fn add_action<T: DeserializeOwned + JsonSchema>(
        &mut self,
        args: ActionArgs<T>,
        handler: impl (Fn(&Action, T)) + Send + 'static,
    ) -> ActionProxy<T> {
        let p = ActionProxy {
            args,
            client: self.client.clone(),
            target: self.clone(),
        };

        let mut rcv = self.client.client.get_messages();

        let handler_id = p.id().clone();

        tokio::spawn(async move {
            println!("Action handler started");
            while let Some(msg) = rcv.next().await {
                let command = serde_json::from_value::<MykoMessage<SdkCommands>>(msg.clone());

                match command {
                    Ok(MykoMessage::Command(SdkCommands::ExecTargetAction(exec_target_action))) => {
                        if exec_target_action.action.id() != handler_id {
                            continue;
                        }

                        match serde_json::from_value::<T>(exec_target_action.data) {
                            Ok(data) => {
                                handler(&exec_target_action.action, data);
                            }
                            Err(e) => {
                                println!("Could not parse data: {:?}", e);
                            }
                        }
                    }

                    Err(_e) => {
                        // println!("Could not parse command: {:?}, {}", e, msg);
                    }
                    _ => {}
                }
            }

            println!("Action handler exited");
        });

        p.save().await;

        self.actions.insert(p.id().clone());
        self.save(Status::Online).await;

        p
    }

    pub async fn save(&self, status: Status) {
        let parent_ids: Vec<String> = match &self.args.parent_targets {
            Some(ids) => ids.clone(),
            None => vec![],
        }
        .iter()
        .map(|x| x.id())
        .collect();

        let target = Target {
            name: self.args.name.clone(),
            id: self.id(),
            category: self.args.category.clone(),
            action_ids: self.actions.iter().cloned().collect(),
            emitter_ids: self.emitters.iter().cloned().collect(),
            bg_color: self.instance.args.color.clone(),
            fg_color: self.instance.args.color.clone(),
            hash: uuid::Uuid::new_v4().to_string(),
            parent_targets: parent_ids.clone(),
            root_level: parent_ids.is_empty(),
            service_id: self.instance.args.service_id.clone(),
            sub_targets: vec![],
        };

        let status = TargetStatus {
            id: format!("{}:{}", self.instance.args.short_id, self.args.short_id),
            target_id: self.id(),
            status,
            instance_id: self.instance.args.short_id.clone(),
            hash: uuid::Uuid::new_v4().to_string(),
        };

        if let Err(err) = self.client.save_item(&target).await {
            println!("Could not save target: {}", err);
        }
        if let Err(err) = self.client.save_item(&status).await {
            println!("Could not save target status: {}", err);
        }
    }

    pub(crate) fn id(&self) -> String {
        format!("{}:{}", self.instance.args.service_id, self.args.short_id)
    }

    pub async fn set_status(&self, status: Status) {
        self.save(status).await;
    }
}