valera_utils/
lib.rs

1#![allow(dead_code, clippy::useless_format)]
2
3use std::time::{SystemTime, UNIX_EPOCH};
4
5pub fn alert() {
6	let sound_bytes = include_bytes!("../Notification.mp3");
7	let cursor = std::io::Cursor::new(sound_bytes);
8	let source = rodio::Decoder::new(cursor).unwrap();
9	let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
10	let sink = rodio::Sink::try_new(&stream_handle).unwrap();
11	sink.append(source);
12	sink.sleep_until_end();
13}
14
15pub fn get_caller_name() -> String {
16	let bt = backtrace::Backtrace::new();
17	let get_name = |index: usize| -> String {
18		bt.frames()
19			.get(index)
20			.and_then(|frame| frame.symbols().get(0))
21			.and_then(|symbol| symbol.filename())
22			.and_then(|filename| filename.file_stem())
23			.map(|name| name.to_string_lossy().into_owned())
24			.unwrap_or_else(|| "unknown".to_string())
25	};
26	format!("{}", get_name(1))
27}
28
29/// a thing that sends me a ping. Crate for myself, so this is configured out of the box. For personal use, change the receiver. Or submit a pull request that does this properly
30pub fn tg_msg(text: Option<&str>) {
31	let message = match text {
32		Some(t) => t.to_string(),
33		None => format!("{} has finished", get_caller_name()),
34	};
35	let params = [("chat_id", "-1001800341082"), ("text", &message)];
36	let _ = reqwest::blocking::Client::new()
37		.post("https://api.telegram.org/bot6225430873:AAEYlbJ2bY-WsLADxlWY1NS-z4r75sf9X5I/sendMessage")
38		.form(&params)
39		.send();
40}
41pub fn tg() {
42	tg_msg(None);
43}
44
45pub fn shutdown() {
46	std::process::Command::new("shutdown").args(["/s", "/t", "1"]).output().unwrap();
47}
48
49#[derive(Clone, Debug)]
50pub struct ProgressBar {
51	bar_width: f64,
52	timestamp_ms: u128,
53	total: f64,
54}
55impl ProgressBar {
56	pub fn new(total: usize) -> Self {
57		let bar_width: f64 = 133.0;
58		let timestamp_ms = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis();
59		let total = total as f64;
60		ProgressBar { bar_width, timestamp_ms, total }
61	}
62	pub fn progress(&mut self, i: usize) {
63		const CLEAR: &str = "\x1B[2J\x1B[1;1H";
64		let scalar: f64 = self.bar_width / self.total;
65		let display_i = (i as f64 * scalar) as usize;
66		let display_total = (self.total * scalar) as usize;
67
68		println!("{}", CLEAR);
69		println!("[{}{}]", "*".repeat(display_i), " ".repeat(display_total - display_i));
70
71		let since_timestamp_ms = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() - self.timestamp_ms;
72		let progress_left_scalar = (self.total - i as f64) / i as f64;
73		let left_s = (since_timestamp_ms as f64 * progress_left_scalar / 1000.0) as usize;
74		println!("Time left: ≈ {}s", left_s);
75	}
76}
77
78// Json
79//Todo: move this under feature-flag json, so I don't import all this crap for every project. Do same for all others.
80use serde::de::DeserializeOwned;
81use serde::{Deserialize, Serialize};
82use std::collections::VecDeque;
83use std::fs::File;
84use std::io::{Read, Write};
85pub fn jdump<T: Serialize>(filepath: String, object: T) {
86	let parent_dir = std::path::Path::new(&filepath).parent().unwrap();
87	let _ = std::fs::create_dir_all(parent_dir);
88	let mut file = File::create(&filepath).unwrap();
89	let serialized = serde_json::to_string(&object).unwrap();
90	file.write_all(serialized.as_bytes()).unwrap();
91}
92// to use do `let my_struct: MyStruct = jload(path);`. So definition of the struct should just be accessible somewhere in the code.
93pub fn jload<T: DeserializeOwned>(filepath: String) -> T {
94	let mut file = File::open(&filepath).unwrap();
95	let mut contents = String::new();
96	file.read_to_string(&mut contents).unwrap();
97	return serde_json::from_str(&contents).unwrap();
98}
99pub fn jadd<T>(filepath: String, object: T)
100where
101	T: for<'de> Deserialize<'de> + Serialize,
102{
103	let parent_dir = std::path::Path::new(&filepath).parent().unwrap();
104	let _ = std::fs::create_dir_all(parent_dir);
105
106	let mut contents = String::new();
107	if let Ok(mut file) = File::open(&filepath) {
108		file.read_to_string(&mut contents).unwrap();
109	}
110
111	let mut objects: VecDeque<T> = serde_json::from_str(&contents).unwrap_or_else(|_| VecDeque::new());
112
113	objects.push_back(object);
114
115	let mut file = File::create(&filepath).unwrap();
116	file.write_all(serde_json::to_string(&objects).unwrap().as_bytes()).unwrap();
117}
118//