initial proof of concept
This commit is contained in:
commit
65692ec481
5 changed files with 455 additions and 0 deletions
182
src/main.rs
Normal file
182
src/main.rs
Normal 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();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue