You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
gui/src/app.rs

291 lines
14 KiB

use std::time::{Duration, SystemTime};
use std::net::TcpStream;
use eframe::egui;
use egui::FontFamily::Proportional;
use egui::FontId;
use egui::TextStyle::*;
use crate::player::Player;
use crate::tor::GuiTor;
use crate::stats::Market;
use crate::irc::Client as IRCClient;
use libtor::Error as libtorError;
pub struct App {
pub player: Player,
pub market: Market,
pub irc: IRCClient,
pub tor_required: bool,
pub tor_started: bool,
pub tor_connected: bool,
pub to_data: String,
pub show_irc: bool,
pub irc_message: String,
pub irc_connected: bool,
pub show_market_data: bool,
pub show_radio: bool,
pub irc_stream: Option<TcpStream>,
pub irc_last_ping: SystemTime,
pub irc_active_channel: String
}
impl Default for App {
fn default() -> Self {
Self {
player: Player::default(),
market: Market::new(),
irc: IRCClient::new(),
tor_started: false,
tor_required: true,
tor_connected: false,
show_market_data: false,
show_irc: false,
irc_connected: false,
to_data: "".to_owned(),
irc_message: "".to_owned(),
show_radio: true,
irc_stream: None,
irc_last_ping: SystemTime::now(),
irc_active_channel: "#wownero-music".to_owned()
}
}
}
fn show_boolmoji(b: bool) -> String {
if b { return "✔".to_owned() } else { return "☠".to_owned() }
}
impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let mut style = (*ctx.style()).clone();
style.text_styles = [
(Heading, FontId::new(30.0, Proportional)),
(Name("Heading2".into()), FontId::new(25.0, Proportional)),
(Name("Context".into()), FontId::new(23.0, Proportional)),
(Body, FontId::new(18.0, Proportional)),
(Monospace, FontId::new(14.0, Proportional)),
(Button, FontId::new(14.0, Proportional)),
(Small, FontId::new(10.0, Proportional)),
].into();
ctx.set_style(style);
ctx.set_visuals(egui::Visuals::dark());
egui::TopBottomPanel::top("top").show(ctx, |ui| {
ui.heading("Wownero Operations Center");
ui.label("Made by ya boi, lza_menace");
ui.hyperlink("https://lzahq.tech");
});
egui::CentralPanel::default().show(ctx, |ui| {
ui.horizontal(|ui| {
ui.checkbox(&mut self.tor_required, "Require Tor");
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");
});
// Tor
if self.tor_required {
if self.tor_started {
ui.label(
egui::RichText::new(
format!(
"Tor Started: {} Tor Connected: {} Proxy Up: {}",
show_boolmoji(self.tor_started),
show_boolmoji(self.tor_connected),
show_boolmoji(self.tor_connected)
)
)
);
} else {
if ui.button("Connect to the Tor network").clicked() {
let _t: std::thread::JoinHandle<Result<u8, libtorError>> = GuiTor::start_tor();
self.tor_started = true;
self.tor_connected = true;
}
}
}
ui.separator();
// WOW!Radio
if self.show_radio {
ui.heading(egui::RichText::new("WOW!Radio").color(egui::Color32::WHITE));
ui.label(egui::RichText::new("Your home for the most diabolical playlist of the century, made by the skeevers, scallywags, chupacabras, snails, and whores of the Wownero community. Join da chat to peep da scoop.\n").color(egui::Color32::WHITE));
ui.horizontal(|ui| {
if self.player.playing {
if ui.button("⏸").clicked() {
let _ = self.player.sink.pause();
self.player.playing = false;
}
// if ui.button("⏹").clicked() {
// let _ = self.player.sink.stop();
// self.player.playing = false;
// let _ = std::fs::remove_file(crate::RADIO_STREAM);
// }
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 f = std::fs::File::open(crate::RADIO_STREAM);
if let Ok(fo) = f {
let file = std::io::BufReader::new(fo);
let source = rodio::Decoder::new(file);
if source.is_err() {
return ()
}
let _ = self.player.sink.append(source.unwrap());
let _ = self.player.sink.play();
} else {
return ()
}
}
} else {
if ! self.tor_connected && self.tor_required {
ui.label("Connect to the Tor network first.");
} else {
if ui.button("▶").clicked() {
if ! self.tor_connected && self.tor_required {
return ();
}
// If stream thread is done, start again
if self.player.stream_thread.is_finished() {
self.player.stream_thread = self.player.start_radio_stream(self.tor_required);
}
let _ = self.player.sink.play();
self.player.playing = true;
}
}
}
});
// Show spinner when downloading, along with file size
if ! self.player.stream_thread.is_finished() {
ui.horizontal(|ui| {
ui.spinner();
let size: u64 = self.player.get_radio_size();
ui.label(format!(
"{:?} -> {} ({} bytes)",
self.player.stream_source,
crate::RADIO_STREAM,
size
));
});
}
// Show exif metadata when radio file available to read
if self.player.playing && self.player.get_radio_size() > 0 {
let rt = egui::RichText::new(
format!("\n{:?}", self.player.stream_exif))
.color(egui::Color32::WHITE)
.size(18.0);
ui.label(rt);
let dur = self.player.exif_date.elapsed().unwrap();
if dur > Duration::from_secs(15) {
self.player.exif_date = SystemTime::now();
self.player.stream_exif = self.player.get_song_meta().unwrap();
}
if ui.button(" +1 ").clicked() {
let _ = self.irc.send_tune();
}
}
ui.separator();
}
// IRC
if self.show_irc && ! self.irc_connected {
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(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 = 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());
}
self.irc_message = "".to_owned();
}
});
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();
}
});
}
// Market
if self.show_market_data {
egui::ComboBox::from_label("Pick currency base.")
.selected_text(format!("{}", self.market.denomination))
.show_ui(ui, |ui| {
ui.selectable_value(&mut self.market.denomination, "sats".to_owned(), "sats");
ui.selectable_value(&mut self.market.denomination, "usd".to_owned(), "usd");
ui.selectable_value(&mut self.market.denomination, "eth".to_owned(), "eth");
}
);
if self.market.last_check_time.elapsed().unwrap() > Duration::from_secs(120) {
println!("[+] Refreshing WOW market data.");
self.market.store_market_data(self.tor_required);
self.market.last_check_time = SystemTime::now();
}
if self.market.last_check_time.elapsed().unwrap() < Duration::from_secs(30) && self.market.read_json_from_file().len() == 0 {
ui.horizontal(|ui| {
ui.spinner();
ui.label("Fetching market data...");
});
}
self.market.last_cg_data = self.market.read_json_from_file();
let m = &self.market.last_cg_data;
let md = &m["market_data"];
ui.horizontal_wrapped(|ui| {
ui.vertical(|ui| {
ui.label("Current Price");
ui.heading(egui::RichText::new(md["current_price"][&self.market.denomination].to_string()).strong());
ui.label("All-Time High");
ui.heading(egui::RichText::new(md["ath"][&self.market.denomination].to_string()).strong());
ui.label("All-Time Low");
ui.heading(egui::RichText::new(md["atl"][&self.market.denomination].to_string()).strong());
ui.label("Total Volume");
ui.heading(egui::RichText::new(md["total_volume"][&self.market.denomination].to_string()).strong());
ui.label("Market Cap");
ui.heading(egui::RichText::new(md["market_cap"][&self.market.denomination].to_string()).strong());
});
ui.vertical(|ui| {
ui.label("PriceChg% (~24hrs)");
ui.heading(egui::RichText::new(md["price_change_percentage_24h_in_currency"][&self.market.denomination].to_string()).strong());
ui.label("PriceChg% (~7d)");
ui.heading(egui::RichText::new(md["price_change_percentage_7d_in_currency"][&self.market.denomination].to_string()).strong());
ui.label("PriceChg% (~14d)");
ui.heading(egui::RichText::new(md["price_change_percentage_14d_in_currency"][&self.market.denomination].to_string()).strong());
ui.label("PriceChg% (~30d)");
ui.heading(egui::RichText::new(md["price_change_percentage_30d_in_currency"][&self.market.denomination].to_string()).strong());
});
});
}
});
}
}