diff --git a/src/gog.rs b/src/gog.rs index d3c3b5a..5dc69b0 100644 --- a/src/gog.rs +++ b/src/gog.rs @@ -13,7 +13,12 @@ use configfiles::{ConfigFiles, ConfigError}; use http::{Http, HttpError}; use models; -use models::{Token, Content, ContentInfo, DataInfo, ExtraInfo, Data}; +use models::content::Content; +use models::contentinfo::ContentInfo; +use models::datainfo::DataInfo; +use models::extrainfo::ExtraInfo; +use models::data::Data; +use models::token::Token; use serde_json; use serde_json::Value; use std::collections::HashMap; diff --git a/src/main.rs b/src/main.rs index 83dc251..0c0bcd9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ use configfiles::ConfigFiles; use clap::{Arg, App}; use gog::Gog; use http::Http; -use models::Config; +use models::config::Config; fn main() { env_logger::init().unwrap(); diff --git a/src/models.rs b/src/models.rs deleted file mode 100644 index ba03472..0000000 --- a/src/models.rs +++ /dev/null @@ -1,197 +0,0 @@ -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; -use serde::{Deserialize, Deserializer}; -use regex::Regex; - -#[derive(Serialize, Deserialize)] -pub struct Token { - pub access_token: String, - pub expires_in: u16, - pub token_type: String, - pub scope: String, - pub session_id: String, - pub refresh_token: String, - pub user_id: String, - #[serde(default = "timestamp")] - pub timestamp: i64, -} - -impl Token { - pub fn is_expired(&self) -> bool { - let now = UTC::now().timestamp(); - - now > self.timestamp + self.expires_in as i64 - } -} - -fn timestamp() -> i64 { - UTC::now().timestamp() -} - -fn default_list() -> Vec { - Vec::new() -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Config { - #[serde(default)] - pub game_storage: String, - #[serde(default)] - pub movie_storage: String, - #[serde(default = "default_list")] - pub os_filters: Vec, - #[serde(default = "default_list")] - pub language_filters: Vec, - #[serde(default = "default_list")] - pub resolution_filters: Vec, - #[serde(default)] - pub skip_movies: bool, - #[serde(default)] - pub skip_games: bool, -} - -impl Config { - pub fn new() -> Config { - Config { - game_storage: String::from("."), - movie_storage: String::from("."), - os_filters: Vec::new(), - language_filters: Vec::new(), - resolution_filters: Vec::new(), - skip_movies: false, - skip_games: false, - } - } -} - -#[derive(Hash)] -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Content { - #[serde(skip_deserializing)] - pub id: u64, - #[serde(deserialize_with = "normalize_title")] - pub title: String, - #[serde(skip_deserializing)] - #[serde(rename(deserialize = "cdKey"))] - pub cd_keys: BTreeMap, - #[serde(skip_deserializing)] - pub is_movie: bool, - #[serde(skip_deserializing)] - pub data: Vec, - pub extras: Vec, -} - -impl fmt::Display for Content { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({})", self.title) - } -} - -fn normalize_title(deserializer: D) -> Result - where D: Deserializer -{ - let raw_title = String::deserialize(deserializer)?.replace(":", " - "); - - let regex_normalize = Regex::new(r"[^'^\w^\s^-]+").unwrap(); - let regex_whitespace = Regex::new(r"\s\s+").unwrap(); - - let title_normalized = regex_normalize - .replace_all(raw_title.as_str(), "") - .to_string(); - - let title_whitespace = regex_whitespace - .replace_all(title_normalized.as_str(), " ") - .to_string(); - - Ok(title_whitespace) -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ContentInfo { - #[serde(skip_deserializing)] - pub id: u64, - pub hash: u64, - pub title: String, - pub cd_keys: BTreeMap, - pub data: HashMap, - pub extras: HashMap, -} - -impl ContentInfo { - pub fn new() -> ContentInfo { - ContentInfo { - id: 0, - hash: 0, - title: String::new(), - cd_keys: BTreeMap::new(), - data: HashMap::new(), - extras: HashMap::new(), - } - } -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct DataInfo { - pub hash: u64, - pub filename: String, - pub language: String, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ExtraInfo { - pub hash: u64, - pub filename: String, - pub name: String, -} - -#[derive(Hash)] -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Data { - pub manual_url: String, - pub version: String, - pub os: String, - pub language: String, -} - -impl fmt::Display for Data { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "({}, {}, {}, {})", - self.manual_url, - self.version, - self.os, - self.language) - } -} - -#[derive(Hash)] -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Extra { - pub manual_url: String, - pub name: String, -} - -impl fmt::Display for Extra { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({}, {})", self.manual_url, self.name) - } -} - -pub fn get_hash(obj: &T) -> u64 - where T: Hash -{ - let mut s = DefaultHasher::new(); - obj.hash(&mut s); - s.finish() -} diff --git a/src/models/config.rs b/src/models/config.rs new file mode 100644 index 0000000..d2bf627 --- /dev/null +++ b/src/models/config.rs @@ -0,0 +1,36 @@ +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Config { + #[serde(default)] + pub game_storage: String, + #[serde(default)] + pub movie_storage: String, + #[serde(default = "default_list")] + pub os_filters: Vec, + #[serde(default = "default_list")] + pub language_filters: Vec, + #[serde(default = "default_list")] + pub resolution_filters: Vec, + #[serde(default)] + pub skip_movies: bool, + #[serde(default)] + pub skip_games: bool, +} + +impl Config { + pub fn new() -> Config { + Config { + game_storage: String::from("."), + movie_storage: String::from("."), + os_filters: Vec::new(), + language_filters: Vec::new(), + resolution_filters: Vec::new(), + skip_movies: false, + skip_games: false, + } + } +} + +fn default_list() -> Vec { + Vec::new() +} diff --git a/src/models/content.rs b/src/models/content.rs new file mode 100644 index 0000000..a311e21 --- /dev/null +++ b/src/models/content.rs @@ -0,0 +1,49 @@ +use models::data::Data; +use models::extra::Extra; +use regex::Regex; +use serde::{Deserialize, Deserializer}; +use std::collections::BTreeMap; +use std::fmt; + +#[derive(Hash)] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Content { + #[serde(skip_deserializing)] + pub id: u64, + #[serde(deserialize_with = "normalize_title")] + pub title: String, + #[serde(skip_deserializing)] + #[serde(rename(deserialize = "cdKey"))] + pub cd_keys: BTreeMap, + #[serde(skip_deserializing)] + pub is_movie: bool, + #[serde(skip_deserializing)] + pub data: Vec, + pub extras: Vec, +} + +impl fmt::Display for Content { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({})", self.title) + } +} + +fn normalize_title(deserializer: D) -> Result + where D: Deserializer +{ + let raw_title = String::deserialize(deserializer)?.replace(":", " - "); + + let regex_normalize = Regex::new(r"[^'^\w^\s^-]+").unwrap(); + let regex_whitespace = Regex::new(r"\s\s+").unwrap(); + + let title_normalized = regex_normalize + .replace_all(raw_title.as_str(), "") + .to_string(); + + let title_whitespace = regex_whitespace + .replace_all(title_normalized.as_str(), " ") + .to_string(); + + Ok(title_whitespace) +} diff --git a/src/models/contentinfo.rs b/src/models/contentinfo.rs new file mode 100644 index 0000000..179f248 --- /dev/null +++ b/src/models/contentinfo.rs @@ -0,0 +1,29 @@ +use models::datainfo::DataInfo; +use models::extrainfo::ExtraInfo; +use std::collections::BTreeMap; +use std::collections::HashMap; + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ContentInfo { + #[serde(skip_deserializing)] + pub id: u64, + pub hash: u64, + pub title: String, + pub cd_keys: BTreeMap, + pub data: HashMap, + pub extras: HashMap, +} + +impl ContentInfo { + pub fn new() -> ContentInfo { + ContentInfo { + id: 0, + hash: 0, + title: String::new(), + cd_keys: BTreeMap::new(), + data: HashMap::new(), + extras: HashMap::new(), + } + } +} diff --git a/src/models/data.rs b/src/models/data.rs new file mode 100644 index 0000000..84bc708 --- /dev/null +++ b/src/models/data.rs @@ -0,0 +1,22 @@ +use std::fmt; + +#[derive(Hash)] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Data { + pub manual_url: String, + pub version: String, + pub os: String, + pub language: String, +} + +impl fmt::Display for Data { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, + "({}, {}, {}, {})", + self.manual_url, + self.version, + self.os, + self.language) + } +} diff --git a/src/models/datainfo.rs b/src/models/datainfo.rs new file mode 100644 index 0000000..4bc3d7b --- /dev/null +++ b/src/models/datainfo.rs @@ -0,0 +1,7 @@ +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct DataInfo { + pub hash: u64, + pub filename: String, + pub language: String, +} diff --git a/src/models/extra.rs b/src/models/extra.rs new file mode 100644 index 0000000..eac4d31 --- /dev/null +++ b/src/models/extra.rs @@ -0,0 +1,15 @@ +use std::fmt; + +#[derive(Hash)] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Extra { + pub manual_url: String, + pub name: String, +} + +impl fmt::Display for Extra { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({}, {})", self.manual_url, self.name) + } +} diff --git a/src/models/extrainfo.rs b/src/models/extrainfo.rs new file mode 100644 index 0000000..c9e2f93 --- /dev/null +++ b/src/models/extrainfo.rs @@ -0,0 +1,7 @@ +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExtraInfo { + pub hash: u64, + pub filename: String, + pub name: String, +} diff --git a/src/models/mod.rs b/src/models/mod.rs new file mode 100644 index 0000000..aa71619 --- /dev/null +++ b/src/models/mod.rs @@ -0,0 +1,19 @@ +use std::hash::{Hash, Hasher}; +use std::collections::hash_map::DefaultHasher; + +pub mod config; +pub mod content; +pub mod contentinfo; +pub mod data; +pub mod datainfo; +pub mod extra; +pub mod extrainfo; +pub mod token; + +pub fn get_hash(obj: &T) -> u64 + where T: Hash +{ + let mut s = DefaultHasher::new(); + obj.hash(&mut s); + s.finish() +} diff --git a/src/models/token.rs b/src/models/token.rs new file mode 100644 index 0000000..7bdecae --- /dev/null +++ b/src/models/token.rs @@ -0,0 +1,26 @@ +use chrono::UTC; + +#[derive(Serialize, Deserialize)] +pub struct Token { + pub access_token: String, + pub expires_in: u16, + pub token_type: String, + pub scope: String, + pub session_id: String, + pub refresh_token: String, + pub user_id: String, + #[serde(default = "timestamp")] + pub timestamp: i64, +} + +impl Token { + pub fn is_expired(&self) -> bool { + let now = UTC::now().timestamp(); + + now > self.timestamp + self.expires_in as i64 + } +} + +fn timestamp() -> i64 { + UTC::now().timestamp() +}