skyblock_repo/utils/
repo.rs1#[cfg(feature = "python")]
2pub mod python {
3 use std::fs::{File, OpenOptions, create_dir_all, exists, remove_dir_all, remove_file, rename};
4 use std::io::{self, Write};
5 use std::path::Path;
6
7 use pyo3::exceptions::{PyIOError, PyRuntimeError};
8 use pyo3::*;
9
10 #[pyfunction(name = "download_repo")]
12 #[pyo3(signature=(delete_zip=true))]
13 pub fn download_zip(delete_zip: bool) -> PyResult<()> {
14 let url = "https://github.com/SkyblockRepo/Repo/archive/main.zip";
15
16 let mut response = ureq::get(url)
17 .call()
18 .map_err(|e| PyErr::new::<PyRuntimeError, _>(e.to_string()))?;
19
20 if !exists("SkyblockRepo")?
21 || (!exists("SkyblockRepo-main.zip")? && !exists("SkyblockRepo")?)
22 {
23 if response.status() == 200 {
24 let mut file = OpenOptions::new()
25 .read(true)
26 .write(true)
27 .create_new(true)
28 .open("SkyblockRepo-main.zip")?;
29
30 let content = response
31 .body_mut()
32 .read_to_vec()
33 .map_err(|e| PyErr::new::<PyRuntimeError, _>(e.to_string()))?;
34 file.write_all(&content)?;
35
36 unzip_repo(file)?;
37 } else {
38 return Err(PyErr::new::<PyRuntimeError, _>(format!(
39 "Reqwest failed with status {}",
40 response.status()
41 )));
42 }
43 } else {
44 return Ok(());
45 }
46
47 if delete_zip {
48 remove_file(Path::new("SkyblockRepo-main.zip"))?;
49 }
50
51 Ok(())
52 }
53
54 fn unzip_repo(file: File) -> PyResult<()> {
55 let mut archive =
56 zip::ZipArchive::new(file).map_err(|e| PyErr::new::<PyIOError, _>(e.to_string()))?;
57
58 for i in 0..archive.len() {
59 let mut file = archive
60 .by_index(i)
61 .map_err(|e| PyErr::new::<PyIOError, _>(e.to_string()))?;
62 let outpath = match file.enclosed_name() {
63 | Some(path) => path,
64 | None => continue,
65 };
66
67 if file.is_dir() {
68 create_dir_all(&outpath)?;
69 } else {
70 if let Some(p) = outpath.parent() {
71 if !p.exists() {
72 create_dir_all(p)?;
73 }
74 }
75 let mut outfile = File::create(&outpath)?;
76 io::copy(&mut file, &mut outfile)?;
77 }
78
79 #[cfg(unix)]
80 {
81 use std::os::unix::fs::PermissionsExt;
82
83 if let Some(mode) = file.unix_mode() {
84 use std::fs::{Permissions, set_permissions};
85
86 set_permissions(&outpath, Permissions::from_mode(mode))?;
87 }
88 }
89 }
90
91 rename(Path::new("Repo-main"), Path::new("SkyblockRepo"))?;
92
93 Ok(())
94 }
95
96 #[pyfunction(name = "delete_repo")]
97 pub fn delete_repo_files() -> PyResult<()> {
98 let _ = remove_file("SkyblockRepo-main.zip").or_else(|err| {
99 if err.kind() == io::ErrorKind::NotFound {
101 Ok(())
102 } else {
103 Err(err)
104 }
105 })?;
106 remove_dir_all("SkyblockRepo")?;
107 Ok(())
108 }
109}
110
111#[cfg(not(feature = "python"))]
112pub mod rust {
113 use std::fs::{File, OpenOptions, create_dir_all, exists, remove_dir_all, remove_file, rename};
114 use std::io::{self, Write};
115 use std::path::Path;
116
117 #[cfg(feature = "log")]
118 use log::{error, trace};
119
120 pub fn download_zip(delete_zip: bool) -> Result<(), Box<dyn std::error::Error>> {
124 let url = "https://github.com/SkyblockRepo/Repo/archive/main.zip";
125
126 let mut response = ureq::get(url).call()?;
127
128 if !exists("SkyblockRepo")?
129 || (!exists("SkyblockRepo-main.zip")? && !exists("SkyblockRepo")?)
130 {
131 if response.status() == 200 {
132 let mut file = OpenOptions::new()
133 .read(true)
134 .write(true)
135 .create_new(true)
136 .open("SkyblockRepo-main.zip")?;
137
138 let content = response.body_mut().read_to_vec()?;
139 file.write_all(&content)?;
140
141 unzip_repo(file)?;
142 } else {
143 return Err(format!("Reqwest failed with status {}", response.status()).into());
144 }
145 } else {
146 #[cfg(feature = "log")]
147 error!(
148 "SkyblockRepo-main.zip and/or SkyblockRepo/ directory are present, if you wish to refetch them, delete them."
149 );
150 return Ok(());
151 }
152
153 if delete_zip {
154 remove_file(Path::new("SkyblockRepo-main.zip"))?;
155 }
156
157 Ok(())
158 }
159
160 fn unzip_repo(file: File) -> Result<(), Box<dyn std::error::Error>> {
161 let mut archive = zip::ZipArchive::new(file)?;
162
163 for i in 0..archive.len() {
164 let mut file = archive.by_index(i)?;
165 let outpath = match file.enclosed_name() {
166 | Some(path) => path,
167 | None => continue,
168 };
169
170 if file.is_dir() {
171 #[cfg(feature = "log")]
172 trace!("File {} extracted to \"{}\"", i, outpath.display());
173 create_dir_all(&outpath)?;
174 } else {
175 #[cfg(feature = "log")]
176 trace!(
177 "File {} extracted to \"{}\" ({} bytes)",
178 i,
179 outpath.display(),
180 file.size()
181 );
182 if let Some(p) = outpath.parent() {
183 if !p.exists() {
184 create_dir_all(p)?;
185 }
186 }
187 let mut outfile = File::create(&outpath)?;
188 io::copy(&mut file, &mut outfile)?;
189 }
190
191 #[cfg(unix)]
192 {
193 use std::os::unix::fs::PermissionsExt;
194
195 if let Some(mode) = file.unix_mode() {
196 use std::fs::{Permissions, set_permissions};
197
198 set_permissions(&outpath, Permissions::from_mode(mode))?;
199 }
200 }
201 }
202
203 rename(Path::new("Repo-main"), Path::new("SkyblockRepo"))?;
204
205 Ok(())
206 }
207
208 pub fn delete_repo_files() -> Result<(), Box<dyn std::error::Error>> {
209 let _ = remove_file("SkyblockRepo-main.zip").or_else(|err| {
210 if err.kind() == io::ErrorKind::NotFound {
212 Ok(())
213 } else {
214 Err(err)
215 }
216 })?;
217 remove_dir_all("SkyblockRepo")?;
218 Ok(())
219 }
220}