Browse Source

Added config and download function

master
Drew Short 4 years ago
parent
commit
2b7fcbcfc3
  1. 173
      Cargo.lock
  2. 4
      Cargo.toml
  3. 70
      src/config.rs
  4. 116
      src/main.rs

173
Cargo.lock

@ -6,9 +6,11 @@ version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"clap", "clap",
"curl",
"lazy_static", "lazy_static",
"serde", "serde",
"serde_json", "serde_json",
"url",
] ]
[[package]] [[package]]
@ -43,6 +45,18 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "cc"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.11" version = "0.4.11"
@ -70,6 +84,36 @@ dependencies = [
"vec_map", "vec_map",
] ]
[[package]]
name = "curl"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "762e34611d2d5233a506a79072be944fddd057db2f18e04c0d6fa79e3fd466fd"
dependencies = [
"curl-sys",
"libc",
"openssl-probe",
"openssl-sys",
"schannel",
"socket2",
"winapi",
]
[[package]]
name = "curl-sys"
version = "0.4.31+curl-7.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcd62757cc4f5ab9404bc6ca9f0ae447e729a1403948ce5106bd588ceac6a3b0"
dependencies = [
"cc",
"libc",
"libz-sys",
"openssl-sys",
"pkg-config",
"vcpkg",
"winapi",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.13" version = "0.1.13"
@ -79,6 +123,17 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "idna"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "0.4.5" version = "0.4.5"
@ -97,6 +152,24 @@ version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
[[package]]
name = "libz-sys"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.42" version = "0.1.42"
@ -116,6 +189,37 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "openssl-probe"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
[[package]]
name = "openssl-sys"
version = "0.9.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7410fef80af8ac071d4f63755c0ab89ac3df0fd1ea91f1d1f37cf5cec4395990"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.17" version = "1.0.17"
@ -134,12 +238,28 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.4" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
[[package]]
name = "schannel"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
dependencies = [
"lazy_static",
"winapi",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.110" version = "1.0.110"
@ -171,6 +291,24 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "smallvec"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
[[package]]
name = "socket2"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"winapi",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.8.0"
@ -207,6 +345,24 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "unicode-bidi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
dependencies = [
"matches",
]
[[package]]
name = "unicode-normalization"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
dependencies = [
"smallvec",
]
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.7" version = "0.1.7"
@ -219,6 +375,23 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "url"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
dependencies = [
"idna",
"matches",
"percent-encoding",
]
[[package]]
name = "vcpkg"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
[[package]] [[package]]
name = "vec_map" name = "vec_map"
version = "0.8.2" version = "0.8.2"

4
Cargo.toml

@ -13,7 +13,9 @@ incremental = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
chrono = { version = "0.4.11", features = ["serde"] } chrono = { version = "0.4.11", features = ["serde"] }
curl = "0.4.29"
clap = "2.33.1" clap = "2.33.1"
lazy_static = "1.4.0" lazy_static = "1.4.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_json = "1.0"
url = "2.1.1"

70
src/config.rs

@ -0,0 +1,70 @@
use std::error::Error;
use std::ffi::OsString;
use std::fs::File;
use std::io::{BufReader, BufWriter};
use std::path::Path;
use std::process::exit;
use serde::ser::Error as SerdeError;
use serde::{Deserialize, Serialize};
use serde_json::{from_reader, to_writer_pretty};
#[derive(Serialize, Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct Config {
pub save_directory: Option<String>,
pub downloaded: Vec<String>,
}
pub struct ConfigManager {
config_path: OsString,
pub config: Config,
}
fn read_config<P: AsRef<Path>>(path: P) -> Result<Config, Box<dyn Error>> {
let file = File::open(path)?;
let reader = BufReader::new(file);
let result: Config = from_reader(reader)?;
Ok(result)
}
fn save_config<P: AsRef<Path>>(path: P, config: &Config) -> serde_json::Result<()> {
match File::create(path) {
Err(e) => Err(serde_json::Error::custom(e)),
Ok(file) => to_writer_pretty(file, config),
}
}
impl ConfigManager {
pub fn new(config_path: &Path) -> ConfigManager {
let mut config = ConfigManager {
config_path: OsString::from(config_path.as_os_str()),
config: Config {
save_directory: None,
downloaded: vec![],
},
};
config.load();
config
}
fn load(&mut self) {
match read_config(&self.config_path) {
Err(e) => {
println!("Failed to read config file {:#?}", &self.config_path);
exit(1);
}
Ok(config) => self.config = config,
}
}
pub fn save(&mut self, config: Config) {
match save_config(&self.config_path, &config) {
Err(e) => {
println!("Unexpected error saving config: {}", e);
}
Ok(_) => (),
}
self.config = config;
}
}

116
src/main.rs

@ -1,17 +1,24 @@
use clap::{App, Arg};
use lazy_static::lazy_static;
use serde_json::from_reader;
use std::env;
use std::error::Error; use std::error::Error;
use std::fs::File; use std::fs::File;
use std::io::BufReader;
use std::io::{BufReader, Write};
use std::path::Path; use std::path::Path;
use std::process::exit; use std::process::exit;
use clap::{App, Arg};
use curl::easy::{Easy, WriteError};
use serde_json::from_reader;
use url::Url;
use crate::config::{Config, ConfigManager};
use lazy_static::lazy_static;
const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION"); const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
lazy_static! { lazy_static! {
static ref COMMANDS: Vec<&'static str> = vec!["print", "searches", "favorites"];
static ref COMMANDS: Vec<&'static str> = vec!["download", "favorites", "print", "searches"];
} }
mod config;
mod model; mod model;
fn read_animeboxes_backup<P: AsRef<Path>>( fn read_animeboxes_backup<P: AsRef<Path>>(
@ -23,20 +30,78 @@ fn read_animeboxes_backup<P: AsRef<Path>>(
Ok(result) Ok(result)
} }
fn searches_command(backup: model::anime_boxes::Backup) {
let mut searches: Vec<String> = backup
.search_history
fn write_to_file(data: &[u8], path: &Path) -> std::io::Result<()> {
let mut file = File::create(path)?;
file.write_all(data)?;
Ok(())
}
fn download_command(backup: model::anime_boxes::Backup, mut config: config::ConfigManager) {
let favorites: Vec<String> = backup
.favorites
.iter() .iter()
.map(|s| String::from(&s.search_text))
.map(|f| String::from(&f.file.url))
.collect(); .collect();
searches.sort();
for search in searches {
println!("{}", search);
let mut favorites_to_download: Vec<String> = Vec::new();
for favorite in favorites {
if !config.config.downloaded.contains(&favorite) {
favorites_to_download.push(favorite);
}
}
let mut favorites_downloaded = Vec::new();
for favorite in favorites_to_download {
let mut easy = Easy::new();
let favorite_url = Url::parse(&favorite);
match favorite_url {
Err(e) => {
println!("Error downloading {}. Not a valid URL", favorite);
continue;
}
Ok(url) => {
let target_path = env::current_dir().unwrap().join(
config
.config
.save_directory
.as_ref()
.unwrap_or(&String::from("tmp")),
);
easy.url(url.as_str());
match easy.write_function(move |data| match write_to_file(data, &target_path) {
Err(e) => Err(WriteError::Pause),
Ok(d) => Ok(data.len()),
}) {
Err(e) => {
println!("Error downloading {}", favorite);
}
Ok(_) => favorites_downloaded.push(String::from(favorite)),
}
easy.perform().unwrap();
}
}
}
let favorites_downloaded_count = favorites_downloaded.len();
let mut all_downloaded: Vec<String> = Vec::new();
for downloaded in &config.config.downloaded {
all_downloaded.push(String::from(downloaded));
}
for downloaded in favorites_downloaded {
println!("{}", downloaded);
all_downloaded.push(downloaded);
} }
let all_downloaded_count = all_downloaded.len();
let new_config = Config {
save_directory: Some(String::from(config.config.save_directory.as_ref().unwrap())),
downloaded: all_downloaded,
};
config.save(new_config);
println!(
"Downloaded {:#?}/{:#?} images",
favorites_downloaded_count, all_downloaded_count
)
} }
fn favorites_command(backup: model::anime_boxes::Backup) { fn favorites_command(backup: model::anime_boxes::Backup) {
let mut favorites: Vec<String> = backup
let favorites: Vec<String> = backup
.favorites .favorites
.iter() .iter()
.map(|f| String::from(&f.file.url)) .map(|f| String::from(&f.file.url))
@ -46,6 +111,18 @@ fn favorites_command(backup: model::anime_boxes::Backup) {
} }
} }
fn searches_command(backup: model::anime_boxes::Backup) {
let mut searches: Vec<String> = backup
.search_history
.iter()
.map(|s| String::from(&s.search_text))
.collect();
searches.sort();
for search in searches {
println!("{}", search);
}
}
fn main() { fn main() {
let matches = App::new("AnimeBoxes Sync") let matches = App::new("AnimeBoxes Sync")
.version(VERSION.unwrap_or("UNKNOWN")) .version(VERSION.unwrap_or("UNKNOWN"))
@ -73,19 +150,18 @@ fn main() {
) )
.get_matches(); .get_matches();
let config = matches.value_of("config").unwrap_or("abs-default.conf");
let config = matches.value_of("config").unwrap_or("config.json");
let config_path = env::current_dir().unwrap().join(config);
let mut config_manager = ConfigManager::new(config_path.as_path());
let path = matches.value_of("INPUT").unwrap(); let path = matches.value_of("INPUT").unwrap();
let result = read_animeboxes_backup(path).unwrap(); let result = read_animeboxes_backup(path).unwrap();
let command = matches.value_of("COMMAND").unwrap(); let command = matches.value_of("COMMAND").unwrap();
match command { match command {
"favorites" => {
favorites_command(result);
}
"download" => download_command(result, config_manager),
"favorites" => favorites_command(result),
"print" => println!("{:#?}", result), "print" => println!("{:#?}", result),
"searches" => {
searches_command(result);
}
"searches" => searches_command(result),
_ => { _ => {
println!("{} is unrecognized", command); println!("{} is unrecognized", command);
exit(1) exit(1)

Loading…
Cancel
Save