initial proof of concept

This commit is contained in:
Sebastian Hugentobler 2017-03-19 14:50:58 +01:00
commit 65692ec481
5 changed files with 455 additions and 0 deletions

182
src/main.rs Normal file
View file

@ -0,0 +1,182 @@
extern crate url;
extern crate curl;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
use std::io;
use std::fs::File;
use std::io::Write;
use curl::easy::{Easy, List};
use std::str;
use serde_json::Value;
use url::{Url, Host};
use std::path::Path;
#[derive(Serialize, Deserialize)]
struct Token {
access_token: String,
expires_in: u16,
token_type: String,
scope: String,
session_id: String,
refresh_token: String,
user_id: String,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Game {
title: String,
cd_key: String,
#[serde(skip_deserializing)]
installers: Vec<Installer>,
extras: Vec<Extra>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Installer {
manual_url: String,
version: String,
os: String,
language: String,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Extra {
manual_url: String,
name: String,
}
fn main() {
const CLIENT_ID: &'static str = "46899977096215655";
const CLIENT_SECRET: &'static str = "9d85c43b1482497dbbce61f6e4aa173a433796eeae2ca8c5f6129f2dc4de46d9";
// const redirect_uri: &'static str = "https://embed.gog.com/on_login_success?origin=client";
const REDIRECT_URI_QUOTED: &'static str = "https%3A%2F%2Fembed.gog.\
com%2Fon_login_success%3Forigin%3Dclient";
let auth_url = format!("https://auth.gog.\
com/auth?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code&layout=client2",
client_id = CLIENT_ID,
redirect_uri = REDIRECT_URI_QUOTED);
println!("{}", auth_url);
let mut code = String::new();
print!("Code: ");
io::stdout().flush().unwrap();
io::stdin()
.read_line(&mut code)
.expect("Failed to read line");
let token_query = format!("https://auth.gog.\
com/token?client_id={client_id}&client_secret={client_secret}&grant_type=authorization_code&code={code}&redirect_uri={redirect_uri_quoted}",
client_id = CLIENT_ID,
client_secret = CLIENT_SECRET,
code = code.trim(),
redirect_uri_quoted = REDIRECT_URI_QUOTED);
let mut token_response_body = String::new();
let mut curl = Easy::new();
curl.url(token_query.as_str()).unwrap();
{
let mut transfer = curl.transfer();
transfer.write_function(|data| {
token_response_body = String::from(str::from_utf8(data).unwrap());
Ok(data.len())
})
.unwrap();
transfer.perform().unwrap();
}
let token: Token = serde_json::from_str(&token_response_body).unwrap();
let mut list = List::new();
list.append(format!("Authorization: Bearer {token}", token = token.access_token).as_str())
.unwrap();
curl.http_headers(list).unwrap();
curl.follow_location(true);
let mut games_response_body = String::new();
curl.url("https://embed.gog.com/user/data/games").unwrap();
{
let mut transfer = curl.transfer();
transfer.write_function(|data| {
games_response_body = String::from(str::from_utf8(data).unwrap());
Ok(data.len())
})
.unwrap();
transfer.perform().unwrap();
}
let game_ids_raw: Value = serde_json::from_str(games_response_body.as_str()).unwrap();
let game_ids = &game_ids_raw["owned"];
let mut game_response_body = String::new();
let game_query = format!("https://embed.gog.com/account/gameDetails/{game_id}.json",
game_id = game_ids[10]);
curl.url(game_query.as_str()).unwrap();
{
let mut transfer = curl.transfer();
transfer.write_function(|data| {
game_response_body = String::from(str::from_utf8(data).unwrap());
Ok(data.len())
})
.unwrap();
transfer.perform().unwrap();
}
let mut game: Game = serde_json::from_str(&game_response_body).unwrap();
let game_raw: Value = serde_json::from_str(game_response_body.as_str()).unwrap();
let downloads = &game_raw["downloads"];
for languages in downloads.as_array() {
for language in languages {
for systems in language[1].as_object() {
for system in systems.keys() {
for real_downloads in systems.get(system) {
for real_download in real_downloads.as_array() {
let download = &real_download[0];
let installer = Installer {
manual_url: String::from(download["manualUrl"].as_str().unwrap()),
version: String::from(download["manualUrl"].as_str().unwrap()),
os: system.clone(),
language: String::from(language[0].as_str().unwrap()),
};
game.installers.push(installer);
}
}
}
}
}
}
let download_query = format!("https://embed.gog.com{}", game.installers[0].manual_url);
curl.url(download_query.as_str()).unwrap();
curl.perform().unwrap();
let download_url = Url::parse(curl.effective_url().unwrap().unwrap()).unwrap();
let file_name = download_url.path_segments().unwrap().last().unwrap();
let download_path = Path::new("/Users/sebastianhugentobler/Downloads/").join(file_name);
let mut file_download = File::create(download_path).unwrap();
curl.url(download_query.as_str()).unwrap();
{
let mut transfer = curl.transfer();
transfer.write_function(|data| {
file_download.write(data);
Ok(data.len())
})
.unwrap();
transfer.perform().unwrap();
}
}