Skip to content
This repository has been archived by the owner on May 14, 2024. It is now read-only.

Commit

Permalink
Added "Generate RoPro Verification Token" option, need to fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefanuk12 committed Dec 28, 2022
1 parent 9532641 commit 488d6f4
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 13 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
[package]
name = "ropro-patcher"
version = "0.1.1"
version = "0.1.2"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = { version = "1.0", features = ["derive"] }
reqwest = { version = "0.11", features = ["json", "blocking"] }
platform-dirs = "0.3.0"
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ This currently does not support Firefox but it easily can be done manually.
## NOTE
Chrome (and possibly other browsers) have a feature that checks the hash of the extension. This means that it will flag as corrupted. Therefore, you will have to download the extension, patch it with a custom path and use developer mode to load an unpacked extension.

- an exception to this rule is Opera GX
- an exception to this rule is Opera GX

# Getting RoPro Verification Token
You may use the patcher to get this token, however, you might find it easier to do it another way:
- Go to your extensions in your browser, e.g. `chrome://extensions`
- You should see something like `Inspect views background page` under RoPro
- Press on the underlined __background page__
- The developer console for the extensions should open, go to the console tab
- Execute this `await getStorage("userVerification")`
- The format will be `{USERID: 'TOKEN'}`
127 changes: 116 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,39 +47,144 @@ fn patch(path: PathBuf) {
fs::write(options.clone(), options_contents).expect("Unable to write file contents (options.js)");
}

// Converts Roblox cookie to CSRF
fn grab_csrf(cookie: String) -> String {
// Create the request
let client = reqwest::blocking::Client::new();
let response = client.post("https://catalog.roblox.com/v1/catalog/items/details")
.header("Cookie", format!(".ROBLOSECURITY={};", cookie))
.header("content-length", 0)
.send()
.unwrap();

// Return header
let csrf = response.headers()["x-csrf-token"].to_str().unwrap().to_owned();
return csrf;
}

// Grab verification metadata from RoPro
#[derive(serde::Deserialize)]
struct Verification {
universeId: i64
}
fn grab_verification_md() -> i64 {
// Create the request
let client = reqwest::blocking::Client::new();
let response: Verification = client.post("https://api.ropro.io/verificationMetadata.php")
.header("content-length", 0)
.send()
.unwrap()
.json()
.unwrap();

// Return
return response.universeId;
}

// (Un)favourite a Roblox universe
fn favourite_universe(cookie: String, csrf: String, universe_id: i64, unfavourite: bool) {
// Create the request
let client = reqwest::blocking::Client::new();
let mut data = std::collections::HashMap::new();
data.insert("isFavorited", !unfavourite);
let response = client.post(format!("https://games.roblox.com/v1/games/{}/favorites", universe_id))
.header("Cookie", format!(".ROBLOSECURITY={};", cookie))
.header("x-csrf-token", csrf)
.json(&data)
.send();

// Check for error
if response.is_err() {
println!("Unable to (un)favourite universe for unknown reason")
}
}

// Get the verification token
#[derive(serde::Deserialize)]
struct VerificationResponse {
success: bool,
error_code: Option<i8>,
token: Option<String>
}
fn get_verification() -> String {
// Create the request
let client = reqwest::blocking::Client::new();
let response: VerificationResponse = client.post("https://api.ropro.io/generateVerificationToken.php")
.header("content-length", 0)
.send()
.unwrap()
.json()
.unwrap();

// Return
if response.success == false {
return response.error_code.unwrap().to_string();
} else {
return response.token.unwrap();
}
}

// Main
fn main() {
// Grab the input directory
let mut input_dir = String::new();
print!("Thanks for using Stefanuk12's RoPro Patcher.\n\nPlease select an option:\n\n1. Opera GX\n2. Google Chrome\n3. Custom Path\n> ");
print!("Thanks for using Stefanuk12's RoPro Patcher.\n\nPlease select an option:\n\n0. Generate RoPro Verification Token\n1. Opera GX\n2. Custom Path\n> ");
stdout().flush().unwrap();
stdin().read_line(&mut input_dir).ok().expect("Failed to get user input");

// All of the options
let path: PathBuf;
match input_dir.trim() {
// Generate RoPro Verification Token
"0" => {
// Ask for their Roblox cookie
let mut cookie = String::new();
cookie.clear();
print!("Please enter your Roblox cookie (without the '.ROBLOSECURITY=' part)\n> ");
stdout().flush().unwrap();
stdin().read_line(&mut cookie).ok().expect("Failed to get user input");
cookie = cookie.trim().to_string();

// Resolve to CSRF
let csrf = grab_csrf(cookie.to_owned());

// Favourite, grab token, unfavourite
let universe_id = grab_verification_md();
favourite_universe(cookie.to_owned(), csrf.to_owned(), universe_id, false);
let token = get_verification();
favourite_universe(cookie.to_owned(), csrf.to_owned(), universe_id, true);

// Check
if token.len() == 25 {
println!("Got your RoPro verification token: {}", token);
} else {
println!("There was an issue with getting your token (Error {})", token)
}

//
pause();
}
// Opera GX
"1" => {
path = fs::read_dir(AppDirs::new(Some(r"Opera Software\Opera GX Stable\Extensions\adbacgifemdbhdkfppmeilbgppmhaobf"), false).unwrap().config_dir).expect("Unable to grab Opera GX extension.").next().unwrap().unwrap().path();
}
// Google Chrome
"2" => {
path = fs::read_dir(AppDirs::new(Some(r"Google\Chrome\User Data\Default\Extensions\adbacgifemdbhdkfppmeilbgppmhaobf"), false).unwrap().cache_dir).expect("Unable to grab Google Chrome extension.").next().unwrap().unwrap().path();
patch(path);
println!("Patched!");
pause();
}
// Custom Path
"3" => {
"2" => {
input_dir.clear();
print!("Please enter the path: ");
stdout().flush().unwrap();
stdin().read_line(&mut input_dir).ok().expect("Failed to get user input");
path = PathBuf::from(input_dir.trim().to_string());

patch(path);
println!("Patched!");
pause();
}
// Neither of above
_ => panic!("Invalid option")
}

// Patching
patch(path);
println!("Patched!");
pause();
}

0 comments on commit 488d6f4

Please sign in to comment.