move content deserialization in module file
This commit is contained in:
parent
2f85d2459f
commit
865f398013
157
src/gog.rs
157
src/gog.rs
@ -17,12 +17,10 @@ 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;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
@ -352,44 +350,6 @@ impl<'a> Gog<'a> {
|
||||
return Ok(content_ids);
|
||||
}
|
||||
|
||||
fn parse_cd_keys(&self, content_title: &str, raw_cd_keys: &str) -> BTreeMap<String, String> {
|
||||
let mut cd_keys = BTreeMap::new();
|
||||
let mut raw_cd_keys_fix = raw_cd_keys.to_owned();
|
||||
|
||||
if raw_cd_keys_fix.contains("<span>") {
|
||||
raw_cd_keys_fix = raw_cd_keys_fix
|
||||
.replace("</span><span>", ":")
|
||||
.replace("<span>", "")
|
||||
.replace("</span>", "");
|
||||
}
|
||||
|
||||
raw_cd_keys_fix = raw_cd_keys_fix.replace("<br>", ":").replace("::", ":");
|
||||
|
||||
if raw_cd_keys_fix.contains(":") {
|
||||
let splitted_keys = raw_cd_keys_fix.split(":");
|
||||
|
||||
let mut key_names: Vec<String> = Vec::new();
|
||||
let mut key_values: Vec<String> = Vec::new();
|
||||
|
||||
for (token_index, token) in splitted_keys.enumerate() {
|
||||
if token_index % 2 == 0 {
|
||||
key_names.push(token.to_owned());
|
||||
} 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 api_request_ensure_token(&mut self, response: &str) -> Result<bool, GogError> {
|
||||
let response_json: Value = match serde_json::from_str(response) {
|
||||
Ok(value) => value,
|
||||
@ -436,118 +396,11 @@ impl<'a> Gog<'a> {
|
||||
|
||||
let response = self.api_request_get(content_uri.as_str())?;
|
||||
|
||||
let content_raw: Value = serde_json::from_str(response.as_str())?;
|
||||
debug!("found {:?}", &content_raw);
|
||||
|
||||
let mut content: Content = serde_json::from_str(&response)?;
|
||||
content.id = content_id;
|
||||
|
||||
let downloads = &content_raw["downloads"];
|
||||
|
||||
if content_raw.is_object() &&
|
||||
!content_raw
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.contains_key("forumLink") {
|
||||
return Err(GogError::Error("No forumLink property"));
|
||||
}
|
||||
|
||||
let is_movie = match content_raw["forumLink"].as_str() {
|
||||
Some(value) => value == "https://embed.gog.com/forum/movies",
|
||||
None => false,
|
||||
};
|
||||
|
||||
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 {
|
||||
if !language.is_array() || language.as_array().unwrap().len() < 2 {
|
||||
error!("Skipping a language for {}", content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
let data_language = match language[0].as_str() {
|
||||
Some(value) => value.to_lowercase(),
|
||||
None => String::default(),
|
||||
};
|
||||
|
||||
if data_language.is_empty() {
|
||||
error!("Skipping a language for {}", content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
if !is_movie && !language_filters.is_empty() &&
|
||||
!language_filters.contains(&data_language) {
|
||||
info!("Skipping {} for {}", &data_language, content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
for systems in language[1].as_object() {
|
||||
for system in systems.keys() {
|
||||
if is_movie && !os_filters.is_empty() && !os_filters.contains(system) {
|
||||
info!("Skipping {} {} for {}",
|
||||
&data_language,
|
||||
system,
|
||||
content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
for real_downloads in systems.get(system) {
|
||||
for real_download in real_downloads.as_array() {
|
||||
for download in real_download {
|
||||
if !download.is_object() ||
|
||||
!download.as_object().unwrap().contains_key("manualUrl") ||
|
||||
!download.as_object().unwrap().contains_key("name") {
|
||||
error!("Skipping data for {}", content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
let name: &str = download["name"].as_str().unwrap();
|
||||
|
||||
|
||||
if content.is_movie && !resolution_filters.is_empty() {
|
||||
let mut found_resolution = false;
|
||||
for resolution_filter in resolution_filters {
|
||||
let filter = format!("({})", resolution_filter);
|
||||
if name.ends_with(&filter) {
|
||||
found_resolution = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !found_resolution {
|
||||
info!("Skipping {}: not a suitable resolution.", name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let data = Data {
|
||||
manual_url: String::from(download["manualUrl"]
|
||||
.as_str()
|
||||
.unwrap()),
|
||||
version: String::from(download["version"]
|
||||
.as_str()
|
||||
.unwrap_or("")),
|
||||
os: system.clone(),
|
||||
language: data_language.clone(),
|
||||
};
|
||||
|
||||
content.data.push(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(content)
|
||||
models::content::deserialize(content_id,
|
||||
response.as_str(),
|
||||
os_filters,
|
||||
language_filters,
|
||||
resolution_filters)
|
||||
}
|
||||
|
||||
fn games_uri(&self) -> String {
|
||||
|
@ -1,7 +1,10 @@
|
||||
use gog::GogError;
|
||||
use models::data::Data;
|
||||
use models::extra::Extra;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use serde_json;
|
||||
use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
|
||||
@ -11,7 +14,7 @@ use std::fmt;
|
||||
pub struct Content {
|
||||
#[serde(skip_deserializing)]
|
||||
pub id: u64,
|
||||
#[serde(deserialize_with = "normalize_title")]
|
||||
#[serde(deserialize_with = "deserialize_title")]
|
||||
pub title: String,
|
||||
#[serde(skip_deserializing)]
|
||||
#[serde(rename(deserialize = "cdKey"))]
|
||||
@ -21,6 +24,7 @@ pub struct Content {
|
||||
#[serde(skip_deserializing)]
|
||||
pub data: Vec<Data>,
|
||||
pub extras: Vec<Extra>,
|
||||
pub dlcs: Vec<Content>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Content {
|
||||
@ -29,7 +33,7 @@ impl fmt::Display for Content {
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_title<D>(deserializer: D) -> Result<String, D::Error>
|
||||
fn deserialize_title<D>(deserializer: D) -> Result<String, D::Error>
|
||||
where D: Deserializer
|
||||
{
|
||||
let raw_title = String::deserialize(deserializer)?.replace(":", " - ");
|
||||
@ -47,3 +51,160 @@ fn normalize_title<D>(deserializer: D) -> Result<String, D::Error>
|
||||
|
||||
Ok(title_whitespace)
|
||||
}
|
||||
|
||||
fn deserialize_cd_keys(content_title: &str, raw_cd_keys: &str) -> BTreeMap<String, String> {
|
||||
let mut cd_keys = BTreeMap::new();
|
||||
let mut raw_cd_keys_fix = raw_cd_keys.to_owned();
|
||||
|
||||
if raw_cd_keys_fix.contains("<span>") {
|
||||
raw_cd_keys_fix = raw_cd_keys_fix
|
||||
.replace("</span><span>", ":")
|
||||
.replace("<span>", "")
|
||||
.replace("</span>", "");
|
||||
}
|
||||
|
||||
raw_cd_keys_fix = raw_cd_keys_fix.replace("<br>", ":").replace("::", ":");
|
||||
|
||||
if raw_cd_keys_fix.contains(":") {
|
||||
let splitted_keys = raw_cd_keys_fix.split(":");
|
||||
|
||||
let mut key_names: Vec<String> = Vec::new();
|
||||
let mut key_values: Vec<String> = Vec::new();
|
||||
|
||||
for (token_index, token) in splitted_keys.enumerate() {
|
||||
if token_index % 2 == 0 {
|
||||
key_names.push(token.to_owned());
|
||||
} 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());
|
||||
}
|
||||
|
||||
cd_keys
|
||||
}
|
||||
|
||||
pub fn deserialize(content_id: u64,
|
||||
content_string: &str,
|
||||
os_filters: &Vec<String>,
|
||||
language_filters: &Vec<String>,
|
||||
resolution_filters: &Vec<String>)
|
||||
-> Result<Content, GogError> {
|
||||
let content_raw: Value = serde_json::from_str(content_string)?;
|
||||
debug!("found {:?}", &content_raw);
|
||||
|
||||
let mut content: Content = serde_json::from_str(content_string)?;
|
||||
content.id = content_id;
|
||||
|
||||
let downloads = &content_raw["downloads"];
|
||||
|
||||
if content_raw.is_object() &&
|
||||
!content_raw
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.contains_key("forumLink") {
|
||||
return Err(GogError::Error("No forumLink property"));
|
||||
}
|
||||
|
||||
let is_movie = match content_raw["forumLink"].as_str() {
|
||||
Some(value) => value == "https://embed.gog.com/forum/movies",
|
||||
None => false,
|
||||
};
|
||||
|
||||
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 = deserialize_cd_keys(&content.title, cd_keys_raw);
|
||||
}
|
||||
|
||||
debug!("processing installer fields: {:?}", &downloads);
|
||||
for languages in downloads.as_array() {
|
||||
for language in languages {
|
||||
if !language.is_array() || language.as_array().unwrap().len() < 2 {
|
||||
error!("Skipping a language for {}", content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
let data_language = match language[0].as_str() {
|
||||
Some(value) => value.to_lowercase(),
|
||||
None => String::default(),
|
||||
};
|
||||
|
||||
if data_language.is_empty() {
|
||||
error!("Skipping a language for {}", content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
if !is_movie && !language_filters.is_empty() &&
|
||||
!language_filters.contains(&data_language) {
|
||||
info!("Skipping {} for {}", &data_language, content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
for systems in language[1].as_object() {
|
||||
for system in systems.keys() {
|
||||
if is_movie && !os_filters.is_empty() && !os_filters.contains(system) {
|
||||
info!("Skipping {} {} for {}",
|
||||
&data_language,
|
||||
system,
|
||||
content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
for real_downloads in systems.get(system) {
|
||||
for real_download in real_downloads.as_array() {
|
||||
for download in real_download {
|
||||
if !download.is_object() ||
|
||||
!download.as_object().unwrap().contains_key("manualUrl") ||
|
||||
!download.as_object().unwrap().contains_key("name") {
|
||||
error!("Skipping data for {}", content.title);
|
||||
continue;
|
||||
}
|
||||
|
||||
let name: &str = download["name"].as_str().unwrap();
|
||||
|
||||
|
||||
if content.is_movie && !resolution_filters.is_empty() {
|
||||
let mut found_resolution = false;
|
||||
for resolution_filter in resolution_filters {
|
||||
let filter = format!("({})", resolution_filter);
|
||||
if name.ends_with(&filter) {
|
||||
found_resolution = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !found_resolution {
|
||||
info!("Skipping {}: not a suitable resolution.", name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let data = Data {
|
||||
manual_url: String::from(download["manualUrl"]
|
||||
.as_str()
|
||||
.unwrap()),
|
||||
version:
|
||||
String::from(download["version"].as_str().unwrap_or("")),
|
||||
os: system.clone(),
|
||||
language: data_language.clone(),
|
||||
};
|
||||
|
||||
content.data.push(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(content)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user