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::consts;
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
46pub fn get_version<'a>() -> &'a str {
49 env!("CARGO_PKG_VERSION")
50}
51
52pub fn get_identifier() -> String {
54 format!("WHY2/{}", get_version())
55}
56
57pub fn fetch_data(url: &str) -> Result<String, Error> {
59 let agent: Agent = Agent::config_builder()
61 .timeout_global(Some(Duration::from_millis(consts::FETCH_TIMEOUT)))
62 .build()
63 .into();
64
65 agent.get(url)
67 .header("User-Agent", &get_identifier())
68 .call()?
69 .body_mut()
70 .read_to_string()
71}
72
73pub fn check_version(#[cfg(feature = "client")] tx: &Sender<ClientEvent>) {
75 let metadata_raw = match fetch_data(consts::METADATA_URL)
77 {
78 Ok(m) => m,
79 Err(_) =>
80 {
81 #[cfg(feature = "client")]
82 {
83 tx.send(ClientEvent::VersionFailed).unwrap();
84 }
85
86 #[cfg(feature = "server")]
87 {
88 log::warn!("Fetching versions failed, this release could be unsafe!");
89 }
90
91 return;
92 }
93 };
94
95 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"))
99 .and_then(|v| v.as_str())
100 .unwrap();
101
102 let current_version = get_version();
104 if current_version != newest_version
105 {
106 let versions = metadata.get("versions").and_then(|v| v.as_array()).unwrap();
108 let mut newer_versions = 0usize;
109 let current_version = Version::parse(current_version).expect("Invalid version");
110
111 for version in versions
113 {
114 if Version::parse(version.get("num").and_then(|n| n.as_str()).unwrap()).unwrap() > current_version
116 {
117 newer_versions += 1;
119 }
120 }
121
122 #[cfg(feature = "client")]
123 {
124 tx.send(ClientEvent::UnsafeVersion(newer_versions, current_version, newest_version.to_owned())).unwrap();
125 }
126
127 #[cfg(feature = "server")]
128 {
129 log::warn!("This release could be unsafe! You are {newer_versions} versions behind! ({current_version}/{newest_version})");
130 }
131 }
132}
133
134pub fn get_why2_dir() -> String {
136 get_dir(consts::CONFIG_DIR)
137}
138
139pub fn check_directory() {
141 let config = get_why2_dir();
142
143 if !Path::new(&config).is_dir()
145 {
146 fs::create_dir_all(config).expect("Failed to create WHY2 config directory");
147 }
148}