1use std::
20{
21 fs,
22 env,
23 time::Duration,
24 path::Path,
25};
26
27use ureq::{ Error, Agent };
28
29use serde_json::Value;
30
31use semver::Version;
32
33use crate::consts;
34
35#[cfg(feature = "client")]
36use std::sync::mpsc::Sender;
37
38#[cfg(feature = "client")]
39use crate::network::client::ClientEvent;
40
41#[cfg(feature = "server")]
42use std::path::PathBuf;
43
44fn get_dir(dir: &str) -> String
46{
47 dir.replace("{HOME}", dirs::home_dir().expect("Could not determine home directory").to_str().expect("Invalid home directory"))
48}
49
50pub fn get_version<'a>() -> &'a str {
53 env!("CARGO_PKG_VERSION")
54}
55
56pub fn get_identifier() -> String {
58 format!("WHY2/{}", get_version())
59}
60
61pub fn fetch_data(url: &str) -> Result<String, Error> {
63 let agent: Agent = Agent::config_builder()
65 .timeout_global(Some(Duration::from_millis(consts::FETCH_TIMEOUT)))
66 .build()
67 .into();
68
69 agent.get(url)
71 .header("User-Agent", &get_identifier())
72 .call()?
73 .body_mut()
74 .read_to_string()
75}
76
77pub fn check_version(#[cfg(feature = "client")] tx: &Sender<ClientEvent>) {
79 let metadata_raw = match fetch_data(consts::METADATA_URL)
81 {
82 Ok(m) => m,
83 Err(_) =>
84 {
85 #[cfg(feature = "client")]
86 {
87 tx.send(ClientEvent::VersionFailed).unwrap();
88 }
89
90 #[cfg(feature = "server")]
91 {
92 log::warn!("Fetching versions failed, this release could be unsafe!");
93 }
94
95 return;
96 }
97 };
98
99 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"))
103 .and_then(|v| v.as_str())
104 .unwrap();
105
106 let current_version = get_version();
108 if current_version != newest_version
109 {
110 let versions = metadata.get("versions").and_then(|v| v.as_array()).unwrap();
112 let mut newer_versions = 0usize;
113 let current_version = Version::parse(current_version).expect("Invalid version");
114
115 for version in versions
117 {
118 if Version::parse(version.get("num").and_then(|n| n.as_str()).unwrap()).unwrap() > current_version
120 {
121 newer_versions += 1;
123 }
124 }
125
126 #[cfg(feature = "client")]
127 {
128 tx.send(ClientEvent::UnsafeVersion(newer_versions, current_version, newest_version.to_owned())).unwrap();
129 }
130
131 #[cfg(feature = "server")]
132 {
133 log::warn!("This release could be unsafe! You are {newer_versions} versions behind! ({current_version}/{newest_version})");
134 }
135 }
136}
137
138pub fn get_why2_dir() -> String {
140 get_dir(consts::CONFIG_DIR)
141}
142
143pub fn check_directory() {
145 let config = get_why2_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
154#[cfg(feature = "server")]
155pub fn get_upload_dir(username: &str) -> PathBuf {
157 env::temp_dir().join(consts::UPLOADS_DIR).join(username)
158}