initial movie support
This commit is contained in:
parent
e385a07aac
commit
88827749db
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
[root]
|
[root]
|
||||||
name = "gog-sync"
|
name = "gog-sync"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
use std::fmt;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std;
|
use std;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
@ -20,6 +21,15 @@ pub enum ConfigError {
|
|||||||
SerdeJsonError(serde_json::Error),
|
SerdeJsonError(serde_json::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ConfigError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
ConfigError::IOError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
ConfigError::SerdeJsonError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<std::io::Error> for ConfigError {
|
impl From<std::io::Error> for ConfigError {
|
||||||
fn from(e: std::io::Error) -> Self {
|
fn from(e: std::io::Error) -> Self {
|
||||||
ConfigError::IOError(e)
|
ConfigError::IOError(e)
|
||||||
|
47
src/gog.rs
47
src/gog.rs
@ -17,6 +17,7 @@ use models::{Token, Game, Installer, Config};
|
|||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
@ -33,6 +34,18 @@ pub enum GogError {
|
|||||||
IOError(io::Error),
|
IOError(io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for GogError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
GogError::Error(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
GogError::ConfigError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
GogError::HttpError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
GogError::SerdeError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
GogError::IOError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<ConfigError> for GogError {
|
impl From<ConfigError> for GogError {
|
||||||
fn from(e: ConfigError) -> Self {
|
fn from(e: ConfigError) -> Self {
|
||||||
GogError::ConfigError(e)
|
GogError::ConfigError(e)
|
||||||
@ -109,6 +122,7 @@ impl<'a> Gog<'a> {
|
|||||||
/// Uses a hash to figure out whether something has changed.
|
/// Uses a hash to figure out whether something has changed.
|
||||||
pub fn sync(&mut self,
|
pub fn sync(&mut self,
|
||||||
storage_path: &str,
|
storage_path: &str,
|
||||||
|
storage_path_movies: &str,
|
||||||
os_filters: &Vec<String>,
|
os_filters: &Vec<String>,
|
||||||
language_filters: &Vec<String>)
|
language_filters: &Vec<String>)
|
||||||
-> Result<(), GogError> {
|
-> Result<(), GogError> {
|
||||||
@ -120,6 +134,7 @@ impl<'a> Gog<'a> {
|
|||||||
|
|
||||||
Config {
|
Config {
|
||||||
storage: String::from(storage_path),
|
storage: String::from(storage_path),
|
||||||
|
movie_storage: String::from(storage_path_movies),
|
||||||
games: HashMap::new(),
|
games: HashMap::new(),
|
||||||
installers: HashMap::new(),
|
installers: HashMap::new(),
|
||||||
extras: HashMap::new(),
|
extras: HashMap::new(),
|
||||||
@ -137,7 +152,14 @@ impl<'a> Gog<'a> {
|
|||||||
None => u64::min_value(),
|
None => u64::min_value(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let game = self.get_game(game_id, &os_filters, &language_filters)?;
|
let game = match self.get_game(game_id, &os_filters, &language_filters) {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(error) => {
|
||||||
|
error!("{}", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let game_hash = models::get_hash(&game);
|
let game_hash = models::get_hash(&game);
|
||||||
|
|
||||||
if game_hash_saved == game_hash {
|
if game_hash_saved == game_hash {
|
||||||
@ -145,7 +167,12 @@ impl<'a> Gog<'a> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let game_root = Path::new(storage_path).join(&game.title);
|
let game_root = if game.is_movie {
|
||||||
|
Path::new(storage_path_movies).join(&game.title)
|
||||||
|
} else {
|
||||||
|
Path::new(storage_path).join(&game.title)
|
||||||
|
};
|
||||||
|
|
||||||
fs::create_dir_all(&game_root)?;
|
fs::create_dir_all(&game_root)?;
|
||||||
|
|
||||||
if !game.cd_key.is_empty() {
|
if !game.cd_key.is_empty() {
|
||||||
@ -306,6 +333,17 @@ impl<'a> Gog<'a> {
|
|||||||
let game_raw: Value = serde_json::from_str(response.as_str())?;
|
let game_raw: Value = serde_json::from_str(response.as_str())?;
|
||||||
let downloads = &game_raw["downloads"];
|
let downloads = &game_raw["downloads"];
|
||||||
|
|
||||||
|
if game_raw.is_object() && !game_raw.as_object().unwrap().contains_key("forumLink") {
|
||||||
|
return Err(GogError::Error("No forumLink property"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_movie = match game_raw["forumLink"].as_str() {
|
||||||
|
Some(value) => value == "https://embed.gog.com/forum/movies",
|
||||||
|
None => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
game.is_movie = is_movie;
|
||||||
|
|
||||||
for languages in downloads.as_array() {
|
for languages in downloads.as_array() {
|
||||||
for language in languages {
|
for language in languages {
|
||||||
if !language.is_array() || language.as_array().unwrap().len() < 2 {
|
if !language.is_array() || language.as_array().unwrap().len() < 2 {
|
||||||
@ -323,14 +361,15 @@ impl<'a> Gog<'a> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !language_filters.is_empty() && !language_filters.contains(&installer_language) {
|
if !is_movie && !language_filters.is_empty() &&
|
||||||
|
!language_filters.contains(&installer_language) {
|
||||||
info!("Skipping {} for {}", &installer_language, game.title);
|
info!("Skipping {} for {}", &installer_language, game.title);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for systems in language[1].as_object() {
|
for systems in language[1].as_object() {
|
||||||
for system in systems.keys() {
|
for system in systems.keys() {
|
||||||
if !os_filters.is_empty() && !os_filters.contains(system) {
|
if is_movie && !os_filters.is_empty() && !os_filters.contains(system) {
|
||||||
info!("Skipping {} {} for {}",
|
info!("Skipping {} {} for {}",
|
||||||
&installer_language,
|
&installer_language,
|
||||||
system,
|
system,
|
||||||
|
13
src/http.rs
13
src/http.rs
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use curl;
|
use curl;
|
||||||
use curl::easy::{Easy, List, WriteError};
|
use curl::easy::{Easy, List, WriteError};
|
||||||
|
use std::fmt;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
@ -24,6 +25,18 @@ pub enum HttpError {
|
|||||||
UrlParseError(url::ParseError),
|
UrlParseError(url::ParseError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for HttpError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
HttpError::Error(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
HttpError::CurlError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
HttpError::Utf8Error(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
HttpError::IOError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
HttpError::UrlParseError(ref err) => fmt::Display::fmt(err, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<curl::Error> for HttpError {
|
impl From<curl::Error> for HttpError {
|
||||||
fn from(e: curl::Error) -> Self {
|
fn from(e: curl::Error) -> Self {
|
||||||
HttpError::CurlError(e)
|
HttpError::CurlError(e)
|
||||||
|
17
src/main.rs
17
src/main.rs
@ -52,6 +52,12 @@ fn main() {
|
|||||||
.value_name("FOLDER")
|
.value_name("FOLDER")
|
||||||
.help("Sets the download folder (defaults to the working directory).")
|
.help("Sets the download folder (defaults to the working directory).")
|
||||||
.takes_value(true))
|
.takes_value(true))
|
||||||
|
.arg(Arg::with_name("movie-storage")
|
||||||
|
.short("m")
|
||||||
|
.long("movie-storage")
|
||||||
|
.value_name("FOLDER")
|
||||||
|
.help("Sets the download folder for movies (defaults to the game directory).")
|
||||||
|
.takes_value(true))
|
||||||
.arg(Arg::with_name("os")
|
.arg(Arg::with_name("os")
|
||||||
.short("o")
|
.short("o")
|
||||||
.long("os")
|
.long("os")
|
||||||
@ -78,6 +84,11 @@ fn main() {
|
|||||||
None => config.storage.as_str(),
|
None => config.storage.as_str(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let download_folder_movies: &str = match matches.value_of("movieStorage") {
|
||||||
|
Some(value) => value,
|
||||||
|
None => config.movie_storage.as_str(),
|
||||||
|
};
|
||||||
|
|
||||||
let os_filters: Vec<String> = match matches.value_of("os") {
|
let os_filters: Vec<String> = match matches.value_of("os") {
|
||||||
Some(value) => value.split(',').map(String::from).collect(),
|
Some(value) => value.split(',').map(String::from).collect(),
|
||||||
None => config.os_filters,
|
None => config.os_filters,
|
||||||
@ -91,5 +102,9 @@ fn main() {
|
|||||||
let mut http_client = Http::new();
|
let mut http_client = Http::new();
|
||||||
let mut gog = Gog::new(&mut http_client);
|
let mut gog = Gog::new(&mut http_client);
|
||||||
gog.login().unwrap();
|
gog.login().unwrap();
|
||||||
gog.sync(download_folder, &os_filters, &language_filters).unwrap();
|
gog.sync(download_folder,
|
||||||
|
download_folder_movies,
|
||||||
|
&os_filters,
|
||||||
|
&language_filters)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ fn timestamp() -> i64 {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub storage: String,
|
pub storage: String,
|
||||||
|
pub movie_storage: String,
|
||||||
#[serde(default = "default_map")]
|
#[serde(default = "default_map")]
|
||||||
pub games: HashMap<String, u64>,
|
pub games: HashMap<String, u64>,
|
||||||
#[serde(default = "default_map")]
|
#[serde(default = "default_map")]
|
||||||
@ -57,6 +58,7 @@ impl Config {
|
|||||||
pub fn new() -> Config {
|
pub fn new() -> Config {
|
||||||
Config {
|
Config {
|
||||||
storage: String::from("."),
|
storage: String::from("."),
|
||||||
|
movie_storage: String::from("."),
|
||||||
games: HashMap::new(),
|
games: HashMap::new(),
|
||||||
installers: HashMap::new(),
|
installers: HashMap::new(),
|
||||||
extras: HashMap::new(),
|
extras: HashMap::new(),
|
||||||
@ -73,6 +75,8 @@ pub struct Game {
|
|||||||
pub title: String,
|
pub title: String,
|
||||||
pub cd_key: String,
|
pub cd_key: String,
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
|
pub is_movie: bool,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
pub installers: Vec<Installer>,
|
pub installers: Vec<Installer>,
|
||||||
pub extras: Vec<Extra>,
|
pub extras: Vec<Extra>,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user