1use crate::config::Config;
2use crate::error::Error;
3use crate::showroom;
4use crate::source::Source;
5use path_absolutize::*;
6use rand::prelude::*;
7use std::fs;
8use std::path::PathBuf;
9use std::process::exit;
10use std::str::FromStr;
11
12#[derive(Debug)]
13pub struct Wall {
14 pub config: Option<Config>,
15}
16
17impl Wall {
18 pub fn new(config: Option<Config>) -> Wall {
19 Wall { config }
20 }
21
22 pub fn absolute(&self, path: PathBuf) -> PathBuf {
23 match path.absolutize() {
24 Ok(p) => p.to_path_buf(),
25 Err(_) => {
26 eprintln!("Can't not absolutize the path.");
27 exit(1);
28 }
29 }
30 }
31
32 pub fn set(&self, path: PathBuf) {
33 let binding = self.absolute(path.clone());
34
35 let path = match binding.to_str() {
36 Some(p) => p,
37 None => {
38 eprintln!("Well, you passed wrong path");
39 exit(1);
40 }
41 };
42
43 if wallpaper::set_from_path(path).is_ok() {
44 println!("Voila!");
45 }
46 }
47
48 fn get_pics(dir: &PathBuf) -> Result<Vec<PathBuf>, Error> {
49 let mut result: Vec<PathBuf> = Vec::new();
50
51 if dir.is_dir() {
52 let read_dir = match fs::read_dir(dir) {
53 Ok(e) => e,
54 Err(err) => return Err(Error::ReadDirError(err)),
55 };
56
57 for entry in read_dir {
58 let entry = entry.unwrap();
59 let path = entry.path();
60
61 if path.is_dir() {
62 match Self::get_pics(&path) {
63 Ok(p) => p,
64 Err(_) => {
65 return Err(Error::NotListableDirectory(String::from(
66 path.to_str().unwrap(),
67 )))
68 }
69 };
70 } else {
71 let check = path.to_str().unwrap();
72 if check.ends_with(".png") || check.ends_with(".jpg") {
73 result.push(path)
74 }
75 }
76 }
77 }
78
79 Ok(result)
80 }
81
82 pub fn random(&self, path: Option<PathBuf>) {
83 let mut rng = thread_rng();
84 let mut location = PathBuf::new();
85
86 if let Some(c) = &self.config {
87 location = match PathBuf::from_str(&c.path) {
88 Ok(p) => p,
89 Err(e) => {
90 eprintln!("Can't parse the path: {}", e);
91 exit(1);
92 }
93 }
94 }
95
96 if path.is_some() {
97 location = path.unwrap()
98 }
99
100 location = self.absolute(location.clone());
101
102 if location.to_str().unwrap().is_empty() {
103 eprintln!(
104 "Seems like we couldn't find config either you didn't pass path to assets folder..."
105 );
106 exit(1);
107 }
108
109 let mut pics = showroom!(Self::get_pics(&location));
110
111 pics.shuffle(&mut rng);
112
113 let first = match pics.first() {
114 Some(p) => p,
115 None => {
116 eprintln!("Seems like there were no pictures!");
117 exit(1)
118 }
119 };
120
121 self.set(first.to_owned())
122 }
123
124 pub async fn install(&mut self, url: Option<String>) -> Result<(), Error> {
125 let mut target = String::new();
126 let source = Source::new(None);
127
128 match url {
133 Some(l) => target.push_str(&l),
134 None => {
135 let mut versions = source.get_latest_version().await.unwrap();
136 versions = format!(
137 "https://github.com/akumarujon/wall-rs-mirror/releases/download/{}/assets.zip",
138 versions
139 );
140
141 match self.config.as_mut() {
142 Some(c) => c.set_version(versions.clone()),
143 None => (),
144 };
145
146 target.push_str(&versions)
147 }
148 };
149
150 const FILENAME: &str = "assets.zip";
151
152 source
153 .download_file(target, FILENAME.to_string())
154 .await
155 .unwrap();
156
157 source.extract_file(FILENAME).unwrap();
158
159 Ok(())
160 }
161
162 pub fn exit(&self) {
163 self.config.as_ref().unwrap().write("").unwrap()
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use crate::config::Config;
170 use crate::wall::Wall;
171
172 #[test]
173 fn test_random() {
174 let config = match Config::from_local_conf() {
175 Ok(c) => Some(c),
176 Err(_) => None,
177 };
178 let wall = Wall::new(config);
179
180 wall.random(None);
181 }
182}