1use std::
20{
21 fs,
22 path::Path,
23 time::Duration,
24};
25
26use ureq::{ Error, Agent };
27
28use serde_json::Value;
29
30use semver::Version;
31
32use crate::options;
33
34#[cfg(feature = "client")]
35use std::sync::mpsc::Sender;
36
37#[cfg(feature = "client")]
38use crate::network::client::ClientEvent;
39
40fn get_dir(dir: &str) -> String
42{
43 dir.replace("{HOME}", dirs::home_dir().expect("Could not determine home directory").to_str().expect("Invalid home directory"))
44}
45
46fn get_config_dir() -> String
47{
48 get_dir(options::USER_CONFIG_DIR)
49}
50
51pub fn get_version<'a>() -> &'a str {
54 env!("CARGO_PKG_VERSION")
55}
56
57pub fn get_identifier() -> String {
59 format!("WHY2/{}", get_version())
60}
61
62pub fn fetch_data(url: &str) -> Result<String, Error> {
64 let agent: Agent = Agent::config_builder()
66 .timeout_global(Some(Duration::from_millis(options::FETCH_TIMEOUT)))
67 .build()
68 .into();
69
70 agent.get(url)
72 .header("User-Agent", &get_identifier())
73 .call()?
74 .body_mut()
75 .read_to_string()
76}
77
78pub fn check_version(#[cfg(feature = "client")] tx: &Sender<ClientEvent>) {
80 let metadata_raw = match fetch_data(options::METADATA_URL)
82 {
83 Ok(m) => m,
84 Err(_) =>
85 {
86 let print_text = "Fetching versions failed, this release could be unsafe!";
87
88 #[cfg(feature = "client")]
89 {
90 tx.send(ClientEvent::Info(print_text.to_string(), true, 0)).unwrap()
91 }
92
93 #[cfg(feature = "server")]
94 {
95 log::warn!("{print_text}");
96 }
97
98 return;
99 }
100 };
101
102 let metadata: Value = serde_json::from_str(&metadata_raw).expect("Parsing versions failed"); let newest_version = metadata.get("crate") .and_then(|c| c.get("newest_version"))
106 .and_then(|v| v.as_str())
107 .unwrap();
108
109 let current_version = get_version();
111 if current_version != newest_version
112 {
113 let versions = metadata.get("versions").and_then(|v| v.as_array()).unwrap();
115 let mut newer_versions = 0;
116 let current_version = Version::parse(current_version).expect("Invalid version");
117
118 for version in versions
120 {
121 if Version::parse(version.get("num").and_then(|n| n.as_str()).unwrap()).unwrap() > current_version
123 {
124 newer_versions += 1;
126 }
127 }
128
129 let print_text = format!("This release could be unsafe! You are {newer_versions} versions behind! ({current_version}/{newest_version})");
130
131 #[cfg(feature = "client")]
132 {
133 tx.send(ClientEvent::Info(print_text, true, 0)).unwrap()
134 }
135
136 #[cfg(feature = "server")]
137 {
138 log::warn!("{print_text}");
139 }
140 }
141}
142
143pub fn check_directory() {
145 let config = get_config_dir() + options::CONFIG_DIR;
146
147 if !Path::new(&config).is_dir()
149 {
150 fs::create_dir_all(config).expect("Failed to create WHY2 config directory");
151 }
152}
153
154pub fn get_why2_dir() -> String {
156 get_config_dir() + options::CONFIG_DIR
157}