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