From 34df79764842215fa5d1cd102faf2d2f464430f0 Mon Sep 17 00:00:00 2001 From: lza_menace Date: Thu, 27 Oct 2022 16:19:12 -0700 Subject: [PATCH] beef up functionality --- src/app.rs | 38 +++++++++++++++++++++++--------- src/irc.rs | 63 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 79 insertions(+), 22 deletions(-) diff --git a/src/app.rs b/src/app.rs index ac6c242..5ff2db3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,5 +1,4 @@ use std::time::{Duration, SystemTime}; -use std::io::Write; use std::net::TcpStream; use eframe::egui; use egui::FontFamily::Proportional; @@ -24,7 +23,9 @@ pub struct App { pub irc_connected: bool, pub show_market_data: bool, pub show_radio: bool, - pub irc_stream: Result, + pub irc_stream: Option, + pub irc_last_ping: SystemTime, + pub irc_active_channel: String } impl Default for App { @@ -42,7 +43,9 @@ impl Default for App { to_data: "".to_owned(), irc_message: "".to_owned(), show_radio: true, - irc_stream: TcpStream::connect("0.0.0.0:0") + irc_stream: None, + irc_last_ping: SystemTime::now(), + irc_active_channel: "#wownero-music".to_owned() } } } @@ -79,8 +82,8 @@ impl eframe::App for App { if (self.tor_connected && self.tor_required) || (! self.tor_required) { ui.checkbox(&mut self.show_market_data, "Show Market Data"); ui.checkbox(&mut self.show_irc, "Show IRC"); - ui.checkbox(&mut self.show_radio, "Show Radio"); } + ui.checkbox(&mut self.show_radio, "Show Radio"); }); // Tor @@ -119,7 +122,6 @@ impl eframe::App for App { ui.add(egui::Slider::new(&mut self.player.volume, 0.0..=100.0)); self.player.sink.set_volume(self.player.volume / 100.0); if self.player.sink.len() != 1 { - // let _ = self.player.wait_for_source(); let f = std::fs::File::open(crate::RADIO_STREAM); if let Ok(fo) = f { let file = std::io::BufReader::new(fo); @@ -127,7 +129,6 @@ impl eframe::App for App { if source.is_err() { return () } - // let _ = self.player.sink.stop(); let _ = self.player.sink.append(source.unwrap()); let _ = self.player.sink.play(); } else { @@ -190,17 +191,30 @@ impl eframe::App for App { // IRC if self.show_irc && ! self.irc_connected { - self.irc_stream = self.irc.run(); - self.irc_connected = true; + let i = self.irc.run(); + if i.is_ok() { + self.irc_stream = Some(i.unwrap()); + self.irc_connected = true; + } + } else if self.show_irc { egui::ScrollArea::vertical().stick_to_bottom(true).show(ui, |ui| { - ui.label(self.irc.read_irc_log()); + ui.label(self.irc.read_irc_log(self.irc_active_channel.clone())); ui.horizontal(|ui| { + egui::ComboBox::from_label("") + .selected_text(format!("{}", self.irc_active_channel)) + .show_ui(ui, |ui| { + ui.selectable_value(&mut self.irc_active_channel, "".to_owned(), "system"); + ui.selectable_value(&mut self.irc_active_channel, "#wownero-music".to_owned(), "#wownero-music"); + ui.selectable_value(&mut self.irc_active_channel, "#wownero".to_owned(), "#wownero"); + } + ); ui.text_edit_singleline(&mut self.irc_message); if ui.button("> Send <").clicked() { - let res = self.irc_stream.as_ref().unwrap().write(self.irc_message.as_bytes()); + let res = crate::irc::send_cmd(&self.irc_stream.as_ref().unwrap(), "PRIVMSG", format!("{} :{}\r\n", self.irc_active_channel, self.irc_message)); if res.is_ok() { println!("wrote {} bytes to IRC: {}", res.unwrap(), self.irc_message); + let _ = crate::irc::write_log(format!("PRIVMSG {} :{}\r\n", self.irc_active_channel, self.irc_message).as_str(), false); } else { eprintln!("error: {:?}", res.err()); } @@ -210,6 +224,10 @@ impl eframe::App for App { if ui.button("Clear IRC Log").clicked() { let _ = std::fs::File::create(crate::IRC_LOG); } + if self.irc_last_ping.elapsed().unwrap() > Duration::from_secs(60) { + let _ = crate::irc::send_cmd(&self.irc_stream.as_ref().unwrap(), "PING", format!("")); + self.irc_last_ping = SystemTime::now(); + } }); } diff --git a/src/irc.rs b/src/irc.rs index 4f1614c..485ef0a 100644 --- a/src/irc.rs +++ b/src/irc.rs @@ -6,10 +6,12 @@ use std::fs::OpenOptions; use std::io::{Read, Write}; use std::time::SystemTime; +use std::io::{prelude::*, BufReader}; use std::collections::HashMap; use std::net::TcpStream; use std::str; use std::thread; +use regex::Regex; ///! A simple IRC client written in Rust. @@ -78,6 +80,7 @@ pub fn send_cmd(mut stream: &TcpStream, cmd: &str, msg: String) -> Result std::io::Result<()> { + let mut first_line: bool = true; loop { let mut buffer = Vec::new(); let mut temp = [1]; @@ -94,16 +97,22 @@ fn receive(mut stream: &TcpStream) -> std::io::Result<()> { match res_string { Ok(r) => { if !res_string.unwrap().is_empty() { - if std::fs::File::open(crate::IRC_LOG).is_err() { - let _ = std::fs::write(crate::IRC_LOG, ""); - } - let mut f = OpenOptions::new() - .append(true) - .open(crate::IRC_LOG) - .unwrap(); - if let Err(e) = writeln!(f, "{}", r.to_string()) { - eprintln!("[!] Failed to write to file: {}", e); - } + // if std::fs::File::open(crate::IRC_LOG).is_err() { + // let _ = std::fs::write(crate::IRC_LOG, ""); + // } + // let mut f = OpenOptions::new() + // .append(true) + // .open(crate::IRC_LOG) + // .unwrap(); + // if ! first_line { + // let _ = writeln!(f, "-------------writing to file-------------"); + // first_line = true; + // } + // if let Err(e) = writeln!(f, "{}", r.to_string()) { + // eprintln!("[!] Failed to write to file: {}", e); + // } + let _ = write_log(r, first_line); + first_line = false; } } Err(error) => eprintln!("error while reading from tcp stream: {}", error), @@ -111,6 +120,23 @@ fn receive(mut stream: &TcpStream) -> std::io::Result<()> { } } +pub fn write_log(log: &str, first_line: bool) -> Result<(), std::io::Error> { + if std::fs::File::open(crate::IRC_LOG).is_err() { + let _ = std::fs::write(crate::IRC_LOG, ""); + } + let mut f = OpenOptions::new() + .append(true) + .open(crate::IRC_LOG) + .unwrap(); + if first_line { + let _ = writeln!(f, "-------------writing to file-------------"); + } + if let Err(e) = writeln!(f, "{}", log.to_string()) { + eprintln!("[!] Failed to write to file: {}", e); + } + Ok(()) +} + /// Generates a friendly IRC nick string /// /// # Example @@ -200,12 +226,25 @@ impl Client { Some(()) } - pub fn read_irc_log(&self) -> String { + pub fn read_irc_log(&self, active_channel: String) -> String { let mut s: String = String::new(); let f = std::fs::File::open(crate::IRC_LOG); // ("unable to open irc log"); if f.is_err() { return "".to_owned() } - let _ = f.unwrap().read_to_string(&mut s); + if active_channel.len() > 0 { + let re = Regex::new(format!(r".*PRIVMSG {} :.*", active_channel).as_str()).unwrap(); + let reader = BufReader::new(f.unwrap()); + for line in reader.lines() { + if line.is_err() { continue } + let msg = line.unwrap(); + if re.is_match(msg.as_str()) { + s = s + "\n" + msg.as_str(); + } + } + } else { + let _ = f.unwrap().read_to_string(&mut s); + } return s; + } pub fn send_tune(&self) -> std::io::Result<()> {