Compare commits

...

2 Commits

Author SHA1 Message Date
Alie 8f2492267a fmt 2023-07-11 09:02:05 +02:00
Alie b1bb5e7961 Merge tag 'v0.2.0' into develop
v0.2.0
2023-07-09 21:21:50 +02:00
3 changed files with 108 additions and 109 deletions

2
Cargo.lock generated
View File

@ -25,7 +25,7 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "bitch"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"futures",
"gelbooru-api",

View File

@ -11,8 +11,7 @@ Tool for curating booru image bots
- [x] CSV structure (Multiple files of just one line, and i refuse to not say its still CSV)
- [x] Read
- [x] Write
## Config file
### Hardcoded for now
## Config file
- [x] Tags
- [x] Keybinds
- [x] DB config (CSV for now)

View File

@ -2,8 +2,8 @@ use gelbooru_api::{posts, Client};
use serde::Deserialize;
use std::collections::HashSet;
use std::{
io::{BufRead, Write},
process::Command,
io::{BufRead, Write},
process::Command,
};
use toml;
@ -11,144 +11,144 @@ const CONFIG: &str = "./config.toml";
#[derive(Deserialize)]
struct Config {
keybinds: Keybinds,
search: Search,
storage: Storage,
keybinds: Keybinds,
search: Search,
storage: Storage,
}
#[derive(Deserialize)]
struct Keybinds {
quit: char,
delete: char,
accept: char,
quit: char,
delete: char,
accept: char,
}
#[derive(Deserialize)]
struct Search {
tags: Vec<String>,
tags: Vec<String>,
}
#[derive(Deserialize)]
struct Storage {
pending: String,
rejected: String,
verified: String,
pending: String,
rejected: String,
verified: String,
}
#[tokio::main]
async fn main() {
let config: Config = parse_config(CONFIG);
let mut arg = std::env::args().skip(1);
match &arg
.next()
.expect("Not enough arguments, please use -f or -v")[..]
{
"-f" => fetch_mode(&config.storage, &config.search).await,
"-v" => verify_mode(&config.keybinds, &config.storage),
_ => {}
}
let config: Config = parse_config(CONFIG);
let mut arg = std::env::args().skip(1);
match &arg
.next()
.expect("Not enough arguments, please use -f or -v")[..]
{
"-f" => fetch_mode(&config.storage, &config.search).await,
"-v" => verify_mode(&config.keybinds, &config.storage),
_ => {}
}
}
/// Parses the given filename to a config struct
fn parse_config(filename: &str) -> Config {
let toml_file = std::fs::read_to_string(filename)
.expect("No config file, consider geting the original one and moodifing it");
toml::from_str(&toml_file).expect("Malformed config file, check the original one for reference")
let toml_file = std::fs::read_to_string(filename)
.expect("No config file, consider geting the original one and moodifing it");
toml::from_str(&toml_file).expect("Malformed config file, check the original one for reference")
}
async fn fetch_mode(storage: &Storage, search: &Search) {
let client = Client::public();
let posts = posts().random(true).tags(&search.tags).send(&client);
let client = Client::public();
let posts = posts().random(true).tags(&search.tags).send(&client);
let pending_set = std::fs::read_to_string(&storage.pending).expect("No pending file");
let rejected_set = std::fs::read_to_string(&storage.rejected).expect("No rejected file");
let verified_set = std::fs::read_to_string(&storage.verified).expect("No verified file");
let pending_set = std::fs::read_to_string(&storage.pending).expect("No pending file");
let rejected_set = std::fs::read_to_string(&storage.rejected).expect("No rejected file");
let verified_set = std::fs::read_to_string(&storage.verified).expect("No verified file");
let image_set = pending_set
.lines()
.chain(rejected_set.lines())
.chain(verified_set.lines())
.collect::<HashSet<_>>();
let image_set = pending_set
.lines()
.chain(rejected_set.lines())
.chain(verified_set.lines())
.collect::<HashSet<_>>();
let posts = posts.await.unwrap();
let mut file = std::fs::OpenOptions::new()
.write(true)
.append(true) // This is needed to append to file
.open(&storage.pending)
.unwrap();
let posts = posts.await.unwrap();
let mut file = std::fs::OpenOptions::new()
.write(true)
.append(true) // This is needed to append to file
.open(&storage.pending)
.unwrap();
for post in posts.posts {
let imgurl = post.image_url();
if !image_set.contains(imgurl) {
write!(file, "{}\n", imgurl).unwrap();
}
for post in posts.posts {
let imgurl = post.image_url();
if !image_set.contains(imgurl) {
write!(file, "{}\n", imgurl).unwrap();
}
}
}
fn verify_mode(keybinds: &Keybinds, storage: &Storage) {
let file: String = std::fs::read(&storage.pending)
.expect("File not found")
.iter()
.map(|c| *c as char)
.collect();
let mut file = file.lines();
while let Some(image_uri) = file.next() {
//Open image
Command::new("xdg-open")
.arg(image_uri)
.spawn()
.expect("open command failed to start");
//Print Legend
println!(
"{} to quit; {} to delete; {} to accept",
&keybinds.quit, &keybinds.delete, &keybinds.accept,
);
// Wait for input
if input_parse(storage, keybinds, image_uri) {
std::fs::write(
&storage.pending,
format!(
"{}\n{}",
image_uri,
file.map(|s| s.to_owned() + "\n").collect::<String>()
),
)
.unwrap();
return;
}
let file: String = std::fs::read(&storage.pending)
.expect("File not found")
.iter()
.map(|c| *c as char)
.collect();
let mut file = file.lines();
while let Some(image_uri) = file.next() {
//Open image
Command::new("xdg-open")
.arg(image_uri)
.spawn()
.expect("open command failed to start");
//Print Legend
println!(
"{} to quit; {} to delete; {} to accept",
&keybinds.quit, &keybinds.delete, &keybinds.accept
);
// Wait for input
if input_parse(storage, keybinds, image_uri) {
std::fs::write(
&storage.pending,
format!(
"{}\n{}",
image_uri,
file.map(|s| s.to_owned() + "\n").collect::<String>()
),
)
.unwrap();
return;
}
std::fs::write(&storage.pending, "").unwrap();
}
std::fs::write(&storage.pending, "").unwrap();
}
fn input_parse(storage: &Storage, keybinds: &Keybinds, image_uri: &str) -> bool {
loop {
let key = std::io::stdin()
.lock()
.lines()
.next()
.unwrap()
.unwrap()
.chars()
.next()
.unwrap_or('_');
if &key == &keybinds.quit {
return true;
} else if &key == &keybinds.accept {
let mut file = std::fs::OpenOptions::new()
.write(true)
.append(true) // This is needed to append to file
.open(&storage.verified)
.unwrap();
write!(file, "{}\n", image_uri).unwrap();
return false;
} else if &key == &keybinds.delete {
let mut file = std::fs::OpenOptions::new()
.write(true)
.append(true) // This is needed to append to file
.open(&storage.rejected)
.unwrap();
write!(file, "{}\n", image_uri).unwrap();
return false;
}
loop {
let key = std::io::stdin()
.lock()
.lines()
.next()
.unwrap()
.unwrap()
.chars()
.next()
.unwrap_or('_');
if &key == &keybinds.quit {
return true;
} else if &key == &keybinds.accept {
let mut file = std::fs::OpenOptions::new()
.write(true)
.append(true) // This is needed to append to file
.open(&storage.verified)
.unwrap();
write!(file, "{}\n", image_uri).unwrap();
return false;
} else if &key == &keybinds.delete {
let mut file = std::fs::OpenOptions::new()
.write(true)
.append(true) // This is needed to append to file
.open(&storage.rejected)
.unwrap();
write!(file, "{}\n", image_uri).unwrap();
return false;
}
}
}