alfred_core/
module.rs

1use std::collections::HashMap;
2use clap::Command;
3use crate::config::Config;
4use crate::error::Error;
5use crate::message::{Message, MessageType};
6use crate::connection::{Connection, MODULE_INFO_TOPIC_REQUEST, MODULE_INFO_TOPIC_RESPONSE, TOPIC_PREFIX};
7
8pub struct ModuleDetails {
9    module_name: &'static str,
10    version: &'static str,
11    config: Option<Config>,
12    capabilities: HashMap<String, String>
13}
14impl ModuleDetails {
15    pub fn builder() -> ModuleDetailsBuilder {
16        ModuleDetailsBuilder::default()
17    }
18}
19
20#[derive(Default)]
21#[must_use]
22pub struct ModuleDetailsBuilder {
23    module_name: &'static str,
24    version: &'static str,
25    config: Option<Config>,
26    capabilities: HashMap<String, String>
27}
28
29impl ModuleDetailsBuilder {
30    pub fn new() -> Self {
31        Self {
32            module_name: "",
33            version: "",
34            config: None,
35            capabilities: HashMap::new()
36        }
37    }
38    pub const fn module_name(mut self, module_name: &'static str) -> Self {
39        self.module_name = module_name;
40        self
41    }
42    pub const fn version(mut self, version: &'static str) -> Self {
43        self.version = version;
44        self
45    }
46    pub fn config(mut self, config: Option<Config>) -> Self {
47        self.config = config;
48        self
49    }
50    pub fn capabilities(mut self, capabilities: HashMap<String, String>) -> Self {
51        self.capabilities = capabilities;
52        self
53    }
54    pub fn build(self) -> ModuleDetails {
55        ModuleDetails {
56            module_name: self.module_name,
57            version: self.module_name,
58            config: self.config,
59            capabilities: self.capabilities
60        }
61    }
62}
63
64pub struct AlfredModule {
65    pub module_name: String,
66    pub version: String,
67    pub config: Config,
68    pub connection: Connection,
69    pub capabilities: HashMap<String, String> // TODO: change to HashMap<&'static str, &'static str>
70}
71
72impl AlfredModule {
73
74    pub fn manage_args(app_name: &'static str, version: &'static str) {
75        Command::new(app_name).version(version).get_matches();
76    }
77    
78    pub const fn get_lib_version() -> &'static str {
79        env!("CARGO_PKG_VERSION")
80    }
81
82    pub async fn new(module_name: &'static str, version: &'static str) -> Result<Self, Error> {
83        let module_config = ModuleDetails {
84            module_name,
85            version,
86            config: None,
87            capabilities: HashMap::new()
88        };
89        Self::new_with_details(module_config).await
90    }
91
92    pub async fn new_with_details(module_details: ModuleDetails) -> Result<Self, Error> {
93        Self::manage_args(module_details.module_name, module_details.version);
94        let config = module_details.config.unwrap_or_else(|| Config::read(Some(module_details.module_name)));
95        let capabilities = module_details.capabilities;
96        let mut connection = Connection::new(&config).await?;
97        connection.listen(MODULE_INFO_TOPIC_REQUEST).await?;
98        let alfred_module = Self {
99            module_name: module_details.module_name.to_string(),
100            version: module_details.version.to_string(),
101            config,
102            connection,
103            capabilities
104        };
105        alfred_module.send(MODULE_INFO_TOPIC_RESPONSE, &alfred_module.get_info_message()).await?;
106        Ok(alfred_module)
107    }
108
109    pub fn get_info_message(&self) -> Message {
110        Message {
111            text: self.module_name.clone(),
112            message_type: MessageType::ModuleInfo,
113            params: self.capabilities.clone(),
114            ..Message::default()
115        }
116    }
117
118    pub async fn listen(&mut self, topic: &str) -> Result<(), Error> {
119        self.capabilities.insert(String::from(TOPIC_PREFIX), String::from(topic));
120        self.connection.listen(topic).await
121    }
122
123    pub async fn receive(&self) -> Result<(String, Message), Error> {
124        self.connection.receive(&self.module_name, &self.capabilities).await
125    }
126
127    pub async fn send(&self, topic: &str, message: &Message) -> Result<(), Error> {
128        self.connection.send(topic, message).await
129    }
130
131    pub async fn send_event(&mut self, publisher_name: &str, event_name: &str, message: &Message) -> Result<(), Error> {
132        self.connection.send_event(publisher_name, event_name, message).await
133    }
134}