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> }
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}