diff --git a/.vscode/launch.json b/.vscode/launch.json index 2463afa..d909cf0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "name": "Debug", "type": "lldb-mi", "request": "launch", - "target": "./target/debug/gog-backup", + "target": "./target/debug/gog-sync", "cwd": "${workspaceRoot}" } ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 88783e3..d7f5bac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.2.3 (2017-03-23) +- correctly parse serial keys (closes #8) + ## 0.2.2 (2017-03-22) - ability to filter movies by resolution - ability to save movies seperately diff --git a/Cargo.lock b/Cargo.lock index 8d411ef..fe92550 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "gog-sync" version = "0.2.2" dependencies = [ "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.22.0 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -53,7 +53,7 @@ dependencies = [ [[package]] name = "clap" -version = "2.21.2" +version = "2.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -429,7 +429,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" "checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162" "checksum chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "158b0bd7d75cbb6bf9c25967a48a2e9f77da95876b858eadfabaa99cd069de6e" -"checksum clap 2.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "58ad5e8142f3a5eab0c1cba5011aa383e009842936107fe4d94f1a8d380a1aec" +"checksum clap 2.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "875f4f161166a71c4b7bf2c05f46d26c30d8b9052c16a6bdd3171ddf03848cbe" "checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b" "checksum curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d909dc402ae80b6f7b0118c039203436061b9d9a3ca5d2c2546d93e0a61aaa" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" diff --git a/src/gog.rs b/src/gog.rs index f0baebe..b36ea22 100644 --- a/src/gog.rs +++ b/src/gog.rs @@ -17,6 +17,7 @@ use models::{Token, Content, Data, Config}; use serde_json; use serde_json::Value; use std::collections::HashMap; +use std::collections::BTreeMap; use std::fmt; use std::fs; use std::fs::File; @@ -133,7 +134,7 @@ impl<'a> Gog<'a> { let mut config: Config = match configfiles.load("config.json") { Ok(value) => value, Err(_) => { - error!("Configuration error, generating new one..."); + error!("Configuration error, generating new one"); Config { game_storage: String::from(storage_path), @@ -189,10 +190,16 @@ impl<'a> Gog<'a> { fs::create_dir_all(&content_root)?; - if !content.cd_key.is_empty() { - let key_path = Path::new(content_root.as_os_str()).join("key.txt"); + let key_root = content_root.join("keys"); + + if content.cd_keys.len() > 0 { + fs::create_dir_all(&key_root)?; + } + + for (key, value) in content.cd_keys { + let key_path = key_root.join(format!("{}.txt", key)); let mut key_file = File::create(&key_path)?; - key_file.write_all(content.cd_key.as_bytes())? + key_file.write_all(value.as_bytes())? } for data in content.data { @@ -331,6 +338,43 @@ impl<'a> Gog<'a> { return Ok(content_ids); } + fn parse_cd_keys(&self, content_title: &str, raw_cd_keys: &str) -> BTreeMap { + let mut cd_keys = BTreeMap::new(); + let mut raw_cd_keys_fix = raw_cd_keys.to_owned(); + + if raw_cd_keys_fix.contains("") { + raw_cd_keys_fix = raw_cd_keys_fix.replace("", "
") + .replace("", "") + .replace("", ""); + } + + if raw_cd_keys_fix.contains("
") { + let splitted_keys = raw_cd_keys_fix.split("
"); + + let mut key_names: Vec = Vec::new(); + let mut key_values: Vec = Vec::new(); + + for (token_index, token) in splitted_keys.enumerate() { + if token_index % 2 == 0 { + let mut key_name = token.to_owned(); + key_name.truncate(token.len() - 1); + key_names.push(key_name); + } else { + key_values.push(token.trim().to_owned()); + } + } + + for (index, key_name) in key_names.iter().enumerate() { + let key_value = key_values[index].clone(); + cd_keys.insert(key_name.clone(), key_value); + } + } else if !raw_cd_keys_fix.is_empty() { + cd_keys.insert(content_title.to_owned(), raw_cd_keys_fix.trim().to_owned()); + } + + return cd_keys; + } + fn get_content(&mut self, content_id: u64, os_filters: &Vec, @@ -360,6 +404,11 @@ impl<'a> Gog<'a> { content.is_movie = is_movie; + if content_raw.is_object() && content_raw.as_object().unwrap().contains_key("cdKey") { + let cd_keys_raw = content_raw["cdKey"].as_str().unwrap(); + content.cd_keys = self.parse_cd_keys(&content.title, cd_keys_raw); + } + debug!("processing installer fields: {:?}", &downloads); for languages in downloads.as_array() { for language in languages { diff --git a/src/models.rs b/src/models.rs index 2a07f0b..b4e68ca 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,6 +1,7 @@ use chrono::UTC; use std::fmt; use std::hash::{Hash, Hasher}; +use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::hash_map::DefaultHasher; @@ -84,7 +85,9 @@ impl Config { #[serde(rename_all = "camelCase")] pub struct Content { pub title: String, - pub cd_key: String, + #[serde(skip_deserializing)] + #[serde(rename(deserialize = "cdKey"))] + pub cd_keys: BTreeMap, #[serde(skip_deserializing)] pub is_movie: bool, #[serde(skip_deserializing)]