main.rs (4830B)
1 use crate::config::Config; 2 use color_eyre::Result; 3 use futures_util::StreamExt; 4 use matrix_sdk::{ 5 events::{ 6 room::message::{MessageEventContent, NoticeMessageEventContent}, 7 AnyMessageEventContent, 8 }, 9 identifiers::RoomId, 10 SyncSettings, 11 }; 12 use matrix_sdk::{Client, ClientConfig}; 13 use once_cell::sync::{Lazy, OnceCell}; 14 use std::convert::TryFrom; 15 use std::path::Path; 16 use std::{env, fs}; 17 use tokio::io::{AsyncBufReadExt, BufStream}; 18 use tokio::net::UnixListener; 19 use tokio::sync::Mutex; 20 use tracing::*; 21 use url::Url; 22 use users::get_current_uid; 23 24 mod config; 25 26 static ROOM_ID: Lazy<Mutex<String>> = Lazy::new(|| Mutex::new(String::new())); 27 static CLIENT: OnceCell<Mutex<Client>> = OnceCell::new(); 28 static PRESETS: Lazy<Vec<AnyMessageEventContent>> = Lazy::new(|| { 29 vec![AnyMessageEventContent::RoomMessage( 30 MessageEventContent::Notice(NoticeMessageEventContent { 31 body: String::from("This is the first macro message sent using a midi controller"), 32 formatted: None, 33 relates_to: None, 34 }), 35 )] 36 }); 37 38 async fn setup_matrix() -> Result<()> { 39 info!("Beginning Matrix Setup"); 40 let config = Config::load().unwrap(); 41 let store_path_string = config.store_path.to_string(); 42 let store_path = Path::new(&store_path_string); 43 if !store_path.exists() { 44 fs::create_dir_all(store_path)?; 45 } 46 let client_config = ClientConfig::new().store_path(fs::canonicalize(&store_path)?); 47 48 let homeserver_url = 49 Url::parse(&config.homeserver_url).expect("Couldn't parse the homeserver URL"); 50 51 let client = Client::new_with_config(homeserver_url, client_config).unwrap(); 52 53 client 54 .login( 55 &config.mxid, 56 &config.password, 57 None, 58 Some(&"macro-bot".to_string()), 59 ) 60 .await?; 61 info!("logged in as {}", config.mxid); 62 63 let mutexed_client = Mutex::new(client.clone()); 64 CLIENT.set(mutexed_client); 65 66 tokio::spawn(async move { 67 info!("Starting full Sync..."); 68 client.sync(SyncSettings::default()).await; 69 }); 70 Ok(()) 71 } 72 73 #[tokio::main] 74 async fn main() -> Result<()> { 75 // Enable the logging crates 76 color_eyre::install()?; 77 if env::var("RUST_LOG").is_err() { 78 env::set_var("RUST_LOG", "INFO"); 79 } 80 tracing_subscriber::fmt::init(); 81 setup_matrix().await?; 82 83 let user_id = get_current_uid(); 84 let path_string = format!("/run/user/{}/lsc_matrix_presets.sock", user_id); 85 let socket_path = Path::new(&path_string); 86 if socket_path.exists() { 87 fs::remove_file(socket_path)?; 88 } 89 90 // First we create a unix socket. This is required to be a) The same as the crate name and b) to be in /run 91 let mut listener = UnixListener::bind(socket_path).unwrap(); 92 93 //let mut perms = fs::metadata(socket_path)?.permissions(); 94 //perms.set_mode(0o666); 95 //fs::set_permissions(socket_path, perms)?; 96 // This listens for new connections 97 while let Some(stream) = listener.next().await { 98 match stream { 99 Ok(stream) => { 100 tokio::spawn(async move { 101 println!("new client!"); 102 let buffer = BufStream::new(stream); 103 let mut lines = buffer.lines(); 104 while let Ok(line) = lines.next_line().await { 105 if let Some(line) = line { 106 info!("{}", line); 107 let split: Vec<&str> = line.split_whitespace().collect(); 108 if split[0] == "select" { 109 let mut state = ROOM_ID.lock().await; 110 *state = String::from(split[1]); 111 } 112 if split[0] == "do" { 113 let preset = PRESETS[split[1].parse::<usize>().unwrap()].clone(); 114 info!("preset: {:?}", preset); 115 let room_id = ROOM_ID.lock().await; 116 let cloned_id = (*room_id).clone(); 117 let client = CLIENT.get().unwrap().lock().await; 118 client 119 .room_send(&RoomId::try_from(cloned_id).unwrap(), preset, None) 120 .await 121 .unwrap(); 122 info!("executed preset"); 123 } 124 let room_id = ROOM_ID.lock().await; 125 info!("room_id: {}", room_id); 126 } 127 } 128 }); 129 } 130 Err(e) => { 131 error!("Unix socket connection failed: {}", e); 132 } 133 } 134 } 135 Ok(()) 136 }