mirror of
https://github.com/hinto-janai/gupax.git
synced 2024-12-23 03:19:21 +00:00
disk: add [ErrorState] handling for disk errors
This commit is contained in:
parent
e8c41fceb3
commit
7a5fe24276
9 changed files with 209 additions and 217 deletions
101
Cargo.lock
generated
101
Cargo.lock
generated
|
@ -1275,15 +1275,6 @@ dependencies = [
|
|||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-ordinalize"
|
||||
version = "3.1.12"
|
||||
|
@ -1920,7 +1911,6 @@ dependencies = [
|
|||
"openssl",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rfd",
|
||||
"rusqlite",
|
||||
"serde",
|
||||
|
@ -1937,25 +1927,6 @@ dependencies = [
|
|||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.1.0"
|
||||
|
@ -2106,7 +2077,6 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
|
@ -2223,12 +2193,6 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
|
@ -2438,12 +2402,6 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
|
@ -3339,43 +3297,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "retain_mut"
|
||||
version = "0.1.9"
|
||||
|
@ -3661,18 +3582,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "1.14.0"
|
||||
|
@ -4275,7 +4184,6 @@ dependencies = [
|
|||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5439,15 +5347,6 @@ dependencies = [
|
|||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winres"
|
||||
version = "0.1.12"
|
||||
|
|
|
@ -39,7 +39,7 @@ num_cpus = "1.13.1"
|
|||
num-format = "0.4.0"
|
||||
rand = "0.8.5"
|
||||
regex = "1.6.0"
|
||||
reqwest = { version = "0.11.12", features = ["blocking", "json"] }
|
||||
#reqwest = { version = "0.11.12", features = ["blocking", "json"] }
|
||||
rfd = "0.10.0"
|
||||
rusqlite = { version = "0.28.0", features = ["bundled"] }
|
||||
serde = { version = "1.0.145", features = ["rc", "derive"] }
|
||||
|
|
BIN
images/ferris/happy.png
Normal file
BIN
images/ferris/happy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
|
@ -85,7 +85,7 @@ r#"Use advanced settings:
|
|||
- P2Pool Main/Mini selection
|
||||
- Out/In peer setting
|
||||
- Log level setting"#;
|
||||
pub const P2POOL_NAME: &'static str = "Add a unique name to identify this node; Only [A-Za-z0-9-_] and spaces allowed; Max length = 30 characters";
|
||||
pub const P2POOL_NAME: &'static str = "Add a unique name to identify this node; Only [A-Za-z0-9-_] and spaces allowed, if the name already exists, the current settings will be saved to the already existing entry; Max length = 30 characters";
|
||||
pub const P2POOL_NODE_IP: &'static str = "Specify the Monero Node IP to connect to with P2Pool; It must be a valid IPv4 address or a valid domain name; Max length = 255 characters";
|
||||
pub const P2POOL_RPC_PORT: &'static str = "Specify the RPC port of the Monero node; [1-65535]";
|
||||
pub const P2POOL_ZMQ_PORT: &'static str = "Specify the ZMQ port of the Monero node; [1-65535]";
|
||||
|
@ -106,15 +106,17 @@ pub const XMRIG_PRIORITY: &'static str = "Set process priority (0 idle, 2 normal
|
|||
|
||||
// CLI argument messages
|
||||
pub const ARG_HELP: &'static str =
|
||||
r#"USAGE: ./gupax [--flags]
|
||||
r#"USAGE: ./gupax [--flag]
|
||||
|
||||
-h | --help Print this help message
|
||||
-v | --version Print version and build info
|
||||
-l | --node-list Print the manual node list
|
||||
-s | --state Print Gupax state
|
||||
-n | --no-startup Disable all auto-startup settings for this instance
|
||||
-r | --reset Reset all Gupax state and the manual node list
|
||||
-f | --ferris Print an extremely cute crab
|
||||
--help Print this help message
|
||||
--version Print version and build info
|
||||
--state Print Gupax state
|
||||
--nodes Print the manual node list
|
||||
--no-startup Disable all auto-startup settings for this instance
|
||||
--reset-state Reset all Gupax state (your settings)
|
||||
--reset-nodes Reset the manual node list in the [P2Pool] tab
|
||||
--reset-all Reset both the state and the manual node list
|
||||
--ferris Print an extremely cute crab
|
||||
|
||||
To view more detailed console debug information, start Gupax with
|
||||
the environment variable [RUST_LOG] set to a log level like so:
|
||||
|
|
95
src/disk.rs
95
src/disk.rs
|
@ -179,7 +179,7 @@ impl State {
|
|||
}
|
||||
|
||||
// Convert [String] to [State]
|
||||
pub fn from_string(string: String) -> Result<Self, TomlError> {
|
||||
pub fn from_string(string: &String) -> Result<Self, TomlError> {
|
||||
match toml::de::from_str(&string) {
|
||||
Ok(state) => {
|
||||
info!("State | Parse ... OK");
|
||||
|
@ -187,7 +187,7 @@ impl State {
|
|||
Ok(state)
|
||||
}
|
||||
Err(err) => {
|
||||
error!("State | String -> State ... FAIL ... {}", err);
|
||||
warn!("State | String -> State ... FAIL ... {}", err);
|
||||
Err(TomlError::Deserialize(err))
|
||||
},
|
||||
}
|
||||
|
@ -207,11 +207,20 @@ impl State {
|
|||
// Create
|
||||
_ => {
|
||||
Self::create_new()?;
|
||||
read_to_string(file, &path)?
|
||||
match read_to_string(file, &path) {
|
||||
Ok(s) => s,
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
},
|
||||
};
|
||||
// Deserialize
|
||||
Self::from_string(string)
|
||||
// Deserialize, attempt merge if failed
|
||||
match Self::from_string(&string) {
|
||||
Ok(s) => Ok(s),
|
||||
Err(e) => {
|
||||
warn!("State | Attempting merge...");
|
||||
Self::merge(string)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Completely overwrite current [state.toml]
|
||||
|
@ -250,22 +259,17 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
// Take [Self] as input, merge it with whatever the current [default] is,
|
||||
// Take [String] as input, merge it with whatever the current [default] is,
|
||||
// leaving behind old keys+values and updating [default] with old valid ones.
|
||||
// Automatically overwrite current file.
|
||||
pub fn merge(old: &Self) -> Result<Self, TomlError> {
|
||||
info!("Starting TOML merge...");
|
||||
let old = match toml::ser::to_string(&old) {
|
||||
Ok(string) => { info!("Old TOML parse ... OK"); string },
|
||||
Err(err) => { error!("Couldn't parse old TOML into string"); return Err(TomlError::Serialize(err)) },
|
||||
};
|
||||
pub fn merge(old: String) -> Result<Self, TomlError> {
|
||||
let default = match toml::ser::to_string(&Self::new()) {
|
||||
Ok(string) => { info!("Default TOML parse ... OK"); string },
|
||||
Err(err) => { error!("Couldn't parse default TOML into string"); return Err(TomlError::Serialize(err)) },
|
||||
Ok(string) => { info!("State | Default TOML parse ... OK"); string },
|
||||
Err(err) => { error!("State | Couldn't parse default TOML into string"); return Err(TomlError::Serialize(err)) },
|
||||
};
|
||||
let mut new: Self = match Figment::new().merge(Toml::string(&old)).merge(Toml::string(&default)).extract() {
|
||||
Ok(new) => { info!("TOML merge ... OK"); new },
|
||||
Err(err) => { error!("Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) },
|
||||
Ok(new) => { info!("State | TOML merge ... OK"); new },
|
||||
Err(err) => { error!("State | Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) },
|
||||
};
|
||||
// Attempt save
|
||||
Self::save(&mut new)?;
|
||||
|
@ -298,7 +302,7 @@ impl Node {
|
|||
}
|
||||
|
||||
// Convert [String] to [Node] Vec
|
||||
pub fn from_string(string: String) -> Result<Vec<(String, Self)>, TomlError> {
|
||||
pub fn from_string_to_vec(string: &String) -> Result<Vec<(String, Self)>, TomlError> {
|
||||
let nodes: toml::map::Map<String, toml::Value> = match toml::de::from_str(&string) {
|
||||
Ok(map) => {
|
||||
info!("Node | Parse ... OK");
|
||||
|
@ -312,7 +316,6 @@ impl Node {
|
|||
let size = nodes.keys().len();
|
||||
let mut vec = Vec::with_capacity(size);
|
||||
for (key, values) in nodes.iter() {
|
||||
// println!("{:#?}", values.get("ip")); std::process::exit(0);
|
||||
let node = Node {
|
||||
ip: values.get("ip").unwrap().as_str().unwrap().to_string(),
|
||||
rpc: values.get("rpc").unwrap().as_str().unwrap().to_string(),
|
||||
|
@ -357,8 +360,8 @@ impl Node {
|
|||
read_to_string(file, &path)?
|
||||
},
|
||||
};
|
||||
// Deserialize
|
||||
Self::from_string(string)
|
||||
// Deserialize, attempt merge if failed
|
||||
Self::from_string_to_vec(&string)
|
||||
}
|
||||
|
||||
// Completely overwrite current [node.toml]
|
||||
|
@ -380,26 +383,19 @@ impl Node {
|
|||
let string = Self::to_string(vec);
|
||||
match fs::write(path, string) {
|
||||
Ok(_) => { info!("TOML save ... OK"); Ok(()) },
|
||||
Err(err) => { error!("Couldn't overwrite TOML file"); return Err(TomlError::Io(err)) },
|
||||
Err(err) => { error!("Couldn't overwrite TOML file"); Err(TomlError::Io(err)) },
|
||||
}
|
||||
}
|
||||
|
||||
// // Take [Self] as input, merge it with whatever the current [default] is,
|
||||
// // leaving behind old keys+values and updating [default] with old valid ones.
|
||||
// // Automatically overwrite current file.
|
||||
// pub fn merge(old: &Self) -> Result<Self, TomlError> {
|
||||
// info!("Starting TOML merge...");
|
||||
// let old = match toml::ser::to_string(&old) {
|
||||
// Ok(string) => { info!("Old TOML parse ... OK"); string },
|
||||
// Err(err) => { error!("Couldn't parse old TOML into string"); return Err(TomlError::Serialize(err)) },
|
||||
// };
|
||||
// pub fn merge(old: &String) -> Result<Self, TomlError> {
|
||||
// info!("Node | Starting TOML merge...");
|
||||
// let default = match toml::ser::to_string(&Self::new()) {
|
||||
// Ok(string) => { info!("Default TOML parse ... OK"); string },
|
||||
// Err(err) => { error!("Couldn't parse default TOML into string"); return Err(TomlError::Serialize(err)) },
|
||||
// Ok(string) => { info!("Node | Default TOML parse ... OK"); string },
|
||||
// Err(err) => { error!("Node | Couldn't parse default TOML into string"); return Err(TomlError::Serialize(err)) },
|
||||
// };
|
||||
// let mut new: Self = match Figment::new().merge(Toml::string(&old)).merge(Toml::string(&default)).extract() {
|
||||
// Ok(new) => { info!("TOML merge ... OK"); new },
|
||||
// Err(err) => { error!("Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) },
|
||||
// Ok(new) => { info!("Node | TOML merge ... OK"); new },
|
||||
// Err(err) => { error!("Node | Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) },
|
||||
// };
|
||||
// // Attempt save
|
||||
// Self::save(&mut new)?;
|
||||
|
@ -408,15 +404,24 @@ impl Node {
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Custom Error [TomlError]
|
||||
#[derive(Debug)]
|
||||
pub enum TomlError {
|
||||
Io(std::io::Error),
|
||||
Path(String),
|
||||
Serialize(toml::ser::Error),
|
||||
Deserialize(toml::de::Error),
|
||||
Merge(figment::Error),
|
||||
}
|
||||
|
||||
impl Display for TomlError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
use TomlError::*;
|
||||
match self {
|
||||
Io(err) => write!(f, "{}: {} | {}", ERROR, self, err),
|
||||
Path(err) => write!(f, "{}: {} | {}", ERROR, self, err),
|
||||
Serialize(err) => write!(f, "{}: {} | {}", ERROR, self, err),
|
||||
Deserialize(err) => write!(f, "{}: {} | {}", ERROR, self, err),
|
||||
Merge(err) => write!(f, "{}: {} | {}", ERROR, self, err),
|
||||
Io(err) => write!(f, "{}: IO | {}", ERROR, err),
|
||||
Path(err) => write!(f, "{}: Path | {}", ERROR, err),
|
||||
Serialize(err) => write!(f, "{}: Serialize | {}", ERROR, err),
|
||||
Deserialize(err) => write!(f, "{}: Deserialize | {}", ERROR, err),
|
||||
Merge(err) => write!(f, "{}: Merge | {}", ERROR, err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -447,16 +452,6 @@ pub const DEFAULT_XMRIG_PATH: &'static str = r"XMRig\xmrig.exe";
|
|||
#[cfg(target_family = "unix")]
|
||||
pub const DEFAULT_XMRIG_PATH: &'static str = "xmrig/xmrig";
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Error Enum
|
||||
#[derive(Debug)]
|
||||
pub enum TomlError {
|
||||
Io(std::io::Error),
|
||||
Path(String),
|
||||
Serialize(toml::ser::Error),
|
||||
Deserialize(toml::de::Error),
|
||||
Merge(figment::Error),
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [File] Enum (for matching which file)
|
||||
#[derive(Clone,Copy,Eq,PartialEq,Debug,Deserialize,Serialize)]
|
||||
pub enum File {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
// Some images of ferris in byte form for error messages, etc
|
||||
|
||||
pub const FERRIS_HAPPY: &[u8] = include_bytes!("../images/ferris/happy.png");
|
||||
pub const FERRIS_OOPS: &[u8] = include_bytes!("../images/ferris/oops.png");
|
||||
pub const FERRIS_ERROR: &[u8] = include_bytes!("../images/ferris/error.png");
|
||||
pub const FERRIS_PANIC: &[u8] = include_bytes!("../images/ferris/panic.png"); // This isnt technically ferris but its ok since its spooky
|
||||
|
@ -35,7 +36,6 @@ pub const FERRIS_PANIC: &[u8] = include_bytes!("../images/ferris/panic.png"); //
|
|||
|
||||
|
||||
|
||||
|
||||
// This is the ANSI representation of Ferris in string form.
|
||||
// Calling [println!] on this straight up prints a 256-bit color Ferris to the terminal.
|
||||
// The ANSI codes were generated with [https://docs.rs/ansipix], but there is no reason to include the library and
|
||||
|
|
202
src/main.rs
202
src/main.rs
|
@ -86,7 +86,6 @@ pub struct App {
|
|||
xmrig: bool, // Is xmrig online?
|
||||
// State from [--flags]
|
||||
no_startup: bool,
|
||||
reset: bool,
|
||||
// Static stuff
|
||||
now: Instant, // Internal timer
|
||||
exe: String, // Path for [Gupax] binary
|
||||
|
@ -128,7 +127,6 @@ impl App {
|
|||
p2pool: false,
|
||||
xmrig: false,
|
||||
no_startup: false,
|
||||
reset: false,
|
||||
now: Instant::now(),
|
||||
exe: "".to_string(),
|
||||
dir: "".to_string(),
|
||||
|
@ -157,18 +155,42 @@ impl App {
|
|||
Ok(dir) => dir,
|
||||
Err(err) => { panic_main(err.to_string()); exit(1); },
|
||||
};
|
||||
// Read disk state if no [--reset] arg
|
||||
if app.reset == false {
|
||||
app.og = match State::get() {
|
||||
Ok(toml) => Arc::new(Mutex::new(toml)),
|
||||
Err(err) => { panic_main(err.to_string()); exit(1); },
|
||||
};
|
||||
}
|
||||
let mut og = app.og.lock().unwrap(); // Lock [og]
|
||||
app.state = og.clone();
|
||||
// Get node list
|
||||
app.og_node_vec = Node::get().unwrap();
|
||||
// Read disk state
|
||||
use TomlError::*;
|
||||
app.state = match State::get() {
|
||||
Ok(toml) => toml,
|
||||
Err(err) => {
|
||||
error!("State ... {}", err);
|
||||
match err {
|
||||
Io(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
Path(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
Serialize(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
Deserialize(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
Merge(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Error, ErrorButtons::ResetState),
|
||||
};
|
||||
State::new()
|
||||
},
|
||||
};
|
||||
app.og = Arc::new(Mutex::new(app.state.clone()));
|
||||
// Read node list
|
||||
app.og_node_vec = match Node::get() {
|
||||
Ok(toml) => toml,
|
||||
Err(err) => {
|
||||
error!("Node ... {}", err);
|
||||
match err {
|
||||
Io(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
Path(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
Serialize(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
Deserialize(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
Merge(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Error, ErrorButtons::ResetState),
|
||||
};
|
||||
Node::new_vec()
|
||||
},
|
||||
};
|
||||
app.node_vec = app.og_node_vec.clone();
|
||||
|
||||
|
||||
let mut og = app.og.lock().unwrap(); // Lock [og]
|
||||
// Handle max threads
|
||||
og.xmrig.max_threads = num_cpus::get();
|
||||
let current = og.xmrig.current_threads;
|
||||
|
@ -222,7 +244,7 @@ impl Default for Tab {
|
|||
//---------------------------------------------------------------------------------------------------- [ErrorState] struct
|
||||
pub struct ErrorState {
|
||||
error: bool, // Is there an error?
|
||||
msg: &'static str, // What message to display?
|
||||
msg: String, // What message to display?
|
||||
ferris: ErrorFerris, // Which ferris to display?
|
||||
buttons: ErrorButtons, // Which buttons to display?
|
||||
}
|
||||
|
@ -231,17 +253,17 @@ impl ErrorState {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
error: false,
|
||||
msg: "Unknown Error",
|
||||
msg: "Unknown Error".to_string(),
|
||||
ferris: ErrorFerris::Oops,
|
||||
buttons: ErrorButtons::Okay,
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience function to set the [App] error state
|
||||
pub fn set(&mut self, error: bool, msg: &'static str, ferris: ErrorFerris, buttons: ErrorButtons) {
|
||||
pub fn set(&mut self, error: bool, msg: impl Into<String>, ferris: ErrorFerris, buttons: ErrorButtons) {
|
||||
*self = Self {
|
||||
error,
|
||||
msg,
|
||||
msg: msg.into(),
|
||||
ferris,
|
||||
buttons,
|
||||
};
|
||||
|
@ -253,12 +275,15 @@ impl ErrorState {
|
|||
pub enum ErrorButtons {
|
||||
YesNo,
|
||||
StayQuit,
|
||||
ResetState,
|
||||
ResetNode,
|
||||
Okay,
|
||||
Quit,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ErrorFerris {
|
||||
Happy,
|
||||
Oops,
|
||||
Error,
|
||||
Panic,
|
||||
|
@ -267,6 +292,7 @@ pub enum ErrorFerris {
|
|||
//---------------------------------------------------------------------------------------------------- [Images] struct
|
||||
struct Images {
|
||||
banner: RetainedImage,
|
||||
happy: RetainedImage,
|
||||
oops: RetainedImage,
|
||||
error: RetainedImage,
|
||||
panic: RetainedImage,
|
||||
|
@ -276,6 +302,7 @@ impl Images {
|
|||
fn new() -> Self {
|
||||
Self {
|
||||
banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).unwrap(),
|
||||
happy: RetainedImage::from_image_bytes("happy.png", FERRIS_HAPPY).unwrap(),
|
||||
oops: RetainedImage::from_image_bytes("oops.png", FERRIS_OOPS).unwrap(),
|
||||
error: RetainedImage::from_image_bytes("error.png", FERRIS_ERROR).unwrap(),
|
||||
panic: RetainedImage::from_image_bytes("panic.png", FERRIS_PANIC).unwrap(),
|
||||
|
@ -388,6 +415,9 @@ fn init_auto(app: &App) {
|
|||
if app.no_startup {
|
||||
info!("[--no-startup] flag passed, skipping init_auto()...");
|
||||
return
|
||||
} else if app.error_state.error {
|
||||
info!("App error detected, skipping init_auto()...");
|
||||
return
|
||||
} else {
|
||||
info!("Starting init_auto()...");
|
||||
}
|
||||
|
@ -442,17 +472,31 @@ fn init_auto(app: &App) {
|
|||
}
|
||||
}
|
||||
|
||||
fn reset() {
|
||||
let mut code = 0;
|
||||
fn reset_state() -> Result<(), TomlError> {
|
||||
info!("Resetting [state.toml]...");
|
||||
match State::create_new() {
|
||||
Ok(_) => info!("Resetting [state.toml] ... OK"),
|
||||
Err(e) => { error!("Resetting [state.toml] ... FAIL ... {}", e); code = 1; },
|
||||
Ok(_) => { info!("Resetting [state.toml] ... OK"); Ok(()) },
|
||||
Err(e) => { error!("Resetting [state.toml] ... FAIL ... {}", e); Err(e) },
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_nodes() -> Result<(), TomlError> {
|
||||
info!("Resetting [node.toml]...");
|
||||
match Node::create_new() {
|
||||
Ok(_) => info!("Resetting [node.toml] ... OK"),
|
||||
Err(e) => { error!("Resetting [node.toml] ... FAIL ... {}", e); code = 1; },
|
||||
Ok(_) => { info!("Resetting [node.toml] ... OK"); Ok(()) },
|
||||
Err(e) => { error!("Resetting [node.toml] ... FAIL ... {}", e); Err(e) },
|
||||
}
|
||||
}
|
||||
|
||||
fn reset() {
|
||||
let mut code = 0;
|
||||
match reset_state() {
|
||||
Ok(_) => (),
|
||||
Err(_) => code = 1,
|
||||
}
|
||||
match reset_nodes() {
|
||||
Ok(_) => (),
|
||||
Err(_) => code = 1,
|
||||
}
|
||||
match code {
|
||||
0 => println!("\nGupax files were reset successfully."),
|
||||
|
@ -469,23 +513,25 @@ fn parse_args(mut app: App) -> App {
|
|||
// [help/version], exit early
|
||||
for arg in &args {
|
||||
match arg.as_str() {
|
||||
"-h"|"--help" => { println!("{}", ARG_HELP); exit(0); },
|
||||
"-v"|"--version" => {
|
||||
"--help" => { println!("{}", ARG_HELP); exit(0); },
|
||||
"--version" => {
|
||||
println!("Gupax {} [OS: {}, Commit: {}]\n\n{}", GUPAX_VERSION, OS_NAME, &COMMIT[..40], ARG_COPYRIGHT);
|
||||
exit(0);
|
||||
},
|
||||
"-f"|"--ferris" => { println!("{}", FERRIS_ANSI); exit(0); },
|
||||
"--ferris" => { println!("{}", FERRIS_ANSI); exit(0); },
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
// Everything else
|
||||
for arg in args {
|
||||
match arg.as_str() {
|
||||
"-l"|"--node-list" => { info!("Printing node list..."); print_disk_file(File::Node); }
|
||||
"-s"|"--state" => { info!("Printing state..."); print_disk_file(File::State); }
|
||||
"-r"|"--reset" => { reset(); }
|
||||
"-n"|"--no-startup" => { app.no_startup = true; }
|
||||
_ => { eprintln!("[Gupax error] Invalid option: [{}]\nFor help, use: [--help]", arg); exit(1); },
|
||||
"--nodes" => { info!("Printing node list..."); print_disk_file(File::Node); }
|
||||
"--state" => { info!("Printing state..."); print_disk_file(File::State); }
|
||||
"--reset-state" => if let Ok(()) = reset_state() { exit(0) } else { exit(1) },
|
||||
"--reset-nodes" => if let Ok(()) = reset_nodes() { exit(0) } else { exit(1) },
|
||||
"--reset-all" => reset(),
|
||||
"--no-startup" => app.no_startup = true,
|
||||
_ => { eprintln!("[Gupax error] Invalid option: [{}]\nFor help, use: [--help]", arg); exit(1); },
|
||||
}
|
||||
}
|
||||
app
|
||||
|
@ -604,14 +650,6 @@ fn main() {
|
|||
}
|
||||
|
||||
impl eframe::App for App {
|
||||
// pub fn new() -> Self {
|
||||
// Self {
|
||||
// error: false,
|
||||
// msg: String::new(),
|
||||
// image: RetainedImage::from_image_bytes("banner.png", FERRIS_ERROR).unwrap(),
|
||||
// buttons: ErrorButtons::Okay,
|
||||
// }
|
||||
// }
|
||||
fn on_close_event(&mut self) -> bool {
|
||||
if self.state.gupax.ask_before_quit {
|
||||
self.error_state.set(true, "", ErrorFerris::Oops, ErrorButtons::StayQuit);
|
||||
|
@ -652,8 +690,10 @@ impl eframe::App for App {
|
|||
|
||||
// Display ferris
|
||||
use ErrorFerris::*;
|
||||
use ErrorButtons::*;
|
||||
let ferris = match self.error_state.ferris {
|
||||
Oops => &self.img.oops,
|
||||
Happy => &self.img.happy,
|
||||
Oops => &self.img.oops,
|
||||
Error => &self.img.error,
|
||||
Panic => &self.img.panic,
|
||||
};
|
||||
|
@ -669,12 +709,23 @@ impl eframe::App for App {
|
|||
ui.add_sized([width, height], Label::new("--- Are you sure you want to quit? ---"));
|
||||
ui.add_sized([width, height], Label::new(text))
|
||||
},
|
||||
ResetState => {
|
||||
ui.add_sized([width, height], Label::new(format!("--- Gupax has encountered an error! ---\n{}", &self.error_state.msg)));
|
||||
ui.add_sized([width, height], Label::new("Reset Gupax state? (Your settings)"))
|
||||
},
|
||||
ResetNode => {
|
||||
ui.add_sized([width, height], Label::new(format!("--- Gupax has encountered an error! ---\n{}", &self.error_state.msg)));
|
||||
ui.add_sized([width, height], Label::new("Reset the manual node list?"))
|
||||
},
|
||||
_ => {
|
||||
ui.add_sized([width, height], Label::new("--- Gupax has encountered an error! ---"));
|
||||
ui.add_sized([width, height], Label::new(self.error_state.msg))
|
||||
match self.error_state.ferris {
|
||||
Panic => ui.add_sized([width, height], Label::new("--- Gupax has encountered an un-recoverable error! ---")),
|
||||
Happy => ui.add_sized([width, height], Label::new("--- Success! ---")),
|
||||
_ => ui.add_sized([width, height], Label::new("--- Gupax has encountered an error! ---")),
|
||||
};
|
||||
ui.add_sized([width, height], Label::new(&self.error_state.msg))
|
||||
},
|
||||
};
|
||||
use ErrorButtons::*;
|
||||
let height = ui.available_height();
|
||||
|
||||
// Capture [Esc] key
|
||||
|
@ -693,8 +744,47 @@ impl eframe::App for App {
|
|||
}
|
||||
if ui.add_sized([width, height/2.0], egui::Button::new("Quit")).clicked() { exit(0); }
|
||||
},
|
||||
// This code handles the [state.toml/node.toml] resetting, [panic!]'ing if it errors once more
|
||||
// Another error after this either means an IO error or permission error, which Gupax can't fix.
|
||||
// [Yes/No] buttons
|
||||
ResetState => {
|
||||
if ui.add_sized([width, height/2.0], egui::Button::new("Yes")).clicked() {
|
||||
match reset_state() {
|
||||
Ok(_) => {
|
||||
match State::get() {
|
||||
Ok(s) => {
|
||||
self.state = s;
|
||||
self.og = Arc::new(Mutex::new(self.state.clone()));
|
||||
self.error_state.set(true, "State read OK", ErrorFerris::Happy, ErrorButtons::Okay);
|
||||
},
|
||||
Err(e) => self.error_state.set(true, format!("State read fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
}
|
||||
},
|
||||
Err(e) => self.error_state.set(true, format!("State reset fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
};
|
||||
}
|
||||
if esc || ui.add_sized([width, height/2.0], egui::Button::new("No")).clicked() { self.error_state = ErrorState::new() }
|
||||
},
|
||||
ResetNode => {
|
||||
if ui.add_sized([width, height/2.0], egui::Button::new("Yes")).clicked() {
|
||||
match reset_nodes() {
|
||||
Ok(_) => {
|
||||
match Node::get() {
|
||||
Ok(s) => {
|
||||
self.node_vec = s;
|
||||
self.og_node_vec = self.node_vec.clone();
|
||||
self.error_state.set(true, "Node read OK", ErrorFerris::Happy, ErrorButtons::Okay);
|
||||
},
|
||||
Err(e) => self.error_state.set(true, format!("Node read fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
}
|
||||
},
|
||||
Err(e) => self.error_state.set(true, format!("Node reset fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
|
||||
};
|
||||
}
|
||||
if esc || ui.add_sized([width, height/2.0], egui::Button::new("No")).clicked() { self.error_state = ErrorState::new() }
|
||||
},
|
||||
Okay => if esc || ui.add_sized([width, height], egui::Button::new("Okay")).clicked() { self.error_state = ErrorState::new(); },
|
||||
Quit => if ui.add_sized([width, height], egui::Button::new("Quit")).clicked() { exit(0); },
|
||||
Quit => if ui.add_sized([width, height], egui::Button::new("Quit")).clicked() { exit(1); },
|
||||
}
|
||||
})});
|
||||
return
|
||||
|
@ -777,13 +867,21 @@ impl eframe::App for App {
|
|||
self.node_vec = self.og_node_vec.clone();
|
||||
}
|
||||
if ui.add_sized([width, height], egui::Button::new("Save")).on_hover_text("Save changes").clicked() {
|
||||
let mut og = self.og.lock().unwrap();
|
||||
og.gupax = self.state.gupax.clone();
|
||||
og.p2pool = self.state.p2pool.clone();
|
||||
og.xmrig = self.state.xmrig.clone();
|
||||
self.og_node_vec = self.node_vec.clone();
|
||||
self.state.save();
|
||||
Node::save(&self.og_node_vec);
|
||||
match self.state.save() {
|
||||
Ok(_) => {
|
||||
let mut og = self.og.lock().unwrap();
|
||||
og.gupax = self.state.gupax.clone();
|
||||
og.p2pool = self.state.p2pool.clone();
|
||||
og.xmrig = self.state.xmrig.clone();
|
||||
},
|
||||
Err(e) => {
|
||||
self.error_state.set(true, format!("State file: {}", e), ErrorFerris::Error, ErrorButtons::Okay);
|
||||
},
|
||||
};
|
||||
match Node::save(&self.og_node_vec) {
|
||||
Ok(_) => self.og_node_vec = self.node_vec.clone(),
|
||||
Err(e) => self.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Error, ErrorButtons::Okay),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -872,7 +970,7 @@ impl eframe::App for App {
|
|||
|
||||
ui.add_space(ui.available_height()/2.0);
|
||||
ui.hyperlink_to("Powered by egui", "https://github.com/emilk/egui");
|
||||
ui.hyperlink_to(format!("{} {}", GITHUB, "Gupax made by hinto-janaiyo"), "https://www.github.com/hinto-janaiyo/gupax");
|
||||
ui.hyperlink_to(format!("{} {}", GITHUB, "Made by hinto-janaiyo"), "https://gupax.io");
|
||||
ui.label("egui is licensed under MIT & Apache-2.0");
|
||||
ui.label("Gupax, P2Pool, and XMRig are licensed under GPLv3");
|
||||
});
|
||||
|
|
|
@ -27,8 +27,6 @@ use log::*;
|
|||
// header::{HeaderValue,LOCATION},
|
||||
//};
|
||||
|
||||
use reqwest::blocking::ClientBuilder;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Node list
|
||||
// Community Monerod nodes. All of these have ZMQ on 18083.
|
||||
// Adding/removing nodes will need changes to pretty
|
||||
|
|
|
@ -332,7 +332,7 @@ impl P2pool {
|
|||
let text = format!("{}\n Currently selected node: {}. {}\n Current amount of nodes: {}/1000", text, self.selected_index, self.selected_name, node_vec_len);
|
||||
// If the node already exists, show [Save] and mutate the already existing node
|
||||
if exists {
|
||||
ui.set_enabled(save_diff);
|
||||
ui.set_enabled(!incorrect_input && save_diff);
|
||||
if ui.add_sized([width, text_edit], Button::new("Save")).on_hover_text(text).clicked() {
|
||||
let node = Node {
|
||||
ip: self.ip.clone(),
|
||||
|
|
Loading…
Reference in a new issue