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 = [
"chrono",
"clap",
"curl",
"lazy_static",
"serde",
"serde_json",
"url",
]
[[package]]
@ -43,6 +45,18 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "chrono"
version = "0.4.11"
@ -70,6 +84,36 @@ dependencies = [
"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]]
name = "hermit-abi"
version = "0.1.13"
@ -79,6 +123,17 @@ dependencies = [
"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]]
name = "itoa"
version = "0.4.5"
@ -97,6 +152,24 @@ version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "num-integer"
version = "0.1.42"
@ -116,6 +189,37 @@ dependencies = [
"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]]
name = "proc-macro2"
version = "1.0.17"
@ -134,12 +238,28 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]]
name = "ryu"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "serde"
version = "1.0.110"
@ -171,6 +291,24 @@ dependencies = [
"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]]
name = "strsim"
version = "0.8.0"
@ -207,6 +345,24 @@ dependencies = [
"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]]
name = "unicode-width"
version = "0.1.7"
@ -219,6 +375,23 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "vec_map"
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
[dependencies]
chrono = { version = "0.4.11", features = ["serde"] }
curl = "0.4.29"
clap = "2.33.1"
lazy_static = "1.4.0"
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::fs::File;
use std::io::BufReader;
use std::io::{BufReader, Write};
use std::path::Path;
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");
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;
fn read_animeboxes_backup<P: AsRef<Path>>(
@ -23,20 +30,78 @@ fn read_animeboxes_backup<P: AsRef<Path>>(
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()
.map(|s| String::from(&s.search_text))
.map(|f| String::from(&f.file.url))
.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) {
let mut favorites: Vec<String> = backup
let favorites: Vec<String> = backup
.favorites
.iter()
.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() {
let matches = App::new("AnimeBoxes Sync")
.version(VERSION.unwrap_or("UNKNOWN"))
@ -73,19 +150,18 @@ fn main() {
)
.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 result = read_animeboxes_backup(path).unwrap();
let command = matches.value_of("COMMAND").unwrap();
match command {
"favorites" => {
favorites_command(result);
}
"download" => download_command(result, config_manager),
"favorites" => favorites_command(result),
"print" => println!("{:#?}", result),
"searches" => {
searches_command(result);
}
"searches" => searches_command(result),
_ => {
println!("{} is unrecognized", command);
exit(1)

Loading…
Cancel
Save