mirror of
https://github.com/Cyrix126/gupaxx.git
synced 2024-12-22 22:59:27 +00:00
regex: lazy_static
everything instead of function input
This commit is contained in:
parent
bf4d286fad
commit
c8e5462d33
7 changed files with 133 additions and 102 deletions
|
@ -91,10 +91,11 @@ pub const P2POOL_FAILED: &str = "P2Pool is offline and failed when exiting";
|
|||
pub const P2POOL_MIDDLE: &str = "P2Pool is in the middle of (re)starting/stopping";
|
||||
pub const P2POOL_SYNCING: &str = "P2Pool is still syncing. This indicator will turn GREEN when P2Pool is ready";
|
||||
|
||||
pub const XMRIG_ALIVE: &str = "XMRig is online";
|
||||
pub const XMRIG_ALIVE: &str = "XMRig is online and mining";
|
||||
pub const XMRIG_DEAD: &str = "XMRig is offline";
|
||||
pub const XMRIG_FAILED: &str = "XMRig is offline and failed when exiting";
|
||||
pub const XMRIG_MIDDLE: &str = "XMRig is in the middle of (re)starting/stopping";
|
||||
pub const XMRIG_NOT_MINING: &str = "XMRig is online, but not mining to any pool";
|
||||
|
||||
// This is the typical space added when using
|
||||
// [ui.separator()] or [ui.group()]
|
||||
|
|
|
@ -47,7 +47,6 @@ use crate::{
|
|||
SudoState,
|
||||
human::*,
|
||||
GupaxP2poolApi,
|
||||
P2poolRegex,
|
||||
xmr::*,
|
||||
macros::*,
|
||||
RemoteNode,
|
||||
|
@ -56,6 +55,10 @@ use sysinfo::SystemExt;
|
|||
use serde::{Serialize,Deserialize};
|
||||
use sysinfo::{CpuExt,ProcessExt};
|
||||
use log::*;
|
||||
use crate::regex::{
|
||||
P2POOL_REGEX,
|
||||
XMRIG_REGEX,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Constants
|
||||
// The max amount of bytes of process output we are willing to
|
||||
|
@ -182,7 +185,8 @@ impl Process {
|
|||
pub fn is_alive(&self) -> bool {
|
||||
self.state == ProcessState::Alive ||
|
||||
self.state == ProcessState::Middle ||
|
||||
self.state == ProcessState::Syncing
|
||||
self.state == ProcessState::Syncing ||
|
||||
self.state == ProcessState::NotMining
|
||||
}
|
||||
|
||||
pub fn is_waiting(&self) -> bool {
|
||||
|
@ -192,6 +196,10 @@ impl Process {
|
|||
pub fn is_syncing(&self) -> bool {
|
||||
self.state == ProcessState::Syncing
|
||||
}
|
||||
|
||||
pub fn is_not_mining(&self) -> bool {
|
||||
self.state == ProcessState::NotMining
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [Process*] Enum
|
||||
|
@ -205,6 +213,9 @@ pub enum ProcessState {
|
|||
|
||||
// Only for P2Pool, ORANGE.
|
||||
Syncing,
|
||||
|
||||
// Only for XMRig, ORANGE.
|
||||
NotMining,
|
||||
}
|
||||
|
||||
impl Default for ProcessState { fn default() -> Self { Self::Dead } }
|
||||
|
@ -267,14 +278,14 @@ impl Helper {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_pty_p2pool(output_parse: Arc<Mutex<String>>, output_pub: Arc<Mutex<String>>, reader: Box<dyn std::io::Read + Send>, regex: P2poolRegex, gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>) {
|
||||
fn read_pty_p2pool(output_parse: Arc<Mutex<String>>, output_pub: Arc<Mutex<String>>, reader: Box<dyn std::io::Read + Send>, gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>) {
|
||||
use std::io::BufRead;
|
||||
let mut stdout = std::io::BufReader::new(reader).lines();
|
||||
while let Some(Ok(line)) = stdout.next() {
|
||||
// println!("{}", line); // For debugging.
|
||||
if regex.payout.is_match(&line) {
|
||||
if P2POOL_REGEX.payout.is_match(&line) {
|
||||
debug!("P2Pool PTY | Found payout, attempting write: {}", line);
|
||||
let (date, atomic_unit, block) = PayoutOrd::parse_raw_payout_line(&line, ®ex);
|
||||
let (date, atomic_unit, block) = PayoutOrd::parse_raw_payout_line(&line);
|
||||
let formatted_log_line = GupaxP2poolApi::format_payout(&date, &atomic_unit, &block);
|
||||
GupaxP2poolApi::add_payout(&mut lock!(gupax_p2pool_api), &formatted_log_line, date, atomic_unit, block);
|
||||
if let Err(e) = GupaxP2poolApi::write_to_all_files(&lock!(gupax_p2pool_api), &formatted_log_line) { error!("P2Pool PTY GupaxP2poolApi | Write error: {}", e); }
|
||||
|
@ -496,16 +507,13 @@ impl Helper {
|
|||
let mut stdin = pair.master;
|
||||
drop(lock);
|
||||
|
||||
let regex = P2poolRegex::new();
|
||||
|
||||
// 3. Spawn PTY read thread
|
||||
debug!("P2Pool | Spawning PTY read thread...");
|
||||
let output_parse = Arc::clone(&lock!(process).output_parse);
|
||||
let output_pub = Arc::clone(&lock!(process).output_pub);
|
||||
let gupax_p2pool_api = Arc::clone(&gupax_p2pool_api);
|
||||
let regex_clone = regex.clone();
|
||||
thread::spawn(move || {
|
||||
Self::read_pty_p2pool(output_parse, output_pub, reader, regex_clone, gupax_p2pool_api);
|
||||
Self::read_pty_p2pool(output_parse, output_pub, reader, gupax_p2pool_api);
|
||||
});
|
||||
let output_parse = Arc::clone(&lock!(process).output_parse);
|
||||
let output_pub = Arc::clone(&lock!(process).output_pub);
|
||||
|
@ -657,7 +665,7 @@ impl Helper {
|
|||
|
||||
// Always update from output
|
||||
debug!("P2Pool Watchdog | Starting [update_from_output()]");
|
||||
PubP2poolApi::update_from_output(&pub_api, &output_parse, &output_pub, start.elapsed(), ®ex, &process);
|
||||
PubP2poolApi::update_from_output(&pub_api, &output_parse, &output_pub, start.elapsed(), &process);
|
||||
|
||||
// Read [local] API
|
||||
debug!("P2Pool Watchdog | Attempting [local] API file read");
|
||||
|
@ -1369,12 +1377,12 @@ impl PubP2poolApi {
|
|||
|
||||
// Essentially greps the output for [x.xxxxxxxxxxxx XMR] where x = a number.
|
||||
// It sums each match and counts along the way, handling an error by not adding and printing to console.
|
||||
fn calc_payouts_and_xmr(output: &str, regex: &P2poolRegex) -> (u128 /* payout count */, f64 /* total xmr */) {
|
||||
let iter = regex.payout.find_iter(output);
|
||||
fn calc_payouts_and_xmr(output: &str) -> (u128 /* payout count */, f64 /* total xmr */) {
|
||||
let iter = P2POOL_REGEX.payout.find_iter(output);
|
||||
let mut sum: f64 = 0.0;
|
||||
let mut count: u128 = 0;
|
||||
for i in iter {
|
||||
if let Some(word) = regex.payout_float.find(i.as_str()) {
|
||||
if let Some(word) = P2POOL_REGEX.payout_float.find(i.as_str()) {
|
||||
match word.as_str().parse::<f64>() {
|
||||
Ok(num) => { sum += num; count += 1; },
|
||||
Err(e) => error!("P2Pool | Total XMR sum calculation error: [{}]", e),
|
||||
|
@ -1390,7 +1398,6 @@ impl PubP2poolApi {
|
|||
output_parse: &Arc<Mutex<String>>,
|
||||
output_pub: &Arc<Mutex<String>>,
|
||||
elapsed: std::time::Duration,
|
||||
regex: &P2poolRegex,
|
||||
process: &Arc<Mutex<Process>>,
|
||||
) {
|
||||
// 1. Take the process's current output buffer and combine it with Pub (if not empty)
|
||||
|
@ -1401,10 +1408,10 @@ impl PubP2poolApi {
|
|||
|
||||
// 2. Parse the full STDOUT
|
||||
let mut output_parse = lock!(output_parse);
|
||||
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse, regex);
|
||||
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse);
|
||||
// Check for "SYNCHRONIZED" only if we aren't already.
|
||||
if lock!(process).state == ProcessState::Syncing {
|
||||
if regex.synchronized.is_match(&output_parse) {
|
||||
if P2POOL_REGEX.synchronized.is_match(&output_parse) {
|
||||
lock!(process).state = ProcessState::Alive;
|
||||
}
|
||||
}
|
||||
|
@ -1940,14 +1947,9 @@ mod test {
|
|||
assert_eq!(pub_api.xmr, 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_p2pool_regex() {
|
||||
crate::helper::P2poolRegex::new();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn calc_payouts_and_xmr_from_output_p2pool() {
|
||||
use crate::helper::{PubP2poolApi,P2poolRegex};
|
||||
use crate::helper::{PubP2poolApi};
|
||||
use std::sync::{Arc,Mutex};
|
||||
let public = Arc::new(Mutex::new(PubP2poolApi::new()));
|
||||
let output_parse = Arc::new(Mutex::new(String::from(
|
||||
|
@ -1957,9 +1959,8 @@ mod test {
|
|||
)));
|
||||
let output_pub = Arc::new(Mutex::new(String::new()));
|
||||
let elapsed = std::time::Duration::from_secs(60);
|
||||
let regex = P2poolRegex::new();
|
||||
let process = Arc::new(Mutex::new(Process::new(ProcessName::P2pool, "".to_string(), PathBuf::new())));
|
||||
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, ®ex, &process);
|
||||
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, &process);
|
||||
let public = public.lock().unwrap();
|
||||
println!("{:#?}", public);
|
||||
assert_eq!(public.payouts, 3);
|
||||
|
@ -1974,7 +1975,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn set_p2pool_synchronized() {
|
||||
use crate::helper::{PubP2poolApi,P2poolRegex};
|
||||
use crate::helper::{PubP2poolApi};
|
||||
use std::sync::{Arc,Mutex};
|
||||
let public = Arc::new(Mutex::new(PubP2poolApi::new()));
|
||||
let output_parse = Arc::new(Mutex::new(String::from(
|
||||
|
@ -1984,12 +1985,11 @@ mod test {
|
|||
)));
|
||||
let output_pub = Arc::new(Mutex::new(String::new()));
|
||||
let elapsed = std::time::Duration::from_secs(60);
|
||||
let regex = P2poolRegex::new();
|
||||
let process = Arc::new(Mutex::new(Process::new(ProcessName::P2pool, "".to_string(), PathBuf::new())));
|
||||
|
||||
// It only gets checked if we're `Syncing`.
|
||||
process.lock().unwrap().state = ProcessState::Syncing;
|
||||
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, ®ex, &process);
|
||||
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, &process);
|
||||
println!("{:#?}", process);
|
||||
assert!(process.lock().unwrap().state == ProcessState::Alive);
|
||||
}
|
||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -158,7 +158,6 @@ pub struct App {
|
|||
version: &'static str, // Gupax version
|
||||
name_version: String, // [Gupax vX.X.X]
|
||||
img: Images, // Custom Struct holding pre-compiled bytes of [Images]
|
||||
regex: Regexes, // Custom Struct holding pre-made [Regex]'s
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
@ -264,7 +263,6 @@ impl App {
|
|||
version: GUPAX_VERSION,
|
||||
name_version: format!("Gupax {}", GUPAX_VERSION),
|
||||
img: Images::new(),
|
||||
regex: Regexes::new(),
|
||||
};
|
||||
//---------------------------------------------------------------------------------------------------- App init data that *could* panic
|
||||
info!("App Init | Getting EXE path...");
|
||||
|
@ -839,7 +837,7 @@ fn init_auto(app: &mut App) {
|
|||
|
||||
// [Auto-P2Pool]
|
||||
if app.state.gupax.auto_p2pool {
|
||||
if !Regexes::addr_ok(&app.regex, &app.state.p2pool.address) {
|
||||
if !Regexes::addr_ok(&app.state.p2pool.address) {
|
||||
warn!("Gupax | P2Pool address is not valid! Skipping auto-p2pool...");
|
||||
} else if !Gupax::path_is_file(&app.state.gupax.p2pool_path) {
|
||||
warn!("Gupax | P2Pool path is not a file! Skipping auto-p2pool...");
|
||||
|
@ -1527,14 +1525,15 @@ impl eframe::App for App {
|
|||
Alive => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(GREEN))).on_hover_text(P2POOL_ALIVE),
|
||||
Dead => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(GRAY))).on_hover_text(P2POOL_DEAD),
|
||||
Failed => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(RED))).on_hover_text(P2POOL_FAILED),
|
||||
Middle|Waiting => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(YELLOW))).on_hover_text(P2POOL_MIDDLE),
|
||||
Syncing => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(ORANGE))).on_hover_text(P2POOL_SYNCING),
|
||||
Middle|Waiting|NotMining => ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(YELLOW))).on_hover_text(P2POOL_MIDDLE),
|
||||
};
|
||||
ui.separator();
|
||||
match xmrig_state {
|
||||
Alive => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(GREEN))).on_hover_text(XMRIG_ALIVE),
|
||||
Dead => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(GRAY))).on_hover_text(XMRIG_DEAD),
|
||||
Failed => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(RED))).on_hover_text(XMRIG_FAILED),
|
||||
NotMining => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(ORANGE))).on_hover_text(XMRIG_NOT_MINING),
|
||||
Middle|Waiting|Syncing => ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(YELLOW))).on_hover_text(XMRIG_MIDDLE),
|
||||
};
|
||||
});
|
||||
|
@ -1647,7 +1646,7 @@ impl eframe::App for App {
|
|||
// Check if address is okay before allowing to start.
|
||||
let mut text = String::new();
|
||||
let mut ui_enabled = true;
|
||||
if !Regexes::addr_ok(&self.regex, &self.state.p2pool.address) {
|
||||
if !Regexes::addr_ok(&self.state.p2pool.address) {
|
||||
ui_enabled = false;
|
||||
text = format!("Error: {}", P2POOL_ADDRESS);
|
||||
} else if !Gupax::path_is_file(&self.state.gupax.p2pool_path) {
|
||||
|
@ -1874,11 +1873,11 @@ path_xmr: {:#?}\n
|
|||
}
|
||||
Tab::P2pool => {
|
||||
debug!("App | Entering [P2Pool] Tab");
|
||||
crate::disk::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.regex, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.width, self.height, ctx, ui);
|
||||
crate::disk::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.width, self.height, ctx, ui);
|
||||
}
|
||||
Tab::Xmrig => {
|
||||
debug!("App | Entering [XMRig] Tab");
|
||||
crate::disk::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.regex, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.width, self.height, ctx, ui);
|
||||
crate::disk::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.width, self.height, ctx, ui);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -31,10 +31,13 @@ use egui::{
|
|||
use std::sync::{Arc,Mutex};
|
||||
use regex::Regex;
|
||||
use log::*;
|
||||
use crate::regex::{
|
||||
REGEXES,
|
||||
};
|
||||
|
||||
impl crate::disk::P2pool {
|
||||
#[inline(always)]
|
||||
pub fn show(&mut self, node_vec: &mut Vec<(String, Node)>, _og: &Arc<Mutex<State>>, ping: &Arc<Mutex<Ping>>, regex: &Regexes, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubP2poolApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
|
||||
pub fn show(&mut self, node_vec: &mut Vec<(String, Node)>, _og: &Arc<Mutex<State>>, ping: &Arc<Mutex<Ping>>, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubP2poolApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
|
||||
let text_edit = height / 25.0;
|
||||
//---------------------------------------------------------------------------------------------------- [Simple] Console
|
||||
debug!("P2Pool Tab | Rendering [Console]");
|
||||
|
@ -93,7 +96,7 @@ impl crate::disk::P2pool {
|
|||
if self.address.is_empty() {
|
||||
text = format!("Monero Address [{}/95] ➖", len);
|
||||
color = Color32::LIGHT_GRAY;
|
||||
} else if Regexes::addr_ok(regex, &self.address) {
|
||||
} else if Regexes::addr_ok(&self.address) {
|
||||
text = format!("Monero Address [{}/95] ✔", len);
|
||||
color = Color32::from_rgb(100, 230, 100);
|
||||
} else {
|
||||
|
@ -248,7 +251,7 @@ impl crate::disk::P2pool {
|
|||
text = format!("Name [ {}/30 ]➖", len);
|
||||
color = Color32::LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if Regex::is_match(®ex.name, &self.name) {
|
||||
} else if REGEXES.name.is_match(&self.name) {
|
||||
text = format!("Name [ {}/30 ]✔", len);
|
||||
color = Color32::from_rgb(100, 230, 100);
|
||||
} else {
|
||||
|
@ -268,7 +271,7 @@ impl crate::disk::P2pool {
|
|||
text = format!(" IP [{}/255]➖", len);
|
||||
color = Color32::LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if self.ip == "localhost" || Regex::is_match(®ex.ipv4, &self.ip) || Regex::is_match(®ex.domain, &self.ip) {
|
||||
} else if self.ip == "localhost" || REGEXES.ipv4.is_match(&self.ip) || REGEXES.domain.is_match(&self.ip) {
|
||||
text = format!(" IP [{}/255]✔", len);
|
||||
color = Color32::from_rgb(100, 230, 100);
|
||||
} else {
|
||||
|
@ -288,7 +291,7 @@ impl crate::disk::P2pool {
|
|||
text = format!(" RPC [ {}/5 ]➖", len);
|
||||
color = Color32::LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if Regex::is_match(®ex.port, &self.rpc) {
|
||||
} else if REGEXES.port.is_match(&self.rpc) {
|
||||
text = format!(" RPC [ {}/5 ]✔", len);
|
||||
color = Color32::from_rgb(100, 230, 100);
|
||||
} else {
|
||||
|
@ -308,7 +311,7 @@ impl crate::disk::P2pool {
|
|||
text = format!(" ZMQ [ {}/5 ]➖", len);
|
||||
color = Color32::LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if Regex::is_match(®ex.port, &self.zmq) {
|
||||
} else if REGEXES.port.is_match(&self.zmq) {
|
||||
text = format!(" ZMQ [ {}/5 ]✔", len);
|
||||
color = Color32::from_rgb(100, 230, 100);
|
||||
} else {
|
||||
|
|
62
src/regex.rs
62
src/regex.rs
|
@ -18,6 +18,14 @@
|
|||
// Some regexes used throughout Gupax.
|
||||
|
||||
use regex::Regex;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Lazy
|
||||
lazy_static! {
|
||||
pub static ref REGEXES: Regexes = Regexes::new();
|
||||
pub static ref P2POOL_REGEX: P2poolRegex = P2poolRegex::new();
|
||||
pub static ref XMRIG_REGEX: XmrigRegex = XmrigRegex::new();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [Regexes] struct
|
||||
// General purpose Regexes, mostly used in the GUI.
|
||||
|
@ -31,8 +39,8 @@ pub struct Regexes {
|
|||
}
|
||||
|
||||
impl Regexes {
|
||||
pub fn new() -> Self {
|
||||
Regexes {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
name: Regex::new("^[A-Za-z0-9-_.]+( [A-Za-z0-9-_.]+)*$").unwrap(),
|
||||
address: Regex::new("^4[A-Za-z1-9]+$").unwrap(), // This still needs to check for (l, I, o, 0)
|
||||
ipv4: Regex::new(r#"^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$"#).unwrap(),
|
||||
|
@ -44,8 +52,8 @@ impl Regexes {
|
|||
// Check if a Monero address is correct.
|
||||
// This actually only checks for length & Base58, and doesn't do any checksum validation
|
||||
// (the last few bytes of a Monero address are a Keccak hash checksum) so some invalid addresses can trick this function.
|
||||
pub fn addr_ok(&self, address: &str) -> bool {
|
||||
address.len() == 95 && Regex::is_match(&self.address, address) && !address.contains('0') && !address.contains('O') && !address.contains('l')
|
||||
pub fn addr_ok(address: &str) -> bool {
|
||||
address.len() == 95 && REGEXES.address.is_match(address) && !address.contains('0') && !address.contains('O') && !address.contains('l')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,25 +77,41 @@ impl Regexes {
|
|||
// Both are nominally fast enough where it doesn't matter too much but meh, why not use regex.
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct P2poolRegex {
|
||||
pub date: regex::Regex,
|
||||
pub payout: regex::Regex,
|
||||
pub payout_float: regex::Regex,
|
||||
pub block: regex::Regex,
|
||||
pub block_int: regex::Regex,
|
||||
pub block_comma: regex::Regex,
|
||||
pub synchronized: regex::Regex,
|
||||
pub date: Regex,
|
||||
pub payout: Regex,
|
||||
pub payout_float: Regex,
|
||||
pub block: Regex,
|
||||
pub block_int: Regex,
|
||||
pub block_comma: Regex,
|
||||
pub synchronized: Regex,
|
||||
}
|
||||
|
||||
impl P2poolRegex {
|
||||
pub fn new() -> Self {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
date: regex::Regex::new("[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+.[0-9]+").unwrap(),
|
||||
payout: regex::Regex::new("payout of [0-9].[0-9]+ XMR").unwrap(), // Assumes 12 digits after the dot.
|
||||
payout_float: regex::Regex::new("[0-9].[0-9]{12}").unwrap(), // Assumes 12 digits after the dot.
|
||||
block: regex::Regex::new("block [0-9]{7}").unwrap(), // Monero blocks will be 7 digits for... the next 10,379 years
|
||||
block_int: regex::Regex::new("[0-9]{7}").unwrap(),
|
||||
block_comma: regex::Regex::new("[0-9],[0-9]{3},[0-9]{3}").unwrap(),
|
||||
synchronized: regex::Regex::new("SYNCHRONIZED").unwrap(),
|
||||
date: Regex::new("[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+.[0-9]+").unwrap(),
|
||||
payout: Regex::new("payout of [0-9].[0-9]+ XMR").unwrap(), // Assumes 12 digits after the dot.
|
||||
payout_float: Regex::new("[0-9].[0-9]{12}").unwrap(), // Assumes 12 digits after the dot.
|
||||
block: Regex::new("block [0-9]{7}").unwrap(), // Monero blocks will be 7 digits for... the next 10,379 years
|
||||
block_int: Regex::new("[0-9]{7}").unwrap(),
|
||||
block_comma: Regex::new("[0-9],[0-9]{3},[0-9]{3}").unwrap(),
|
||||
synchronized: Regex::new("SYNCHRONIZED").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- XMRig regex.
|
||||
#[derive(Debug)]
|
||||
pub struct XmrigRegex {
|
||||
not_mining: Regex,
|
||||
mining: Regex,
|
||||
}
|
||||
|
||||
impl XmrigRegex {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
not_mining: Regex::new("no active pools, stop mining").unwrap(),
|
||||
mining: Regex::new("new job").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
27
src/xmr.rs
27
src/xmr.rs
|
@ -24,7 +24,9 @@
|
|||
|
||||
use crate::{
|
||||
human::*,
|
||||
P2poolRegex,
|
||||
};
|
||||
use crate::regex::{
|
||||
P2POOL_REGEX,
|
||||
};
|
||||
|
||||
use log::*;
|
||||
|
@ -141,15 +143,15 @@ impl PayoutOrd {
|
|||
}
|
||||
|
||||
// Expected input: "NOTICE 2022-01-27 01:30:23.1377 P2Pool You received a payout of 0.000000000001 XMR in block 2642816"
|
||||
pub fn parse_raw_payout_line(line: &str, regex: &P2poolRegex) -> (String, AtomicUnit, HumanNumber) {
|
||||
pub fn parse_raw_payout_line(line: &str) -> (String, AtomicUnit, HumanNumber) {
|
||||
// Date
|
||||
let date = match regex.date.find(line) {
|
||||
let date = match P2POOL_REGEX.date.find(line) {
|
||||
Some(date) => date.as_str().to_string(),
|
||||
None => { error!("P2Pool | Date parse error: [{}]", line); "????-??-?? ??:??:??.????".to_string() },
|
||||
};
|
||||
// AtomicUnit
|
||||
let atomic_unit = if let Some(word) = regex.payout.find(line) {
|
||||
if let Some(word) = regex.payout_float.find(word.as_str()) {
|
||||
let atomic_unit = if let Some(word) = P2POOL_REGEX.payout.find(line) {
|
||||
if let Some(word) = P2POOL_REGEX.payout_float.find(word.as_str()) {
|
||||
match word.as_str().parse::<f64>() {
|
||||
Ok(au) => AtomicUnit::from_f64(au),
|
||||
Err(e) => { error!("P2Pool | AtomicUnit parse error: [{}] on [{}]", e, line); AtomicUnit::new() },
|
||||
|
@ -163,8 +165,8 @@ impl PayoutOrd {
|
|||
AtomicUnit::new()
|
||||
};
|
||||
// Block
|
||||
let block = if let Some(word) = regex.block.find(line) {
|
||||
if let Some(word) = regex.block_int.find(word.as_str()) {
|
||||
let block = if let Some(word) = P2POOL_REGEX.block.find(line) {
|
||||
if let Some(word) = P2POOL_REGEX.block_int.find(word.as_str()) {
|
||||
match word.as_str().parse::<u64>() {
|
||||
Ok(b) => HumanNumber::from_u64(b),
|
||||
Err(e) => { error!("P2Pool | Block parse error: [{}] on [{}]", e, line); HumanNumber::unknown() },
|
||||
|
@ -181,14 +183,14 @@ impl PayoutOrd {
|
|||
}
|
||||
|
||||
// Expected input: "2022-01-27 01:30:23.1377 | 0.000000000001 XMR | Block 2,642,816"
|
||||
pub fn parse_formatted_payout_line(line: &str, regex: &P2poolRegex) -> (String, AtomicUnit, HumanNumber) {
|
||||
pub fn parse_formatted_payout_line(line: &str) -> (String, AtomicUnit, HumanNumber) {
|
||||
// Date
|
||||
let date = match regex.date.find(line) {
|
||||
let date = match P2POOL_REGEX.date.find(line) {
|
||||
Some(date) => date.as_str().to_string(),
|
||||
None => { error!("P2Pool | Date parse error: [{}]", line); "????-??-?? ??:??:??.????".to_string() },
|
||||
};
|
||||
// AtomicUnit
|
||||
let atomic_unit = if let Some(word) = regex.payout_float.find(line) {
|
||||
let atomic_unit = if let Some(word) = P2POOL_REGEX.payout_float.find(line) {
|
||||
match word.as_str().parse::<f64>() {
|
||||
Ok(au) => AtomicUnit::from_f64(au),
|
||||
Err(e) => { error!("P2Pool | AtomicUnit parse error: [{}] on [{}]", e, line); AtomicUnit::new() },
|
||||
|
@ -198,7 +200,7 @@ impl PayoutOrd {
|
|||
AtomicUnit::new()
|
||||
};
|
||||
// Block
|
||||
let block = match regex.block_comma.find(line) {
|
||||
let block = match P2POOL_REGEX.block_comma.find(line) {
|
||||
Some(b) => HumanNumber::from_str(b.as_str()),
|
||||
None => { error!("P2Pool | Block parse error: [{}]", line); HumanNumber::unknown() },
|
||||
};
|
||||
|
@ -215,12 +217,11 @@ impl PayoutOrd {
|
|||
// Spaces, pipes, commas and words (XMR, Block): [19]
|
||||
// Add 7 more bytes for wrapper type overhead and it's an even [70] bytes per line.
|
||||
pub fn update_from_payout_log(&mut self, log: &str) {
|
||||
let regex = P2poolRegex::new();
|
||||
let amount_of_lines = log.lines().count();
|
||||
let mut vec: Vec<(String, AtomicUnit, HumanNumber)> = Vec::with_capacity(70 * amount_of_lines);
|
||||
for line in log.lines() {
|
||||
debug!("PayoutOrd | Parsing line: [{}]", line);
|
||||
vec.push(Self::parse_formatted_payout_line(line, ®ex));
|
||||
vec.push(Self::parse_formatted_payout_line(line));
|
||||
}
|
||||
*self = Self(vec);
|
||||
}
|
||||
|
|
19
src/xmrig.rs
19
src/xmrig.rs
|
@ -32,10 +32,13 @@ use std::{
|
|||
};
|
||||
use regex::Regex;
|
||||
use log::*;
|
||||
use crate::regex::{
|
||||
REGEXES,
|
||||
};
|
||||
|
||||
impl crate::disk::Xmrig {
|
||||
#[inline(always)]
|
||||
pub fn show(&mut self, pool_vec: &mut Vec<(String, Pool)>, regex: &Regexes, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubXmrigApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
|
||||
pub fn show(&mut self, pool_vec: &mut Vec<(String, Pool)>, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubXmrigApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
|
||||
let text_edit = height / 25.0;
|
||||
//---------------------------------------------------------------------------------------------------- [Simple] Console
|
||||
debug!("XMRig Tab | Rendering [Console]");
|
||||
|
@ -92,7 +95,7 @@ impl crate::disk::Xmrig {
|
|||
if self.address.is_empty() {
|
||||
text = format!("Monero Address [{}/95] ➖", len);
|
||||
color = LIGHT_GRAY;
|
||||
} else if self.address.len() == 95 && Regex::is_match(®ex.address, &self.address) && ! self.address.contains('0') && ! self.address.contains('O') && ! self.address.contains('l') {
|
||||
} else if Regexes::addr_ok(&self.address) {
|
||||
text = format!("Monero Address [{}/95] ✔", len);
|
||||
color = GREEN;
|
||||
} else {
|
||||
|
@ -147,7 +150,7 @@ impl crate::disk::Xmrig {
|
|||
text = format!("Name [ {}/30 ]➖", len);
|
||||
color = LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if Regex::is_match(®ex.name, &self.name) {
|
||||
} else if REGEXES.name.is_match(&self.name) {
|
||||
text = format!("Name [ {}/30 ]✔", len);
|
||||
color = GREEN;
|
||||
} else {
|
||||
|
@ -167,7 +170,7 @@ impl crate::disk::Xmrig {
|
|||
text = format!(" IP [{}/255]➖", len);
|
||||
color = LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if self.ip == "localhost" || Regex::is_match(®ex.ipv4, &self.ip) || Regex::is_match(®ex.domain, &self.ip) {
|
||||
} else if self.ip == "localhost" || REGEXES.ipv4.is_match(&self.ip) || REGEXES.domain.is_match(&self.ip) {
|
||||
text = format!(" IP [{}/255]✔", len);
|
||||
color = GREEN;
|
||||
} else {
|
||||
|
@ -187,7 +190,7 @@ impl crate::disk::Xmrig {
|
|||
text = format!("Port [ {}/5 ]➖", len);
|
||||
color = LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if Regex::is_match(®ex.port, &self.port) {
|
||||
} else if REGEXES.port.is_match(&self.port) {
|
||||
text = format!("Port [ {}/5 ]✔", len);
|
||||
color = GREEN;
|
||||
} else {
|
||||
|
@ -206,7 +209,7 @@ impl crate::disk::Xmrig {
|
|||
if self.rig.is_empty() {
|
||||
text = format!(" Rig [ {}/30 ]➖", len);
|
||||
color = LIGHT_GRAY;
|
||||
} else if Regex::is_match(®ex.name, &self.rig) {
|
||||
} else if REGEXES.name.is_match(&self.rig) {
|
||||
text = format!(" Rig [ {}/30 ]✔", len);
|
||||
color = GREEN;
|
||||
} else {
|
||||
|
@ -361,7 +364,7 @@ impl crate::disk::Xmrig {
|
|||
text = format!("HTTP API IP [{}/255]➖", len);
|
||||
color = LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if self.api_ip == "localhost" || Regex::is_match(®ex.ipv4, &self.api_ip) || Regex::is_match(®ex.domain, &self.api_ip) {
|
||||
} else if self.api_ip == "localhost" || REGEXES.ipv4.is_match(&self.api_ip) || REGEXES.domain.is_match(&self.api_ip) {
|
||||
text = format!("HTTP API IP [{}/255]✔", len);
|
||||
color = GREEN;
|
||||
} else {
|
||||
|
@ -381,7 +384,7 @@ impl crate::disk::Xmrig {
|
|||
text = format!("HTTP API Port [ {}/5 ]➖", len);
|
||||
color = LIGHT_GRAY;
|
||||
incorrect_input = true;
|
||||
} else if Regex::is_match(®ex.port, &self.api_port) {
|
||||
} else if REGEXES.port.is_match(&self.api_port) {
|
||||
text = format!("HTTP API Port [ {}/5 ]✔", len);
|
||||
color = GREEN;
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue