initial commit
This commit is contained in:
141
src/main.rs
Normal file
141
src/main.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
use std::{
|
||||
env::args,
|
||||
ffi::OsStr,
|
||||
fs::{ read, read_dir },
|
||||
path::{ Path, PathBuf },
|
||||
process::exit,
|
||||
};
|
||||
|
||||
use arg::Args;
|
||||
use nanorand::{ WyRand, Rng };
|
||||
|
||||
const F_PATH: &str = "/usr/share/fortune";
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
struct Arguments {
|
||||
_argv0: String,
|
||||
|
||||
#[arg(short = "c",)]
|
||||
c: bool,
|
||||
|
||||
#[arg(short = "f")]
|
||||
f: bool,
|
||||
|
||||
cookies: Vec<String>,
|
||||
}
|
||||
|
||||
fn get_cookies(cookies: Option<Vec<String>>) -> Option<Vec<PathBuf>> {
|
||||
let list = match read_dir(Path::new(F_PATH)) {
|
||||
Ok(path) => path,
|
||||
Err(_) => return None,
|
||||
};
|
||||
|
||||
let mut out = list.map(|x| { x.unwrap().path() }).collect::<Vec<PathBuf>>();
|
||||
|
||||
match cookies {
|
||||
Some(cookies) => {
|
||||
out.clear();
|
||||
for cookie in cookies.iter() {
|
||||
out.push(PathBuf::from(format!("{}/{}", F_PATH, cookie)));
|
||||
}
|
||||
},
|
||||
None => {},
|
||||
};
|
||||
|
||||
out.retain(|x| {
|
||||
let ft = match x.metadata() {
|
||||
Ok(file) => file.is_file(),
|
||||
Err(_) => false,
|
||||
};
|
||||
|
||||
x.extension() != Some(OsStr::new("dat")) && ft
|
||||
});
|
||||
|
||||
Some(out)
|
||||
}
|
||||
|
||||
fn tell_fortune(fortunes: String) -> String {
|
||||
let parsed = fortunes
|
||||
.split('%')
|
||||
.collect::<Vec<&str>>();
|
||||
|
||||
let mut rnd = WyRand::new();
|
||||
let fortune = parsed
|
||||
.get(rnd.generate_range(0_usize..=parsed.len()))
|
||||
.unwrap()
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
fortune
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let argv = args().collect::<Vec<String>>();
|
||||
|
||||
let opts = match Arguments::from_args(
|
||||
argv.clone().iter().map(|x| x.as_str())
|
||||
) {
|
||||
Ok(args) => args,
|
||||
Err(_) => {
|
||||
eprintln!("Usage: {} (-cf)", argv[0]);
|
||||
exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
let selections: Option<Vec<String>>;
|
||||
|
||||
if opts.cookies.is_empty() { selections = None; }
|
||||
else { selections = Some(opts.cookies); }
|
||||
|
||||
let cookies = match get_cookies(selections) {
|
||||
Some(fortunes) => fortunes,
|
||||
None => {
|
||||
eprintln!("{}: No fortune cookies installed.", argv[0]);
|
||||
exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
if opts.f {
|
||||
for file in &cookies {
|
||||
println!("{}", file.file_name().unwrap().to_str().unwrap());
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
let mut rnd = WyRand::new();
|
||||
let cookie = &cookies[
|
||||
rnd.generate_range(0_usize..cookies.len())
|
||||
];
|
||||
|
||||
if opts.c { println!("{:?}\n%", cookie.as_os_str()); }
|
||||
|
||||
let fortune = match read(cookie) {
|
||||
Ok(bytes) => bytes,
|
||||
Err(err) => {
|
||||
eprintln!("{}: {}", argv[0], err);
|
||||
exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
if let Ok(fortune_text) = String::from_utf8(fortune) {
|
||||
println!("{}", tell_fortune(fortune_text));
|
||||
} else { exit(1) }
|
||||
}
|
||||
Reference in New Issue
Block a user