plugin_lua_cygnixy/
lib.rs

1use cygnixy_plugin_interface::{export_plugin, PluginLua};
2use mlua::prelude::LuaError;
3use mlua::{Function, Lua};
4use serenity::all::{ExecuteWebhook, Http, Webhook};
5use std::collections::HashMap;
6use std::error::Error;
7use tokio::runtime::Builder;
8use tracing::{debug, error, info, trace, warn};
9
10pub struct PluginLuaCygnixy;
11
12impl Default for PluginLuaCygnixy {
13    fn default() -> Self {
14        Self
15    }
16}
17
18impl PluginLuaCygnixy {
19    pub fn new() -> Self {
20        PluginLuaCygnixy
21    }
22}
23
24impl PluginLua for PluginLuaCygnixy {
25    fn name(&self) -> &str {
26        "cygnixy"
27    }
28
29    fn on_load(&mut self) -> Result<(), Box<dyn Error>> {
30        trace!("PluginLuaCygnixy loaded!");
31        Ok(())
32    }
33
34    fn on_unload(&mut self) -> Result<(), Box<dyn Error>> {
35        trace!("PluginLuaCygnixy unloaded!");
36        Ok(())
37    }
38
39    fn get_lua_functions(&self, lua: &Lua, name: &str) -> HashMap<String, Function> {
40        let mut functions = HashMap::new();
41
42        if let Err(e) = self.register_functions(lua, name, &mut functions) {
43            error!("Failed to register Lua functions: {}", e);
44        }
45
46        functions
47    }
48}
49
50impl PluginLuaCygnixy {
51    fn register_functions(
52        &self,
53        lua: &Lua,
54        name: &str,
55        functions: &mut HashMap<String, Function>,
56    ) -> Result<(), Box<dyn Error>> {
57        let span = tracing::span!(tracing::Level::DEBUG, "lua", uuid = ?name);
58
59        // Registering the "sleep" function
60        functions.insert(
61            "sleep".to_string(),
62            lua.create_function(|_, n: u64| {
63                std::thread::sleep(std::time::Duration::from_millis(n));
64                Ok(())
65            })?,
66        );
67
68        // Registering the "mouse_move" function
69        #[allow(unused_variables)]
70        functions.insert(
71            "mouse_move".to_string(),
72            lua.create_function(|_, (x, y): (i32, i32)| {
73                #[cfg(target_os = "windows")]
74                control_craft::set_cursor_pos(x, y);
75                Ok(())
76            })?,
77        );
78
79        // Registering the "drag_and_drop" function
80        #[allow(unused_variables)]
81        functions.insert(
82            "drag_and_drop".to_string(),
83            lua.create_function(|_, (x, y): (i32, i32)| {
84                #[cfg(target_os = "windows")]
85                control_craft::drag_and_drop(x, y);
86                Ok(())
87            })?,
88        );
89
90        // Registering the "mouse_click_left" function
91        functions.insert(
92            "mouse_click_left".to_string(),
93            lua.create_function(|_, ()| {
94                #[cfg(target_os = "windows")]
95                control_craft::click_mouse_button_left();
96                Ok(())
97            })?,
98        );
99
100        // Registering the "mouse_click_right" function
101        functions.insert(
102            "mouse_click_right".to_string(),
103            lua.create_function(|_, ()| {
104                #[cfg(target_os = "windows")]
105                control_craft::click_mouse_button_right();
106                Ok(())
107            })?,
108        );
109
110        // Registering the "press_key" function
111        #[allow(unused_variables)]
112        functions.insert(
113            "press_key".to_string(),
114            lua.create_function(|_, key: u8| {
115                #[cfg(target_os = "windows")]
116                control_craft::press_key(key);
117                Ok(())
118            })?,
119        );
120
121        // Registering the "info" function
122        functions.insert(
123            "info".to_string(),
124            lua.create_function({
125                let span = span.clone();
126                move |_, message: String| {
127                    let _enter = span.enter();
128                    info!("{}", message);
129                    Ok(())
130                }
131            })?,
132        );
133
134        // Registering the "warn" function
135        functions.insert(
136            "warn".to_string(),
137            lua.create_function({
138                let span = span.clone();
139                move |_, message: String| {
140                    let _enter = span.enter();
141                    warn!("{}", message);
142                    Ok(())
143                }
144            })?,
145        );
146
147        // Registering the "trace" function
148        functions.insert(
149            "trace".to_string(),
150            lua.create_function({
151                let span = span.clone();
152                move |_, message: String| {
153                    let _enter = span.enter();
154                    trace!("{}", message);
155                    Ok(())
156                }
157            })?,
158        );
159
160        // Registering the "debug" function
161        functions.insert(
162            "debug".to_string(),
163            lua.create_function({
164                let span = span.clone();
165                move |_, message: String| {
166                    let _enter = span.enter();
167                    debug!("{}", message);
168                    Ok(())
169                }
170            })?,
171        );
172
173        // Registering the "error" function
174        functions.insert(
175            "error".to_string(),
176            lua.create_function({
177                let span = span.clone();
178                move |_, message: String| {
179                    let _enter = span.enter();
180                    error!("{}", message);
181                    Ok(())
182                }
183            })?,
184        );
185
186        // Registering the "discord_send" function
187        functions.insert(
188            "discord_send".to_string(),
189            lua.create_function(
190                |_, (webhook_url, username, message): (String, String, String)| {
191                    if webhook_url.trim().is_empty() {
192                        return Ok(());
193                    }
194                    if username.trim().is_empty() {
195                        return Ok(());
196                    }
197                    if message.trim().is_empty() {
198                        return Ok(());
199                    }
200
201                    // Block to execute async code synchronously
202                    let runtime = Builder::new_current_thread().enable_all().build().unwrap();
203
204                    let result = runtime.block_on(async {
205                        let http = Http::new("");
206                        let webhook = Webhook::from_url(&http, &webhook_url)
207                            .await
208                            .map_err(|e| format!("Failed to load webhook: {}", e))?;
209
210                        let builder = ExecuteWebhook::new().content(&message).username(&username);
211
212                        webhook
213                            .execute(&http, false, builder)
214                            .await
215                            .map_err(|e| format!("Failed to execute webhook: {}", e))
216                    });
217
218                    // Handle result
219                    match result {
220                        Ok(_) => Ok(()),
221                        Err(err) => Err(LuaError::external(err)),
222                    }
223                },
224            )?,
225        );
226
227        Ok(())
228    }
229}
230
231export_plugin!(PluginLuaCygnixy);