mirror of
https://github.com/BugisoftRSG/SCAPI.git
synced 2024-12-22 20:47:25 +08:00
Release
This commit is contained in:
commit
466edec3a3
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
26
.github/workflows/ci.yml
vendored
Normal file
26
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: Build Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build on Windows and Linux
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Configure and Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build .
|
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# IDE
|
||||
.vs/
|
||||
.vscode/*
|
||||
!.vscode/launch.json
|
||||
.cache/
|
||||
|
||||
# output directory
|
||||
build/
|
||||
out/
|
||||
__pycache__/
|
||||
|
||||
# precompiled headers
|
||||
*.ipch
|
||||
*.gch
|
||||
*.pch
|
BIN
.vs/slnx.sqlite
Normal file
BIN
.vs/slnx.sqlite
Normal file
Binary file not shown.
48
CMakeLists.txt
Normal file
48
CMakeLists.txt
Normal file
@ -0,0 +1,48 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(SCAPI CXX ASM_MASM)
|
||||
|
||||
set(SRC_DIR "${PROJECT_SOURCE_DIR}/src")
|
||||
|
||||
# Fetch modules
|
||||
message("\nFetching modules")
|
||||
include(scripts/pugixml.cmake)
|
||||
include(scripts/cpr.cmake)
|
||||
include(scripts/json.cmake)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/scripts)
|
||||
find_package(botan 2.19.3 REQUIRED)
|
||||
botan_generate(botan sha1 hmac rc4 rng base64 mac stream hash auto_rng win32_stats)
|
||||
|
||||
# SCAPI
|
||||
message(STATUS "SCAPI")
|
||||
file(GLOB_RECURSE SRC_MAIN
|
||||
"${SRC_DIR}/**.hpp"
|
||||
"${SRC_DIR}/**.h"
|
||||
"${SRC_DIR}/**.cpp"
|
||||
"${SRC_DIR}/**.cc"
|
||||
"${SRC_DIR}/**.cxx"
|
||||
"${SRC_DIR}/**.asm"
|
||||
)
|
||||
add_executable(SCAPI "${SRC_MAIN}")
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
set_property(TARGET SCAPI PROPERTY CXX_STANDARD 23) # 23 Because std::format is not avalible in std:c++20 for some reason. Maybe it's because i use v142 toolset.
|
||||
|
||||
source_group(TREE ${SRC_DIR} PREFIX "src" FILES ${SRC_MAIN} )
|
||||
|
||||
target_include_directories(SCAPI PRIVATE
|
||||
"${SRC_DIR}"
|
||||
"${json_SOURCE_DIR}/single_include"
|
||||
)
|
||||
|
||||
target_link_libraries(SCAPI PRIVATE botan pugixml cpr json)
|
||||
|
||||
# Warnings as errors
|
||||
set_property(TARGET SCAPI PROPERTY COMPILE_WARNING_AS_ERROR ON)
|
||||
|
||||
add_compile_definitions(SCAPI
|
||||
"_CRT_SECURE_NO_WARNINGS"
|
||||
"NOMINMAX"
|
||||
"WIN32_LEAN_AND_MEAN"
|
||||
)
|
15
CMakeSettings.json
Normal file
15
CMakeSettings.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
}
|
||||
]
|
||||
}
|
53
README.md
Normal file
53
README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# SCAPI
|
||||
|
||||
This project is designed to better understand the API's from Rockstar Games used in Grand Theft Auto V.
|
||||
|
||||
## Features
|
||||
|
||||
### UGC
|
||||
- Copy Job (From other/same platforms to PC, but not vice versa)
|
||||
- Copy Local Job (Copy your own jobs)
|
||||
- Delete Content (Can delete any job you created)
|
||||
- Query Content (Get the job meta info of a job)
|
||||
- Check Text (Checks if a given text is a profanity)
|
||||
- Query Content Creators (Actual usage unknown)
|
||||
|
||||
### Auth
|
||||
- Create Ticket
|
||||
|
||||
### Geo Location
|
||||
- Get Location Info from IP (Looks like its Max Mind DB)
|
||||
|
||||
### Matchmaking
|
||||
- Get Matchmaking (Lists all Sessions available to join)
|
||||
|
||||
### Inbox
|
||||
- Send Email (May also corrupt the target's inbox if base64'd gamer handle is wrong)
|
||||
- Send Bounty completed Message
|
||||
|
||||
### Presence
|
||||
- Send Invite (IIRC only works on friends since the ballstortue incursion)
|
||||
|
||||
### Misc
|
||||
- Decrypt (Allows you to decrypt an http request/response and get the raw xml)
|
||||
|
||||
### Libraries
|
||||
|
||||
This project was builded on Microsoft Visual Studio Community 2022 (64bit)
|
||||
|
||||
Dependencies:
|
||||
- [Botan](https://github.com/randombit/botan)
|
||||
- [cpr](https://github.com/libcpr/cpr)
|
||||
- [pugixml](https://github.com/libcpr/cpr)
|
||||
- Python for Botan
|
||||
|
||||
Build Instructions (Win64)
|
||||
```bash
|
||||
git clone https://github.com/BugisoftRSG/SCAPI.git
|
||||
cd SCAPI
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
```
|
||||
|
||||
## Known Issues
|
||||
- GetTopRatedContent returns SqlException
|
BIN
bfg-1.14.0.jar
Normal file
BIN
bfg-1.14.0.jar
Normal file
Binary file not shown.
140
scripts/FindBotan.cmake
Normal file
140
scripts/FindBotan.cmake
Normal file
@ -0,0 +1,140 @@
|
||||
## This module will automagically download the tarball of the specified Botan version and invoke the configure.py
|
||||
## python script to generate the amalgamation files (botan_all.cpp and botan_all.h).
|
||||
##
|
||||
## Usage:
|
||||
## find_package(
|
||||
## botan 2.18.2
|
||||
## COMPONENTS
|
||||
## system_rng
|
||||
## argon2
|
||||
## sha3
|
||||
## REQUIRED
|
||||
## )
|
||||
##
|
||||
## target_link_libraries(
|
||||
## MyTarget
|
||||
## PRIVATE
|
||||
## botan
|
||||
## )
|
||||
##
|
||||
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
include(FetchContent)
|
||||
|
||||
# Find python
|
||||
find_package(
|
||||
Python
|
||||
COMPONENTS
|
||||
Interpreter
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
# Assemble version string
|
||||
set(Botan_VERSION_STRING "Botan-2.19.3")
|
||||
|
||||
# Assemble download URL
|
||||
set(DOWNLOAD_URL https://botan.randombit.net/releases/${Botan_VERSION_STRING}.tar.xz)
|
||||
|
||||
# Just do a dummy download to see whether we can download the tarball
|
||||
file(
|
||||
DOWNLOAD
|
||||
${DOWNLOAD_URL}
|
||||
STATUS download_status
|
||||
)
|
||||
if (NOT download_status EQUAL 0)
|
||||
message(FATAL_ERROR "Could not download Botan tarball (status = ${download_status}): ${DOWNLOAD_URL}")
|
||||
endif()
|
||||
|
||||
# Download the tarball
|
||||
FetchContent_Declare(
|
||||
botan_upstream
|
||||
URL ${DOWNLOAD_URL}
|
||||
)
|
||||
FetchContent_MakeAvailable(botan_upstream)
|
||||
|
||||
# Heavy lifting by cmake
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Botan DEFAULT_MSG Botan_VERSION_STRING)
|
||||
|
||||
## Function to generate a target named 'TARGET_NAME' with specific Botan modules enabled.
|
||||
function(botan_generate TARGET_NAME MODULES)
|
||||
# The last N arguments are considered to be the modules list.
|
||||
# Here, we collect those in a list and join them with a comma separator ready to be passed to the configure.py script.
|
||||
foreach(module_index RANGE 1 ${ARGC}-2)
|
||||
list(APPEND modules_list ${ARGV${module_index}})
|
||||
|
||||
# Check if PKCS11 module is enabled
|
||||
# Note: This is for a workaround, see further below for more details.
|
||||
if (ARGV${module_index} STREQUAL "pkcs11")
|
||||
set(PKCS11_ENABLED ON)
|
||||
endif()
|
||||
endforeach()
|
||||
list(JOIN modules_list "," ENABLE_MODULES_LIST)
|
||||
|
||||
# Determine botan compiler ID (--cc parameter of configure.py)
|
||||
set(BOTAN_COMPILER_ID ${CMAKE_CXX_COMPILER_ID})
|
||||
string(TOLOWER ${BOTAN_COMPILER_ID} BOTAN_COMPILER_ID)
|
||||
if (BOTAN_COMPILER_ID STREQUAL "gnu")
|
||||
set(BOTAN_COMPILER_ID "gcc")
|
||||
endif()
|
||||
|
||||
# Run the configure.py script
|
||||
add_custom_command(
|
||||
OUTPUT botan_all.cpp botan_all.h
|
||||
COMMENT "Generating Botan amalgamation files botan_all.cpp and botan_all.h"
|
||||
COMMAND ${Python_EXECUTABLE}
|
||||
${botan_upstream_SOURCE_DIR}/configure.py
|
||||
--quiet
|
||||
--cc-bin=${CMAKE_CXX_COMPILER}
|
||||
--cc=${BOTAN_COMPILER_ID}
|
||||
$<$<BOOL:${MINGW}>:--os=mingw>
|
||||
--disable-shared
|
||||
--amalgamation
|
||||
--minimized-build
|
||||
--enable-modules=${ENABLE_MODULES_LIST}
|
||||
)
|
||||
|
||||
# Create target
|
||||
set(TARGET ${TARGET_NAME})
|
||||
add_library(${TARGET} STATIC)
|
||||
target_sources(
|
||||
${TARGET}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_BINARY_DIR}/botan_all.h
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}/botan_all.cpp
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
${TARGET}
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
set_target_properties(
|
||||
${TARGET}
|
||||
PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
|
||||
#
|
||||
# PKCS11 Workaround
|
||||
#
|
||||
# This section is a workaround to handle a "bug" in upstream Botan.
|
||||
# Basically, the amalgamation build of Botan does not include the necessary PKCS11 headers when the PKCS11 module
|
||||
# is enabled.
|
||||
#
|
||||
# See:
|
||||
# - https://github.com/randombit/botan/issues/1447
|
||||
# - https://github.com/randombit/botan/issues/976
|
||||
#
|
||||
if (PKCS11_ENABLED)
|
||||
file(COPY ${botan_upstream_SOURCE_DIR}/src/lib/prov/pkcs11/pkcs11.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
file(COPY ${botan_upstream_SOURCE_DIR}/src/lib/prov/pkcs11/pkcs11f.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
file(COPY ${botan_upstream_SOURCE_DIR}/src/lib/prov/pkcs11/pkcs11t.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(
|
||||
${TARGET}
|
||||
PRIVATE
|
||||
${botan_upstream_SOURCE_DIR}/src/lib/prov/pkcs11
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
14
scripts/cpr.cmake
Normal file
14
scripts/cpr.cmake
Normal file
@ -0,0 +1,14 @@
|
||||
include(FetchContent)
|
||||
|
||||
set(BUILD_TESTING_BEFORE ${BUILD_TESTING})
|
||||
set(CURL_DISABLE_TESTS OFF)
|
||||
FetchContent_Declare(
|
||||
cpr
|
||||
GIT_REPOSITORY https://github.com/libcpr/cpr.git
|
||||
GIT_TAG 1986262ba4e0cb052161e9e7919aef5ef08217f0
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("cpr")
|
||||
FetchContent_MakeAvailable(cpr)
|
||||
|
||||
set(BUILD_TESTING ${BUILD_TESTING_BEFORE} CACHE INTERNAL "" FORCE)
|
12
scripts/json.cmake
Normal file
12
scripts/json.cmake
Normal file
@ -0,0 +1,12 @@
|
||||
include(FetchContent)
|
||||
|
||||
set(JSON_MultipleHeaders OFF)
|
||||
|
||||
FetchContent_Declare(
|
||||
json
|
||||
GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent.git
|
||||
GIT_TAG 67e6070f9d9a44b4dec79ebe6b591f39d2285593
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("json")
|
||||
FetchContent_MakeAvailable(json)
|
11
scripts/pugixml.cmake
Normal file
11
scripts/pugixml.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
pugixml
|
||||
GIT_REPOSITORY https://github.com/zeux/pugixml.git
|
||||
GIT_TAG a0e064336317c9347a91224112af9933598714e9
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("pugixml")
|
||||
FetchContent_MakeAvailable(pugixml)
|
||||
set_property(TARGET pugixml PROPERTY CXX_STANDARD 23)
|
17
src/AccountInfo.hpp
Normal file
17
src/AccountInfo.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
class AccountInfo
|
||||
{
|
||||
public:
|
||||
uint64_t m_rockstar_id;
|
||||
int m_age;
|
||||
string m_avatar_url;
|
||||
string m_country_code;
|
||||
string m_date_of_birth;
|
||||
string m_email;
|
||||
bool m_is_approx_dob;
|
||||
string m_language_code;
|
||||
string m_nickname;
|
||||
string m_last_portal_login_date;
|
||||
};
|
118
src/command.cpp
Normal file
118
src/command.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include "command.hpp"
|
||||
#include "ros_crypt.hpp"
|
||||
#include <cpr/cpr.h>
|
||||
|
||||
ROSCrypt* command::m_launcher_ros = nullptr;
|
||||
ROSCrypt* command::m_ros = nullptr;
|
||||
|
||||
command::command(const string& name) : m_name(name)
|
||||
{
|
||||
m_launcher_ros = new ROSCrypt(true);
|
||||
m_ros = new ROSCrypt(false);
|
||||
|
||||
g_commands[hash<string>()(name)] = this;
|
||||
}
|
||||
|
||||
command* command::get(int command)
|
||||
{
|
||||
return g_commands[command];
|
||||
}
|
||||
|
||||
string command::run_raw(const string url, const string queryString, bool launcher)
|
||||
{
|
||||
auto api = launcher ? m_launcher_ros : m_ros;
|
||||
|
||||
string absolutePath = url.substr(url.find('/', url.find("://") + 3));
|
||||
|
||||
Botan::AutoSeeded_RNG rng;
|
||||
auto challenge = rng.random_vec(8);
|
||||
|
||||
cpr::Response response = cpr::Post(
|
||||
cpr::Url{ url },
|
||||
cpr::Header
|
||||
{
|
||||
{"ros-SecurityFlags", "239" },
|
||||
{"ros-SessionTicket", SESSION_TICKET},
|
||||
{"ros-Challenge", Botan::base64_encode(challenge)},
|
||||
{"ros-HeadersHmac", Botan::base64_encode(api->HeadersHmac(challenge, "POST", absolutePath, SESSION_KEY, SESSION_TICKET)) },
|
||||
{"Content-Type", "application/x-www-form-urlencoded; charset=utf-8"},
|
||||
{"User-Agent", api->GetROSVersionString()},
|
||||
},
|
||||
cpr::Body{ queryString });
|
||||
|
||||
return response.text;
|
||||
}
|
||||
|
||||
string command::run(const string url, map<string, string> map)
|
||||
{
|
||||
auto service_type = this->get_service_type();
|
||||
|
||||
if (service_type == PROD_ROS || service_type == PROD_ROS_LAUNCHER)
|
||||
{
|
||||
auto api = service_type == SERVICE_TYPE::PROD_ROS_LAUNCHER ? m_launcher_ros : m_ros;
|
||||
|
||||
auto params = api->BuildPostString(map);
|
||||
|
||||
string queryString = api->EncryptROSData(params, SESSION_KEY);
|
||||
|
||||
string response = run_raw(url, queryString, service_type == SERVICE_TYPE::PROD_ROS_LAUNCHER);
|
||||
|
||||
if (!response.contains("Internal server error"))
|
||||
return api->DecryptROSData(response.c_str(), response.size(), SESSION_KEY);
|
||||
else {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
else if (service_type == PROD_SCAPI_AMC)
|
||||
{
|
||||
cpr::Parameters params;
|
||||
for (const auto& entry : map) {
|
||||
params.Add(cpr::Parameter(entry.first, entry.second));
|
||||
}
|
||||
|
||||
cpr::Response response = cpr::Get(
|
||||
cpr::Url{ url },
|
||||
cpr::Header
|
||||
{
|
||||
{"Content-Type", "application/x-www-form-urlencoded; charset=utf-8"},
|
||||
{"X-AMC", "true"},
|
||||
{"X-Requested-With", "XMLHttpRequest"}
|
||||
},
|
||||
cpr::Parameters{ params });
|
||||
|
||||
cout << response.status_code << endl;
|
||||
|
||||
return response.text;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
string command::run(const string url, string params)
|
||||
{
|
||||
string queryString = m_ros->EncryptROSData(params, SESSION_KEY);
|
||||
|
||||
string response = run_raw(url, queryString);
|
||||
|
||||
if (!response.contains("Internal server error"))
|
||||
return m_ros->DecryptROSData(response.c_str(), response.size(), SESSION_KEY);
|
||||
else {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
string command::run_anonymous(const string& url, map<string, string> map)
|
||||
{
|
||||
string queryString = m_ros->EncryptROSData(m_ros->BuildPostString(map));
|
||||
|
||||
cpr::Response response = cpr::Post(
|
||||
cpr::Url{ url },
|
||||
cpr::Header
|
||||
{
|
||||
{"Content-Type", "application/x-www-form-urlencoded; charset=utf-8"},
|
||||
{"User-Agent", m_ros->GetROSVersionString()}
|
||||
},
|
||||
cpr::Body{ queryString });
|
||||
|
||||
return m_ros->DecryptROSData(response.text.c_str(), response.text.size(), "");
|
||||
}
|
45
src/command.hpp
Normal file
45
src/command.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <pugixml.hpp>
|
||||
#include "ros_crypt.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
inline string TICKET;
|
||||
inline string SESSION_TICKET;
|
||||
inline string SESSION_KEY;
|
||||
|
||||
enum SERVICE_TYPE
|
||||
{
|
||||
UNKNOWN,
|
||||
PROD_ROS,
|
||||
PROD_ROS_LAUNCHER,
|
||||
PROD_SCAPI_AMC,
|
||||
PROD_CLOUD
|
||||
};
|
||||
|
||||
class command
|
||||
{
|
||||
protected:
|
||||
string m_name;
|
||||
|
||||
string run_raw(const string url, const string queryString, bool launcher = false);
|
||||
string run(const string url, map<string, string> map);
|
||||
string run(const string url, string params);
|
||||
string run_anonymous(const string& url, map<string, string> map);
|
||||
public:
|
||||
|
||||
command(const string& name);
|
||||
inline const string& get_name() { return m_name; }
|
||||
static command* get(int command);
|
||||
virtual string execute(const vector<string>& args) = 0;
|
||||
virtual SERVICE_TYPE get_service_type() = 0;
|
||||
|
||||
static ROSCrypt* m_launcher_ros;
|
||||
static ROSCrypt* m_ros;
|
||||
};
|
||||
|
||||
inline unordered_map<int, command*> g_commands;
|
@ -0,0 +1,25 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class AwardAchievement : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the achievementId:" << endl;
|
||||
string achievementId;
|
||||
cin >> achievementId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["achievementId"] = achievementId;
|
||||
map["achievedOffline"] = "False";
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/achievements.asmx/AwardAchievement", map);
|
||||
}
|
||||
};
|
||||
|
||||
AwardAchievement g_award_achievement("awardachievement");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class AwardAchievementProgress : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the achievementId:" << endl;
|
||||
string achievementId;
|
||||
cin >> achievementId;
|
||||
|
||||
cout << "Specify the achievementProgress:" << endl;
|
||||
string achievementProgress;
|
||||
cin >> achievementProgress;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["achievementId"] = achievementId;
|
||||
map["achievedOffline"] = "False";
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/achievements.asmx/AwardAchievementProgress", map);
|
||||
}
|
||||
};
|
||||
|
||||
AwardAchievementProgress g_award_achievement_progress("awardachievementprogress");
|
@ -0,0 +1,34 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetAchievementDefinitions : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string firstAchievementId;
|
||||
cin >> firstAchievementId;
|
||||
|
||||
cout << "Specify the maxDefinitions:" << endl;
|
||||
string maxDefinitions;
|
||||
cin >> maxDefinitions;
|
||||
|
||||
cout << "Specify the locale (ex. en-US):" << endl;
|
||||
string locale;
|
||||
cin >> locale;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["firstAchievementId"] = firstAchievementId;
|
||||
map["maxDefinitions"] = maxDefinitions;
|
||||
map["locale"] = locale;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/achievements.asmx/GetAchievementDefinitions", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetAchievementDefinitions g_get_achievement_definitions("getachievementdefinitions");
|
@ -0,0 +1,27 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetPlayerAchievements : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the rockstarId:" << endl;
|
||||
string rockstarId;
|
||||
cin >> rockstarId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["playerRockstarId"] = rockstarId;
|
||||
map["crossTitleId"] = "11";
|
||||
map["crossTitleName"] = "gta5";
|
||||
map["crossTitlePlatformName"] = "pcros";
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/achievements.asmx/GetPlayerAchievements", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetPlayerAchievements g_get_player_achievements("getplayerachievements");
|
@ -0,0 +1,30 @@
|
||||
#include "../../../command.hpp"
|
||||
|
||||
class CreateP2PCertificate : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pubKey" << endl;
|
||||
string pubKey;
|
||||
cin >> pubKey;
|
||||
|
||||
cout << "Specify the sig" << endl;
|
||||
string sig;
|
||||
cin >> sig;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pubKeyCurve"] = "nistP256";
|
||||
map["pubKey"] = pubKey;
|
||||
map["hashAlg"] = "SHA256";
|
||||
map["sig"] = sig;
|
||||
|
||||
return run("https://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/auth.asmx/CreateP2PCertificate", map);
|
||||
}
|
||||
};
|
||||
|
||||
CreateP2PCertificate g_create_p2p_certificate("createp2pcertificate");
|
@ -0,0 +1,20 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class CreateScAuthToken : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/auth.asmx/CreateTicketScAuthToken2", map);
|
||||
}
|
||||
};
|
||||
|
||||
CreateScAuthToken g_create_sc_auth_token("createscauthtoken");
|
195
src/commands/prod.ros.rockstargames.com/Auth/CreateTicket.cpp
Normal file
195
src/commands/prod.ros.rockstargames.com/Auth/CreateTicket.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
#include "../../../command.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
class CreateTicket : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
inline void request_socialclub_data(unordered_map<string, string>& env_vars)
|
||||
{
|
||||
cout << "Specify your SocialClub Email" << endl;
|
||||
string email;
|
||||
cin >> email;
|
||||
|
||||
cout << "Specify your SocialClub Profile Name" << endl;
|
||||
string nickname;
|
||||
cin >> nickname;
|
||||
|
||||
cout << "Specify your SocialClub Password" << endl;
|
||||
string password;
|
||||
cin >> password;
|
||||
|
||||
env_vars["EMAIL"] = email;
|
||||
env_vars["NICKNAME"] = nickname;
|
||||
env_vars["PASSWORD"] = password;
|
||||
env_vars["PLATFORM"] = "pcros";
|
||||
|
||||
ofstream outFile(".env");
|
||||
|
||||
for (const auto& pair : env_vars) {
|
||||
outFile << pair.first << "=" << pair.second << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
inline bool request_ticket(string email, string nickname, string password, string platform, string& _response)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["ticket"] = "";
|
||||
map["email"] = email;
|
||||
map["nickname"] = nickname;
|
||||
map["password"] = password;
|
||||
map["platformName"] = platform;
|
||||
|
||||
string response = run_anonymous("https://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/auth.asmx/CreateTicketSc3", map);
|
||||
|
||||
pugi::xml_document doc;
|
||||
if (!doc.load_string(response.c_str())) return false;
|
||||
|
||||
bool successfully = false;
|
||||
|
||||
ofstream outFile("data.bin");
|
||||
|
||||
pugi::xml_node xml_response = doc.child("Response");
|
||||
|
||||
for (pugi::xml_node panel = xml_response.first_child(); panel; panel = panel.next_sibling())
|
||||
{
|
||||
if (strcmp(panel.name(), "Ticket") == 0)
|
||||
{
|
||||
TICKET = panel.text().get();
|
||||
cout << "Ticket: " << TICKET << endl;
|
||||
outFile << "TICKET" << "=" << TICKET << "\n";
|
||||
successfully = true;
|
||||
}
|
||||
else if (strcmp(panel.name(), "SessionKey") == 0)
|
||||
{
|
||||
SESSION_KEY = panel.text().get();
|
||||
cout << "Session Key: " << SESSION_KEY << endl;
|
||||
outFile << "SESSION_KEY" << "=" << SESSION_KEY << "\n";
|
||||
}
|
||||
else if (strcmp(panel.name(), "SessionTicket") == 0)
|
||||
{
|
||||
SESSION_TICKET = panel.text().get();
|
||||
cout << "Session Ticket: " << SESSION_TICKET << endl;
|
||||
outFile << "SESSION_TICKET" << "=" << SESSION_TICKET << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_response = response;
|
||||
|
||||
return successfully;
|
||||
}
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
unordered_map<string, string> env_vars;
|
||||
|
||||
ifstream infile("data.bin");
|
||||
|
||||
bool skip;
|
||||
|
||||
if (filesystem::exists("data.bin"))
|
||||
{
|
||||
string line;
|
||||
while (getline(infile, line)) {
|
||||
size_t equal_pos = line.find('=');
|
||||
if (equal_pos != string::npos) {
|
||||
string key = line.substr(0, equal_pos);
|
||||
string value = line.substr(equal_pos + 1);
|
||||
|
||||
if (key == "TICKET")
|
||||
TICKET = value;
|
||||
else if (key == "SESSION_KEY")
|
||||
SESSION_KEY = value;
|
||||
else if (key == "SESSION_TICKET")
|
||||
SESSION_TICKET = value;
|
||||
}
|
||||
}
|
||||
|
||||
string data = command::get(hash<string>()("getaccountinfo"))->execute({});
|
||||
if (data.empty() || data.contains("Internal Server Error") || data.contains("AuthenticationFailed"))
|
||||
{
|
||||
cout << "Auth -> Cached session is no longer valid... recreating now." << endl;
|
||||
|
||||
if (filesystem::exists("data.bin"))
|
||||
{
|
||||
cout << ".env found at " << filesystem::absolute(".env") << endl;
|
||||
ifstream infile(".env");
|
||||
string line;
|
||||
while (getline(infile, line)) {
|
||||
size_t equal_pos = line.find('=');
|
||||
if (equal_pos != string::npos) {
|
||||
string key = line.substr(0, equal_pos);
|
||||
string value = line.substr(equal_pos + 1);
|
||||
env_vars[key] = value;
|
||||
}
|
||||
}
|
||||
infile.close();
|
||||
|
||||
bool success;
|
||||
string response;
|
||||
do {
|
||||
success = request_ticket(env_vars.at("EMAIL"), env_vars.at("NICKNAME"), env_vars.at("PASSWORD"), env_vars.at("PLATFORM"), response);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
cout << "Auth -> Invalid credentials or rate limited" << endl;
|
||||
request_socialclub_data(env_vars);
|
||||
}
|
||||
} while (!success);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
else if (data.contains("Error Code"))
|
||||
{
|
||||
cout << "Auth -> Received Error: " << data << endl;
|
||||
|
||||
bool success;
|
||||
string response;
|
||||
do {
|
||||
request_socialclub_data(env_vars);
|
||||
success = request_ticket(env_vars.at("EMAIL"), env_vars.at("NICKNAME"), env_vars.at("PASSWORD"), env_vars.at("PLATFORM"), response);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
cout << "Auth -> Invalid credentials or rate limited" << endl;
|
||||
}
|
||||
} while (!success);
|
||||
|
||||
return response;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Auth -> Using cached session";
|
||||
}
|
||||
}
|
||||
else if (!filesystem::exists(".env") || !filesystem::exists("data.bin"))
|
||||
{
|
||||
request_socialclub_data(env_vars);
|
||||
|
||||
bool success;
|
||||
string response;
|
||||
do {
|
||||
success = request_ticket(env_vars.at("EMAIL"), env_vars.at("NICKNAME"), env_vars.at("PASSWORD"), env_vars.at("PLATFORM"), response);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
cout << "Auth -> Invalid credentials or rate limited" << endl;
|
||||
request_socialclub_data(env_vars);
|
||||
}
|
||||
} while (!success);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
return "error";
|
||||
}
|
||||
};
|
||||
|
||||
CreateTicket g_create_ticket("createticket");
|
24
src/commands/prod.ros.rockstargames.com/Clans/Disband.cpp
Normal file
24
src/commands/prod.ros.rockstargames.com/Clans/Disband.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class Disband : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/Disband", map);
|
||||
}
|
||||
};
|
||||
|
||||
Disband g_disband("disbandcrew");
|
49
src/commands/prod.ros.rockstargames.com/Clans/GetAll.cpp
Normal file
49
src/commands/prod.ros.rockstargames.com/Clans/GetAll.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetAll : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
cout << "Specify if isSystemClan (0 = no/1 = yes, -1 = any):" << endl;
|
||||
string isSystemClan;
|
||||
cin >> isSystemClan;
|
||||
|
||||
cout << "Specify if isOpenClan (0 = no/1 = yes, -1 = any):" << endl;
|
||||
string isOpenClan;
|
||||
cin >> isOpenClan;
|
||||
|
||||
cout << "Specify the search (Can be 0):" << endl;
|
||||
string search;
|
||||
cin >> search;
|
||||
|
||||
cout << "Specify the sortMode (Can be 0, other values unknown yet):" << endl;
|
||||
string sortMode;
|
||||
cin >> sortMode;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
map["isSystemClan"] = isSystemClan;
|
||||
map["isOpenClan"] = isOpenClan;
|
||||
map["search"] = search;
|
||||
map["sortMode"] = sortMode;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetAll", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetAll g_get_all("getallcrews");
|
24
src/commands/prod.ros.rockstargames.com/Clans/GetDesc.cpp
Normal file
24
src/commands/prod.ros.rockstargames.com/Clans/GetDesc.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetDesc : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetDesc", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetDesc g_get_desc("getcrewdesc");
|
24
src/commands/prod.ros.rockstargames.com/Clans/GetDescs.cpp
Normal file
24
src/commands/prod.ros.rockstargames.com/Clans/GetDescs.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetDescs : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanIdsCsv (ex.: 12345,56789):" << endl;
|
||||
string clanIdsCsv;
|
||||
cin >> clanIdsCsv;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanIdsCsv"] = clanIdsCsv;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetDescs", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetDescs g_get_descs("getcrewdescs");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetFeudStats : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the since ((lastday, lastweek, last2weeks, lastmonth, last3months, last6months, alltime) / 0):" << endl;
|
||||
string since;
|
||||
cin >> since;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
map["since"] = since;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetFeudStats", map); // TODO Internal Server Error (no longer in use?)
|
||||
}
|
||||
};
|
||||
|
||||
GetFeudStats g_get_feud_stats("getfeudstats");
|
29
src/commands/prod.ros.rockstargames.com/Clans/GetInvites.cpp
Normal file
29
src/commands/prod.ros.rockstargames.com/Clans/GetInvites.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetInvites : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetInvites", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetInvites g_get_invites("getcrewinvites");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetLeadersForClans : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanIdsCsv (ex.: 123456,789801):" << endl;
|
||||
string clanIdsCsv;
|
||||
cin >> clanIdsCsv;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanIdsCsv"] = clanIdsCsv;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetLeadersForClans", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetLeadersForClans g_get_leaders_for_clans("getleadersforclans");
|
39
src/commands/prod.ros.rockstargames.com/Clans/GetMembers.cpp
Normal file
39
src/commands/prod.ros.rockstargames.com/Clans/GetMembers.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetCrewMembers : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the clanName:" << endl;
|
||||
string clanName;
|
||||
cin >> clanName;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
map["clanId"] = clanId;
|
||||
map["clanName"] = clanName;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetMembers", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetCrewMembers g_get_crew_members("getcrewmembers");
|
@ -0,0 +1,39 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetCrewMembersTitleOnly : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the clanName:" << endl;
|
||||
string clanName;
|
||||
cin >> clanName;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
map["clanId"] = clanId;
|
||||
map["clanName"] = clanName;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetMembersTitleOnly", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetCrewMembersTitleOnly g_get_crew_members_title_only("getcrewmemberstitleonly");
|
@ -0,0 +1,34 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetMetadataForClan : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
map["clanId"] = clanId;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetMetadataForClan", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetMetadataForClan g_get_metadata_for_clan("getcrewmetadata");
|
29
src/commands/prod.ros.rockstargames.com/Clans/GetMine.cpp
Normal file
29
src/commands/prod.ros.rockstargames.com/Clans/GetMine.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetMine : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetMine", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetMine g_get_mine("getmycrew");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetPrimaryClans : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the gamerHandlesCsv (ex.: 123456,789900):" << endl;
|
||||
string gamerHandlesCsv;
|
||||
cin >> gamerHandlesCsv;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["gamerHandlesCsv"] = gamerHandlesCsv;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetPrimaryClans", map); // Exception, no further info
|
||||
}
|
||||
};
|
||||
|
||||
GetPrimaryClans g_get_primary_clans("getprimaryclans");
|
34
src/commands/prod.ros.rockstargames.com/Clans/GetRanks.cpp
Normal file
34
src/commands/prod.ros.rockstargames.com/Clans/GetRanks.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetRanks : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetRanks", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetRanks g_get_ranks("getcrewranks");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetSentInvites : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetSentInvites", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetSentInvites g_get_sent_invites("getsentcrewinvites");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetTopRivals : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the since ((lastday, lastweek, last2weeks, lastmonth, last3months, last6months, alltime) / 0):" << endl;
|
||||
string since;
|
||||
cin >> since;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
map["since"] = since;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetTopRivals1", map); // Internal Error, no longer used?
|
||||
}
|
||||
};
|
||||
|
||||
GetTopRivals g_get_top_rivals("gettoprivals");
|
@ -0,0 +1,35 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetWallMessages : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the pageIndex:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the pageSize:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
map["clanId"] = clanId;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetWallMessages", map); // Internal Server Error, great
|
||||
}
|
||||
};
|
||||
|
||||
GetWallMessages g_get_wall_messages("getwallmessages");
|
24
src/commands/prod.ros.rockstargames.com/Clans/JoinClan.cpp
Normal file
24
src/commands/prod.ros.rockstargames.com/Clans/JoinClan.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class JoinCrew : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/Join", map);
|
||||
}
|
||||
};
|
||||
|
||||
JoinCrew g_join_crew("joincrew");
|
29
src/commands/prod.ros.rockstargames.com/Clans/Kick.cpp
Normal file
29
src/commands/prod.ros.rockstargames.com/Clans/Kick.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class Kick : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the targetGamerHandle:" << endl;
|
||||
string targetGamerHandle;
|
||||
cin >> targetGamerHandle;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
map["targetGamerHandle"] = targetGamerHandle;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/Kick", map);
|
||||
}
|
||||
};
|
||||
|
||||
Kick g_kick("kickfromcrew");
|
24
src/commands/prod.ros.rockstargames.com/Clans/Leave.cpp
Normal file
24
src/commands/prod.ros.rockstargames.com/Clans/Leave.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class Leave : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/Leave", map);
|
||||
}
|
||||
};
|
||||
|
||||
Leave g_leave("leavecrew");
|
@ -0,0 +1,34 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class MemberSetRankByRankOrder : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the targetGamerHandle:" << endl;
|
||||
string targetGamerHandle;
|
||||
cin >> targetGamerHandle;
|
||||
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the rankOrder:" << endl;
|
||||
string rankOrder;
|
||||
cin >> rankOrder;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["targetGamerHandle"] = targetGamerHandle;
|
||||
map["clanId"] = clanId;
|
||||
map["rankOrder"] = rankOrder;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/MemberSetRankByRankOrder", map); // Title or Environment not supported
|
||||
}
|
||||
};
|
||||
|
||||
MemberSetRankByRankOrder g_member_set_rank_by_rank_order("membersetrankbyrankorder");
|
@ -0,0 +1,34 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class MemberUpdateRankId : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the targetGamerHandle:" << endl;
|
||||
string targetGamerHandle;
|
||||
cin >> targetGamerHandle;
|
||||
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify if promote (true/false):" << endl;
|
||||
string promote;
|
||||
cin >> promote;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["targetGamerHandle"] = targetGamerHandle;
|
||||
map["clanId"] = clanId;
|
||||
map["promote"] = promote;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/MemberUpdateRankId", map); // Invalid Argument for some reason
|
||||
}
|
||||
};
|
||||
|
||||
MemberUpdateRankId g_member_update_rank_id("memberupdaterankid");
|
34
src/commands/prod.ros.rockstargames.com/Clans/RankCreate.cpp
Normal file
34
src/commands/prod.ros.rockstargames.com/Clans/RankCreate.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class RankCreate : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the rankName (0-4):" << endl; //?
|
||||
string rankName;
|
||||
cin >> rankName;
|
||||
|
||||
cout << "Specify the initialSystemFlags:" << endl;
|
||||
string initialSystemFlags;
|
||||
cin >> initialSystemFlags;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
map["rankName"] = rankName;
|
||||
map["initialSystemFlags"] = initialSystemFlags;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/RankCreate", map); // Error: OutOfRange -> ClanRankLength
|
||||
}
|
||||
};
|
||||
|
||||
RankCreate g_rank_create("createcrewrank");
|
29
src/commands/prod.ros.rockstargames.com/Clans/RankDelete.cpp
Normal file
29
src/commands/prod.ros.rockstargames.com/Clans/RankDelete.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class RankDelete : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the rankId:" << endl;
|
||||
string rankId;
|
||||
cin >> rankId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
map["rankId"] = rankId;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/RankDelete", map);
|
||||
}
|
||||
};
|
||||
|
||||
RankDelete g_rank_delete("deletecrewrank");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class SetPrimaryClan : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/SetPrimaryClan", map);
|
||||
}
|
||||
};
|
||||
|
||||
SetPrimaryClan g_set_primary_clan("setprimaryclan");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class WriteWallMessage : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the clanId:" << endl;
|
||||
string clanId;
|
||||
cin >> clanId;
|
||||
|
||||
cout << "Specify the message:" << endl;
|
||||
string message;
|
||||
cin >> message;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["clanId"] = clanId;
|
||||
map["message"] = message;
|
||||
|
||||
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/WriteWallMessage", map); // Internal Server Error, no longer in use?
|
||||
}
|
||||
};
|
||||
|
||||
WriteWallMessage write_wall_message("writecrewwallmessage");
|
23
src/commands/prod.ros.rockstargames.com/Decrypt.cpp
Normal file
23
src/commands/prod.ros.rockstargames.com/Decrypt.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "../../command.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "../../ros_crypt.hpp"
|
||||
|
||||
class Decrypt : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
ifstream infile(R"(C:\Users\Bugisoft\Downloads\GTA_Reverse\request_content.txt)", ios_base::binary);
|
||||
|
||||
vector<char> bytes((istreambuf_iterator<char>(infile)), (istreambuf_iterator<char>()));
|
||||
|
||||
return m_ros->DecryptROSData(&bytes[0], bytes.size(), SESSION_KEY);
|
||||
}
|
||||
};
|
||||
|
||||
Decrypt g_decrypt("decrypt");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class AcceptFriendRequest : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the rockstarId:" << endl;
|
||||
string rockstarId;
|
||||
cin >> rockstarId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["rockstarId"] = rockstarId;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/AcceptInvite", map); // Missleading name, friend request not session invite
|
||||
}
|
||||
};
|
||||
|
||||
AcceptFriendRequest g_accept_friend_request("acceptfriendrequest");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class InviteByNickname : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the nickname:" << endl;
|
||||
string nickname;
|
||||
cin >> nickname;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["nickName"] = nickname;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/InviteByNickname", map); // This name is missleading since you doesnt actually "invite" a friend instead send a friend request
|
||||
}
|
||||
};
|
||||
|
||||
InviteByNickname g_invite_by_nickname("addfriendbyname");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class InviteByRockstarId : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the rockstar id:" << endl;
|
||||
string rockstarId;
|
||||
cin >> rockstarId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["rockstarId"] = rockstarId;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/InviteByRockstarId", map); // This name is missleading since you doesnt actually "invite" a friend instead send a friend request
|
||||
}
|
||||
};
|
||||
|
||||
InviteByRockstarId g_invite_by_rockstarid("addfriendbyrid");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class BlockCommunications : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the rockstarId:" << endl;
|
||||
string rockstarId;
|
||||
cin >> rockstarId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["rockstarId"] = rockstarId;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/Block", map); // Missleading name, dont have to be a friend
|
||||
}
|
||||
};
|
||||
|
||||
BlockCommunications g_block_communications("blockcoms");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class CancelFriendRequest : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the rockstar id:" << endl;
|
||||
string rockstarId;
|
||||
cin >> rockstarId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["rockstarId"] = rockstarId;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/CancelInvite", map);
|
||||
}
|
||||
};
|
||||
|
||||
CancelFriendRequest g_cancel_invite("cancelfriendrequest");
|
27
src/commands/prod.ros.rockstargames.com/Friends/CountAll.cpp
Normal file
27
src/commands/prod.ros.rockstargames.com/Friends/CountAll.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class CountAll : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
/*
|
||||
* Response:
|
||||
* b -> ?
|
||||
* f -> Friend Count
|
||||
* ir -> Friend Requests Received (See: getfriendrequestssent)
|
||||
* is -> Friend Requests Sent (See:
|
||||
*/
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/CountAll", map);
|
||||
}
|
||||
};
|
||||
|
||||
CountAll g_count_all_friends("countallfriends");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class DeclineFriendRequest : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the rockstarId:" << endl;
|
||||
string rockstarId;
|
||||
cin >> rockstarId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["rockstarId"] = rockstarId;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/DeclineInvite", map); // Missleading name, friend request not session invite
|
||||
}
|
||||
};
|
||||
|
||||
DeclineFriendRequest g_decline_friend_request("declinefriendrequest");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetBlocked : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the page index:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the page size:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetBlocked", map); // Missleading name, not blocked friends just overall blocked players
|
||||
}
|
||||
};
|
||||
|
||||
GetBlocked g_get_blocked("getblocked");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetFriendRequestsReceived : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the page index:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the page size:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetInvitesReceived", map); // Again missleading name
|
||||
}
|
||||
};
|
||||
|
||||
GetFriendRequestsReceived g_get_friend_requests_received("getfriendrequestsreceived");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetFriendRequestsSent : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the page index:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the page size:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetInvitesSent", map); // Again missleading name
|
||||
}
|
||||
};
|
||||
|
||||
GetFriendRequestsSent g_get_friend_requests("getfriendrequestssent");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetFriends : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the page index:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the page size:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetFriends", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetFriends g_get_friends("getfriends");
|
@ -0,0 +1,31 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
// Basically this just also includes the crew name and id
|
||||
|
||||
class GetFriendsAndRequestsSent : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the page index:" << endl;
|
||||
string pageIndex;
|
||||
cin >> pageIndex;
|
||||
|
||||
cout << "Specify the page size:" << endl;
|
||||
string pageSize;
|
||||
cin >> pageSize;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["pageIndex"] = pageIndex;
|
||||
map["pageSize"] = pageSize;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetFriendsAndInvitesSent", map); // missleading name
|
||||
}
|
||||
};
|
||||
|
||||
GetFriendsAndRequestsSent g_get_friends_and_requests_sent("getfriendsandrequestssent");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class RemoveFriend : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the rockstar id:" << endl;
|
||||
string rockstarId;
|
||||
cin >> rockstarId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["rockstarId"] = rockstarId;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/RemoveFriend", map);
|
||||
}
|
||||
};
|
||||
|
||||
RemoveFriend g_remove_friend("removefriend");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class UnblockCommunications : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the rockstarId:" << endl;
|
||||
string rockstarId;
|
||||
cin >> rockstarId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["rockstarId"] = rockstarId;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/Unblock", map); // Missleading name, dont have to be a friend
|
||||
}
|
||||
};
|
||||
|
||||
UnblockCommunications g_unblock_communications("unblockcoms");
|
@ -0,0 +1,23 @@
|
||||
#include "../../../command.hpp"
|
||||
|
||||
class GetLocationInfoFromIP : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the ip:" << endl;
|
||||
string target_rid;
|
||||
cin >> target_rid;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["ipAddrStr"] = target_rid;
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/GeoLocation.asmx/GetLocationInfoFromIP", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetLocationInfoFromIP g_get_location_info_from_ip("getlocationinfofromip");
|
@ -0,0 +1,25 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class GetRelayServers : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the ipAddrStr:" << endl;
|
||||
string ipAddrStr;
|
||||
cin >> ipAddrStr;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["ipAddrStr"] = ipAddrStr;
|
||||
map["secure"] = "false";
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/GeoLocation.asmx/GetRelayServers", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetRelayServers g_get_relay_servers("getrelayservers");
|
31
src/commands/prod.ros.rockstargames.com/Inbox/SendAward.cpp
Normal file
31
src/commands/prod.ros.rockstargames.com/Inbox/SendAward.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
|
||||
class SendAwardMsg : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the target rid:" << endl;
|
||||
string target_rid;
|
||||
cin >> target_rid;
|
||||
|
||||
cout << "Specify the sender name:" << endl;
|
||||
string senderGamerTag;
|
||||
cin >> senderGamerTag;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["recipientsCsv"] = target_rid;
|
||||
map["message"] = format(R"("ros.publish":{{"channel":"friends","msg":{{"gm.evt":{{"e":"StatUpdate","d":{{"stat":1488317176,"from":"{}","ival":100}}}}}}}})", senderGamerTag);
|
||||
map["ttlSeconds"] = "0";
|
||||
|
||||
return run("http://prs-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Presence.asmx/MultiPostMessage", map);
|
||||
}
|
||||
};
|
||||
|
||||
SendAwardMsg g_send_award_msg("sendawardmessage");
|
47
src/commands/prod.ros.rockstargames.com/Inbox/SendBounty.cpp
Normal file
47
src/commands/prod.ros.rockstargames.com/Inbox/SendBounty.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class BountyCompletedMsg : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the target rid:" << endl;
|
||||
string target_rid;
|
||||
cin >> target_rid;
|
||||
|
||||
cout << "Specify the tl31FromGamerTag:" << endl;
|
||||
string tl31FromGamerTag;
|
||||
cin >> tl31FromGamerTag;
|
||||
|
||||
cout << "Specify the tl31TargetGamerTag:" << endl;
|
||||
string tl31TargetGamerTag;
|
||||
cin >> tl31TargetGamerTag;
|
||||
|
||||
cout << "Specify the iOutcome:" << endl;
|
||||
string iOutcome;
|
||||
cin >> iOutcome;
|
||||
|
||||
cout << "Specify the iCash:" << endl;
|
||||
string iCash;
|
||||
cin >> iCash;
|
||||
|
||||
cout << "Specify the iRank:" << endl;
|
||||
string iRank;
|
||||
cin >> iRank;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["userIds"] = target_rid;
|
||||
map["message"] = format(R"({{"gm.evt":{{"e":"bounty","d":{{"Ft":"{}","Tt":"{}","o":{},"c":{},"r":{},"t":1690670145566}}}}}})", tl31FromGamerTag, tl31TargetGamerTag, iOutcome, iCash, iRank);
|
||||
map["tagsCsv"] = "gta5";
|
||||
map["ttlSeconds"] = "1800";
|
||||
|
||||
return run("http://inbox-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Inbox.asmx/PostMessageToRecipients", map);
|
||||
}
|
||||
};
|
||||
|
||||
BountyCompletedMsg g_send_bounty_completed_msg("sendbountycompletedmsg");
|
76
src/commands/prod.ros.rockstargames.com/Inbox/SendEmail.cpp
Normal file
76
src/commands/prod.ros.rockstargames.com/Inbox/SendEmail.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class SendEmail : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
class rlGamerHandle
|
||||
{
|
||||
public:
|
||||
uint64_t m_rockstar_id; //0x0000
|
||||
uint8_t m_platform = 3; //0x0008
|
||||
uint8_t unk_0009; //0x0009
|
||||
}; //Size: 0x0010
|
||||
static_assert(sizeof(rlGamerHandle) == 0x10);
|
||||
|
||||
string rlGamerHandleToBase64(const rlGamerHandle& handle)
|
||||
{
|
||||
const char* base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
vector<uint8_t> bytes(sizeof(rlGamerHandle));
|
||||
memcpy(bytes.data(), &handle, sizeof(rlGamerHandle));
|
||||
|
||||
string result;
|
||||
size_t paddingCount = (3 - bytes.size() % 3) % 3;
|
||||
|
||||
for (size_t i = 0; i < bytes.size(); i += 3)
|
||||
{
|
||||
uint32_t value = (bytes[i] << 16) | ((i + 1 < bytes.size() ? bytes[i + 1] : 0) << 8) | ((i + 2 < bytes.size() ? bytes[i + 2] : 0));
|
||||
result += base64Chars[(value >> 18) & 0x3F];
|
||||
result += base64Chars[(value >> 12) & 0x3F];
|
||||
result += (i + 1 < bytes.size() || paddingCount < 2) ? base64Chars[(value >> 6) & 0x3F] : '=';
|
||||
result += (i + 2 < bytes.size() || paddingCount < 1) ? base64Chars[value & 0x3F] : '=';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the sender rid:" << endl;
|
||||
string sender_rid;
|
||||
cin >> sender_rid;
|
||||
|
||||
cout << "Specify the target rid:" << endl;
|
||||
string target_rid;
|
||||
cin >> target_rid;
|
||||
|
||||
cin.ignore(1000000, '\n');
|
||||
|
||||
cout << "Specify the subject:" << endl;
|
||||
string subject;
|
||||
getline(cin, subject);
|
||||
|
||||
cin.ignore(1000000, '\n');
|
||||
|
||||
cout << "Specify the content:" << endl;
|
||||
string content;
|
||||
getline(cin, content);
|
||||
|
||||
rlGamerHandle handle = rlGamerHandle(stoull(sender_rid));
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["userIds"] = target_rid;
|
||||
map["message"] = format(R"({{"email":{{"gh":"{}","sb":"{}","cn":"{}"}}}})", rlGamerHandleToBase64(handle), subject, content);
|
||||
map["tagsCsv"] = "gta5email"; // gta5marketing
|
||||
map["ttlSeconds"] = "2592000"; // 1800
|
||||
|
||||
return run("http://inbox-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Inbox.asmx/PostMessageToRecipients", map);
|
||||
}
|
||||
};
|
||||
|
||||
SendEmail g_send_email("sendemail");
|
@ -0,0 +1,24 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class Matchmaking : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["availableSlots"] = "1";
|
||||
map["filterName"] = "Group";
|
||||
// filterParamsJson={"GAME_MODE":0,"MMATTR_REGION":0}
|
||||
map["filterParamsJson"] = R"({"GAME_MODE":0,"MMATTR_MM_GROUP_2":30,"MMATTR_REGION":3})";
|
||||
map["maxResults"] = "999999";
|
||||
|
||||
return run("http://mm-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/matchmaking.asmx/Find", map);
|
||||
}
|
||||
};
|
||||
|
||||
Matchmaking g_matchmaking("matchmaking");
|
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
|
||||
class QueryWithMaxRecordLength : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the target rid:" << endl;
|
||||
string target_rid;
|
||||
cin >> target_rid;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["queryName"] = "SessionByGamerHandle";
|
||||
map["paramNameValueCsv"] = format(R"(@ghandle,"SC+{}")", target_rid);
|
||||
map["offset"] = "0";
|
||||
map["count"] = "20";
|
||||
map["maxQueryBufferSize"] = "7680";
|
||||
|
||||
return run("http://prs-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Presence.asmx/QueryWithMaxRecordLength", map);
|
||||
}
|
||||
};
|
||||
|
||||
QueryWithMaxRecordLength query_with_max_record_length("querywithmaxrecordlength");
|
@ -0,0 +1,35 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class SendInvite : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the sender rid:" << endl;
|
||||
string sender_rid;
|
||||
cin >> sender_rid;
|
||||
cout << "Specify the sender name:" << endl;
|
||||
string sender_name;
|
||||
cin >> sender_name;
|
||||
cout << "Specify the target rid:" << endl;
|
||||
string target_rid;
|
||||
cin >> target_rid;
|
||||
cout << "Specify the session info:" << endl;
|
||||
string session_info;
|
||||
cin >> session_info;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["recipientsCsv"] = "SC+" + target_rid;
|
||||
map["message"] = format(R"("ros.mp.invite":{{"h":"SC+{}","n":"{}","s":"{}"}})", sender_rid, sender_name, session_info);
|
||||
map["ttlSeconds"] = "0";
|
||||
|
||||
return run("http://prs-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Presence.asmx/MultiPostMessage", map);
|
||||
}
|
||||
};
|
||||
|
||||
SendInvite g_send_invite("sendinvite");
|
@ -0,0 +1,23 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
//#include <fstream>
|
||||
|
||||
class ReadGameConfig : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
|
||||
//ofstream of("readgameconfig.txt");
|
||||
//of << run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ProfileStatGroups.asmx/ReadGameConfig", map);
|
||||
|
||||
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ProfileStatGroups.asmx/ReadGameConfig", map); // Response text is too large for console
|
||||
}
|
||||
};
|
||||
|
||||
ReadGameConfig g_read_game_config("readgameconfig");
|
@ -0,0 +1,19 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class ReadAllStats : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
|
||||
return run("https://ps-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/ReadAllStats", map); // loads infinite?
|
||||
}
|
||||
};
|
||||
|
||||
ReadAllStats g_read_all_stats("readallstats");
|
@ -0,0 +1,55 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class CreateAccountSc : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the country code" << endl;
|
||||
string countryCode;
|
||||
cin >> countryCode;
|
||||
|
||||
cout << "Specify the date of bearth (dd/mm/yyyy)" << endl;
|
||||
string dob;
|
||||
cin >> dob;
|
||||
|
||||
cout << "Specify the email" << endl;
|
||||
string email;
|
||||
cin >> email;
|
||||
|
||||
cout << "Specify the language code" << endl;
|
||||
string languageCode;
|
||||
cin >> languageCode;
|
||||
|
||||
cout << "Specify the nickname" << endl;
|
||||
string nickname;
|
||||
cin >> nickname;
|
||||
|
||||
cout << "Specify the password" << endl;
|
||||
string password;
|
||||
cin >> password;
|
||||
|
||||
map<string, string> map;
|
||||
map["acceptNewsletter"] = "false";
|
||||
map["avatarUrl"] = "https://prod-avatars.akamaized.net/stock-avatars/n/GTAO/CASINO_2.png";
|
||||
map["countryCode"] = countryCode;
|
||||
map["dob"] = dob;
|
||||
map["email"] = email;
|
||||
map["isApproxDob"] = "False";
|
||||
map["languageCode"] = languageCode;
|
||||
map["nickname"] = nickname;
|
||||
map["password"] = password;
|
||||
map["phone"] = "";
|
||||
map["platform"] = "pcros";
|
||||
map["zipCode"] = "1379800";
|
||||
|
||||
|
||||
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/CreateAccountSc", map);
|
||||
}
|
||||
};
|
||||
|
||||
CreateAccountSc g_create_account_sc("createaccountsc");
|
@ -0,0 +1,19 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class GetAccountInfo : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
|
||||
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/GetAccountInfo", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetAccountInfo g_get_account_info("getaccountinfo");
|
@ -0,0 +1,19 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class GetScAuthToken : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
|
||||
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/GetScAuthToken", map);
|
||||
}
|
||||
};
|
||||
|
||||
GetScAuthToken g_get_sc_auth_token("getscauthtoken");
|
@ -0,0 +1,34 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
|
||||
class LinkAccount2 : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the email:" << endl;
|
||||
string email;
|
||||
cin >> email;
|
||||
|
||||
cout << "Specify the nickname:" << endl;
|
||||
string nickname;
|
||||
cin >> nickname;
|
||||
|
||||
cout << "Specify the password:" << endl;
|
||||
string password;
|
||||
cin >> password;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["email"] = email;
|
||||
map["nickname"] = nickname;
|
||||
map["password"] = password;
|
||||
|
||||
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/LinkAccount2", map);
|
||||
}
|
||||
};
|
||||
|
||||
LinkAccount2 g_link_account_2("linkaccount2");
|
@ -0,0 +1,62 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <format>
|
||||
#include "AccountInfo.hpp"
|
||||
|
||||
class UpdateAccount : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
inline AccountInfo GetAccountInfo()
|
||||
{
|
||||
string data = command::get(hash<string>()("getaccountinfo"))->execute({});
|
||||
pugi::xml_document doc;
|
||||
AccountInfo accountInfo{};
|
||||
|
||||
if (doc.load_string(data.c_str()))
|
||||
{
|
||||
auto path = doc.select_node("//Response/RockstarAccount");
|
||||
auto node = path.node();
|
||||
|
||||
accountInfo.m_rockstar_id = node.child("RockstarId").text().as_uint();
|
||||
accountInfo.m_age = node.child("Age").text().as_int();
|
||||
accountInfo.m_avatar_url = node.child("AvatarUrl").text().as_string();
|
||||
accountInfo.m_country_code = node.child("CountryCode").text().as_string();
|
||||
accountInfo.m_date_of_birth = node.child("Dob").text().as_string();
|
||||
accountInfo.m_email = node.child("Email").text().as_string();
|
||||
accountInfo.m_is_approx_dob = node.child("IsApproxDob").text().as_bool(); // TODO
|
||||
accountInfo.m_language_code = node.child("LanguageCode").text().as_string();
|
||||
accountInfo.m_nickname = node.child("Nickname").text().as_string();
|
||||
accountInfo.m_last_portal_login_date = node.child("LastPortalLoginDate").text().as_string();
|
||||
}
|
||||
|
||||
return accountInfo;
|
||||
}
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
AccountInfo accountInfo = GetAccountInfo();
|
||||
|
||||
cout << "Specify the email:" << endl;
|
||||
string email;
|
||||
cin >> email;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["avatarUrl"] = "null"; // if this invalid, it will be skipped, you can't just put a .jpg or .png there
|
||||
map["countryCode"] = accountInfo.m_country_code;
|
||||
map["dob"] = accountInfo.m_date_of_birth;
|
||||
map["email"] = email;
|
||||
map["isApproxDob"] = accountInfo.m_is_approx_dob ? "True" : "False";
|
||||
map["languageCode"] = accountInfo.m_language_code;
|
||||
map["nickname"] = accountInfo.m_nickname;
|
||||
map["phone"] = "";
|
||||
map["zipCode"] = "";
|
||||
|
||||
|
||||
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/UpdateAccount", map);
|
||||
}
|
||||
};
|
||||
|
||||
UpdateAccount g_update_account("updateaccount");
|
29
src/commands/prod.ros.rockstargames.com/UGC/CheckText.cpp
Normal file
29
src/commands/prod.ros.rockstargames.com/UGC/CheckText.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class CheckText : command
|
||||
{
|
||||
// Tested from UGC Creator -> Job Title
|
||||
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the text to check:" << endl;
|
||||
string text;
|
||||
cin >> text;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["languageCode"] = ""; // Can be empty
|
||||
map["contentName"] = ""; // Can be empty
|
||||
map["description"] = text; // Text to check
|
||||
map["tagCsv"] = ""; // Can be empty
|
||||
|
||||
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/CheckText", map);
|
||||
}
|
||||
};
|
||||
|
||||
CheckText g_check_text("checktext");
|
189
src/commands/prod.ros.rockstargames.com/UGC/CopyJob.cpp
Normal file
189
src/commands/prod.ros.rockstargames.com/UGC/CopyJob.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "../../../ros_crypt.hpp"
|
||||
#include <cpr/cpr.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
class CopyJob : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
inline bool GetJobDetails(string_view content_id, string& title, string& description, string& type, vector<string>& tags, string& image)
|
||||
{
|
||||
cpr::Response response = cpr::Get(
|
||||
cpr::Url{ "https://scapi.rockstargames.com/ugc/mission/details" },
|
||||
cpr::Header{ {"X-AMC", "true" }, { "X-Requested-With", "XMLHttpRequest"} },
|
||||
cpr::Parameters{ {"title", "gtav"}, {"contentId", content_id.data()} });
|
||||
|
||||
nlohmann::json job_details = nlohmann::json::parse(string{ response.text });
|
||||
|
||||
if (job_details["content"].is_object())
|
||||
{
|
||||
nlohmann::json content = job_details["content"];
|
||||
|
||||
title = content["name"];
|
||||
description = content["desc"];
|
||||
type = content["type"];
|
||||
tags = content["userTags"];
|
||||
image = content["imgSrc"];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool GetJobMetaData(string_view content_id, string& result)
|
||||
{
|
||||
string data = command::get(hash<string>()("querycontent"))->execute({ "GetLatestVersionByContentId", content_id.data() });
|
||||
pugi::xml_document doc;
|
||||
int f0 = 0, f1 = 0;
|
||||
string lang;
|
||||
|
||||
if (doc.load_string(data.c_str()))
|
||||
{
|
||||
auto path = doc.select_node("//Response/Result/r/m");
|
||||
auto node = path.node();
|
||||
|
||||
f1 = node.attribute("f1").as_int();
|
||||
f0 = node.attribute("f0").as_int();
|
||||
lang = node.attribute("l").as_string();
|
||||
}
|
||||
|
||||
cpr::Response response = cpr::Get(cpr::Url{ format("https://prod.cloud.rockstargames.com/ugc/gta5mission/{}/{}_{}_{}.json", content_id, f1 < 0 ? 0 : f1, f0 < 0 ? 0 : f0, lang.empty() ? "en" : lang) });
|
||||
|
||||
result = response.text;
|
||||
|
||||
return response.status_code == 200;
|
||||
}
|
||||
|
||||
vector<unsigned char> HexToBytes(const string& hex) {
|
||||
vector<unsigned char> bytes;
|
||||
|
||||
for (unsigned int i = 0; i < hex.length(); i += 2) {
|
||||
string byteString = hex.substr(i, 2);
|
||||
unsigned char byte = (unsigned char)strtol(byteString.c_str(), NULL, 16);
|
||||
bytes.push_back(byte);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
vector<unsigned char> get_data_len(size_t data_len, bool image) // should be 107684
|
||||
{
|
||||
stringstream ss;
|
||||
ss << hex << data_len;
|
||||
string data_len_hex = ss.str();
|
||||
|
||||
|
||||
if (data_len_hex.length() % 2 != 0) {
|
||||
data_len_hex = "0" + data_len_hex;
|
||||
}
|
||||
|
||||
vector<unsigned char> data_len_bytes = HexToBytes(data_len_hex); // should be \x01\xa4\xa4
|
||||
|
||||
switch (data_len_bytes.size()) {
|
||||
case 1:
|
||||
data_len_bytes.insert(data_len_bytes.begin(), 3, 0);
|
||||
break;
|
||||
case 2:
|
||||
data_len_bytes.insert(data_len_bytes.begin(), 2, 0);
|
||||
break;
|
||||
case 3:
|
||||
data_len_bytes.insert(data_len_bytes.begin(), 1, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
data_len_bytes.insert(data_len_bytes.end(), 3, 0);
|
||||
if (image)
|
||||
data_len_bytes.push_back(2);
|
||||
else
|
||||
data_len_bytes.push_back(0);
|
||||
|
||||
return data_len_bytes;
|
||||
}
|
||||
|
||||
string replaceAll(string const& original, string const& from, string const& to)
|
||||
{
|
||||
string results;
|
||||
string::const_iterator end = original.end();
|
||||
string::const_iterator current = original.begin();
|
||||
string::const_iterator next = search(current, end, from.begin(), from.end());
|
||||
while (next != end) {
|
||||
results.append(current, next);
|
||||
results.append(to);
|
||||
current = next + from.size();
|
||||
next = search(current, end, from.begin(), from.end());
|
||||
}
|
||||
results.append(current, next);
|
||||
return results;
|
||||
}
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the content id:" << endl;
|
||||
string content_id;
|
||||
cin >> content_id;
|
||||
|
||||
string title, description, type, image;
|
||||
vector<string> tags;
|
||||
string metadata;
|
||||
|
||||
if (GetJobDetails(content_id, title, description, type, tags, image))
|
||||
{
|
||||
if (!GetJobMetaData(content_id, metadata))
|
||||
{
|
||||
return "Couldn't download job metadata";
|
||||
}
|
||||
}
|
||||
|
||||
map<string, string> map;
|
||||
|
||||
ofstream of("2_0.jpg", ios::binary);
|
||||
cpr::Response r = cpr::Download(of, cpr::Url{ image });
|
||||
ifstream input("2_0.jpg", ios_base::binary);
|
||||
vector<unsigned char> image_bytes((istreambuf_iterator<char>(input)), (istreambuf_iterator<char>()));
|
||||
|
||||
nlohmann::json meta_json = nlohmann::json::parse(metadata);
|
||||
|
||||
vector<unsigned char> data_len = get_data_len(meta_json.dump().size(), false);
|
||||
vector<unsigned char> image_data_len = get_data_len(image_bytes.size(), true);
|
||||
|
||||
nlohmann::json datajson;
|
||||
datajson["meta"] = meta_json["meta"];
|
||||
datajson["mission"] = meta_json["mission"];
|
||||
datajson["version"] = 2;
|
||||
|
||||
string temp = format("ticket={}&contentType=gta5mission¶msJson=", m_ros->url_encode(TICKET));
|
||||
|
||||
temp += m_ros->ex_url_encode(format(R"({{"ContentName":"{}","DataJson":"{}","Description":"{}","Publish":true,"Language":"{}","TagCsv":"{}"}})", title, replaceAll(datajson.dump(), "\"", "\\\""), description, "en", ""));
|
||||
temp += "&data=";
|
||||
|
||||
for (auto& i : data_len)
|
||||
{
|
||||
temp += i;
|
||||
}
|
||||
|
||||
temp += meta_json.dump();
|
||||
|
||||
for (auto& i : image_data_len)
|
||||
{
|
||||
temp += i;
|
||||
}
|
||||
for (auto& i : image_bytes)
|
||||
{
|
||||
temp += i;
|
||||
}
|
||||
|
||||
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/CreateContent", temp);
|
||||
}
|
||||
};
|
||||
|
||||
CopyJob g_copy_job("copyjob");
|
@ -0,0 +1,21 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class CopyLocalContent : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["contentType"] = "gta5mission";
|
||||
map["contentId"] = "Qa2frulcv0u2eHmWg7KSHA"; // TODO
|
||||
|
||||
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/CopyContent", map);
|
||||
}
|
||||
};
|
||||
|
||||
CopyLocalContent g_copy_local_content("copylocalcontent");
|
@ -0,0 +1,26 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class DeleteContent : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the content id:" << endl;
|
||||
string contentId;
|
||||
cin >> contentId;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["contentType"] = "gta5mission";
|
||||
map["contentId"] = contentId;
|
||||
map["deleted"] = "true";
|
||||
|
||||
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/SetDeleted", map);
|
||||
}
|
||||
};
|
||||
|
||||
DeleteContent g_delete_content("deletecontent");
|
110
src/commands/prod.ros.rockstargames.com/UGC/QueryContent.cpp
Normal file
110
src/commands/prod.ros.rockstargames.com/UGC/QueryContent.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class QueryContent : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
enum QueryType {
|
||||
GetLatestVersionByContentId = 1,
|
||||
GetMyBookmarkedContent,
|
||||
GetMyContent,
|
||||
GetRecentlyCreatedContent,
|
||||
GetMyRecentlyPlayedContent,
|
||||
GetFriendContent,
|
||||
GetTopRatedContent
|
||||
};
|
||||
|
||||
QueryType getQueryType(const vector<string>& args) {
|
||||
if (args.empty()) {
|
||||
cout << "Select one of the following query names:" << endl;
|
||||
cout << "(1) GetLatestVersionByContentId" << endl;
|
||||
cout << "(2) GetMyBookmarkedContent" << endl;
|
||||
cout << "(3) GetMyContent" << endl;
|
||||
cout << "(4) GetRecentlyCreatedContent" << endl;
|
||||
cout << "(5) GetMyRecentlyPlayedContent" << endl;
|
||||
cout << "(6) GetFriendContent" << endl;
|
||||
cout << "(7) GetTopRatedContent" << endl;
|
||||
|
||||
int type;
|
||||
cin >> type;
|
||||
|
||||
return static_cast<QueryType>(type);
|
||||
}
|
||||
else {
|
||||
return static_cast<QueryType>(stoi(args[0]));
|
||||
}
|
||||
}
|
||||
|
||||
string getQueryName(QueryType type) {
|
||||
switch (type) {
|
||||
case GetLatestVersionByContentId:
|
||||
return "GetLatestVersionByContentId";
|
||||
case GetMyBookmarkedContent:
|
||||
return "GetMyBookmarkedContent";
|
||||
case GetMyContent:
|
||||
return "GetMyContent";
|
||||
case GetRecentlyCreatedContent:
|
||||
return "GetRecentlyCreatedContent";
|
||||
case GetMyRecentlyPlayedContent:
|
||||
return "GetMyRecentlyPlayedContent";
|
||||
case GetFriendContent:
|
||||
return "GetFriendContent";
|
||||
case GetTopRatedContent:
|
||||
return "GetTopRatedContent";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
string contentId;
|
||||
string queryName;
|
||||
string count;
|
||||
|
||||
map<string, string> params;
|
||||
params["ticket"] = TICKET;
|
||||
params["queryName"] = queryName;
|
||||
|
||||
QueryType queryType = getQueryType(args);
|
||||
params["queryName"] = getQueryName(queryType);
|
||||
|
||||
if (!args.empty())
|
||||
contentId = args[1];
|
||||
else if (queryType == QueryType::GetLatestVersionByContentId)
|
||||
{
|
||||
cout << "Specify the contentId:" << endl;
|
||||
cin >> contentId;
|
||||
}
|
||||
|
||||
switch (queryType) {
|
||||
case GetLatestVersionByContentId:
|
||||
|
||||
params["contentType"] = "gta5mission";
|
||||
params["queryParams"] = "{contentids:[\"" + contentId + "\"], lang: ['en', 'fr', 'de', 'it', 'es', 'pt', 'pl', 'ru', 'es-mx'] }";
|
||||
params["offset"] = "0";
|
||||
params["count"] = "1";
|
||||
break;
|
||||
case GetMyBookmarkedContent:
|
||||
case GetMyContent:
|
||||
case GetRecentlyCreatedContent:
|
||||
case GetMyRecentlyPlayedContent:
|
||||
case GetFriendContent:
|
||||
case GetTopRatedContent:
|
||||
cout << "Specify the count:" << endl;
|
||||
cin >> count;
|
||||
|
||||
params["contentType"] = "gta5mission";
|
||||
params["queryParams"] = "{lang:['de','en','fr','it','es','pt','pl','ru','es-mx']}";
|
||||
params["offset"] = "0";
|
||||
params["count"] = count;
|
||||
break;
|
||||
}
|
||||
|
||||
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/QueryContent", params);
|
||||
}
|
||||
};
|
||||
|
||||
QueryContent g_query_content("querycontent");
|
@ -0,0 +1,30 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class QueryContentCreators : command
|
||||
{
|
||||
// No clue for what this is used and why but GetByUserId seems to be the only queryName
|
||||
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the content creator RID:" << endl; // TODO support multiple
|
||||
string contentCreators;
|
||||
cin >> contentCreators;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["contentType"] = "gta5mission";
|
||||
map["queryName"] = "GetByUserId";
|
||||
map["queryParams"] = "{userids:[" + contentCreators + "]}"; // You can input here multiple seperated by a comma
|
||||
map["offset"] = "0";
|
||||
map["count"] = "10";
|
||||
|
||||
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/QueryContentCreators", map);
|
||||
}
|
||||
};
|
||||
|
||||
QueryContentCreators g_query_content_creators("querycontentcreators");
|
@ -0,0 +1,30 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class SetBookmarked : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
cout << "Specify the content id:" << endl;
|
||||
string contentId;
|
||||
cin >> contentId;
|
||||
|
||||
cout << "Specify if it should be bookmarked (true/false):" << endl;
|
||||
string bookmarked;
|
||||
cin >> bookmarked;
|
||||
|
||||
map<string, string> map;
|
||||
map["ticket"] = TICKET;
|
||||
map["contentType"] = "gta5mission";
|
||||
map["contentId"] = contentId;
|
||||
map["bookmarked"] = bookmarked;
|
||||
|
||||
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/SetBookmarked", map);
|
||||
}
|
||||
};
|
||||
|
||||
SetBookmarked g_set_bookmarked("setbookmarked");
|
@ -0,0 +1,21 @@
|
||||
#include "../../../command.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class SearchMission : command
|
||||
{
|
||||
using command::command;
|
||||
|
||||
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_SCAPI_AMC; }
|
||||
|
||||
virtual string execute(const vector<string>& args)
|
||||
{
|
||||
map<string, string> map;
|
||||
map["title"] = "gtav";
|
||||
map["platform"] = "pc";
|
||||
map["includeCommentCount"] = "false";
|
||||
|
||||
return run("https://scapi.rockstargames.com/search/mission", map);
|
||||
}
|
||||
};
|
||||
|
||||
SearchMission g_search_mission("searchmission");
|
2
src/common.hpp
Normal file
2
src/common.hpp
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#include "command.hpp"
|
157
src/main.cpp
Normal file
157
src/main.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <format>
|
||||
#include "command.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "cpr/cpr.h"
|
||||
#include <pugixml.hpp>
|
||||
#include "AccountInfo.hpp"
|
||||
#include <botan_all.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef _WIN32
|
||||
uintptr_t GetModuleBaseAddress(DWORD procId, const char* modName)
|
||||
{
|
||||
uintptr_t modBaseAddr = 0;
|
||||
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
|
||||
if (hSnap != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
MODULEENTRY32 modEntry;
|
||||
modEntry.dwSize = sizeof(modEntry);
|
||||
if (Module32First(hSnap, &modEntry))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!strcmp(modEntry.szModule, modName))
|
||||
{
|
||||
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
|
||||
break;
|
||||
}
|
||||
} while (Module32Next(hSnap, &modEntry));
|
||||
}
|
||||
}
|
||||
CloseHandle(hSnap);
|
||||
return modBaseAddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
AccountInfo GetAccountInfo()
|
||||
{
|
||||
string data = command::get(hash<string>()("getaccountinfo"))->execute({});
|
||||
pugi::xml_document doc;
|
||||
AccountInfo accountInfo{};
|
||||
|
||||
if (doc.load_string(data.c_str()))
|
||||
{
|
||||
auto path = doc.select_node("//Response/RockstarAccount");
|
||||
auto node = path.node();
|
||||
|
||||
accountInfo.m_rockstar_id = node.child("RockstarId").text().as_uint();
|
||||
accountInfo.m_age = node.child("Age").text().as_int();
|
||||
accountInfo.m_avatar_url = node.child("AvatarUrl").text().as_string();
|
||||
accountInfo.m_country_code = node.child("CountryCode").text().as_string();
|
||||
accountInfo.m_date_of_birth = node.child("Dob").text().as_string();
|
||||
accountInfo.m_email = node.child("Email").text().as_string();
|
||||
accountInfo.m_is_approx_dob = node.child("IsApproxDob").text().as_bool(); // TODO
|
||||
accountInfo.m_language_code = node.child("LanguageCode").text().as_string();
|
||||
accountInfo.m_nickname = node.child("Nickname").text().as_string();
|
||||
accountInfo.m_last_portal_login_date = node.child("LastPortalLoginDate").text().as_string();
|
||||
}
|
||||
|
||||
return accountInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* <Services Count="12">
|
||||
<S ep="/Accounts.svc/" h="accounts-prod.ros.rockstargames.com" />
|
||||
<S ep="/Feed.asmx/" h="feed-gta5-prod.ros.rockstargames.com" />
|
||||
<S ep="/Telemetry.asmx/SubmitCompressed" h="prod.telemetry.ros.rockstargames.com" />
|
||||
<S ep="/Telemetry.asmx/SubmitRealTime" h="prod.telemetry.ros.rockstargames.com" />
|
||||
<S ep="conductor" h="conductor-prod.ros.rockstargames.com" />
|
||||
<S ep="/ProfileStats.asmx/" h="ps-gta5-prod.ros.rockstargames.com" />
|
||||
<S ep="/matchmaking.asmx/" h="mm-gta5-prod.ros.rockstargames.com" />
|
||||
<S ep="/ugc.asmx/" h="ugc-gta5-prod.ros.rockstargames.com" />
|
||||
<S ep="/Presence.asmx/" h="prs-gta5-prod.ros.rockstargames.com" />
|
||||
<S ep="/Inbox.asmx/" h="inbox-gta5-prod.ros.rockstargames.com" />
|
||||
<S ep="/Clans.asmx/" h="crews-gta5-prod.ros.rockstargames.com" />
|
||||
<S ep="/cloudservices/members//GTA5/saves/mpstats" h="cs-gta5-prod.ros.rockstargames.com" />
|
||||
</Services>
|
||||
*/
|
||||
|
||||
int main()
|
||||
{
|
||||
string endpoint;
|
||||
|
||||
#ifdef _WIN64
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
|
||||
HWND hwnd = FindWindowA(NULL, "Grand Theft Auto V");
|
||||
if (hwnd)
|
||||
{
|
||||
DWORD pid;
|
||||
GetWindowThreadProcessId(hwnd, &pid);
|
||||
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
|
||||
uintptr_t base_address = GetModuleBaseAddress(pid, "GTA5.exe");
|
||||
|
||||
char ticket[208]{};
|
||||
ReadProcessMemory(phandle, (void*)(base_address + 0x2E7B300), &ticket, 208, 0);
|
||||
|
||||
char session_ticket[88]{};
|
||||
ReadProcessMemory(phandle, (void*)(base_address + 0x2E7B300 + 0x200), &session_ticket, 88, 0);
|
||||
|
||||
unsigned char session_key[16]{};
|
||||
ReadProcessMemory(phandle, (void*)(base_address + 0x2E7B300 + 0x608), &session_key, 16, 0);
|
||||
|
||||
TICKET = ticket;
|
||||
SESSION_TICKET = string(session_ticket, 88);
|
||||
SESSION_KEY = Botan::base64_encode(reinterpret_cast<const Botan::byte*>(session_key), sizeof(session_key));
|
||||
}
|
||||
#endif
|
||||
|
||||
cout << "Help:" << endl;
|
||||
for (auto& it : g_commands) {
|
||||
cout << it.second->get_name() << endl;
|
||||
}
|
||||
|
||||
if (!TICKET.empty())
|
||||
{
|
||||
cout << "Ticket " << TICKET << endl;
|
||||
cout << "Session Ticket " << SESSION_TICKET << endl;
|
||||
cout << "Session Key " << SESSION_KEY << endl;
|
||||
|
||||
cout << "Enter the endpoint:" << endl;
|
||||
cin >> ws >> endpoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
string response = command::get(hash<string>()("createticket"))->execute({});
|
||||
|
||||
if (TICKET.length() > 20)
|
||||
{
|
||||
cout << "Ticket " << TICKET << endl;
|
||||
cout << "Session Ticket " << SESSION_TICKET << endl;
|
||||
cout << "Session Key " << SESSION_KEY << endl;
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
transform(endpoint.begin(), endpoint.end(), endpoint.begin(), ::tolower);
|
||||
static command* command = command::get(hash<string>()(endpoint));
|
||||
|
||||
if (command) {
|
||||
cout << command->execute({ }) << endl;
|
||||
}
|
||||
cout << "Enter the endpoint:" << endl;
|
||||
cin >> ws >> endpoint;
|
||||
command = command::get(hash<string>()(endpoint));
|
||||
}
|
||||
}
|
277
src/ros_crypt.cpp
Normal file
277
src/ros_crypt.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
#include "ros_crypt.hpp"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <format>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
ROSCryptoState::ROSCryptoState(const string& platformKey)
|
||||
{
|
||||
Botan::secure_vector<uint8_t> platformStr = Botan::base64_decode(platformKey);
|
||||
|
||||
memcpy(m_rc4Key, &platformStr[1], sizeof(m_rc4Key));
|
||||
memcpy(m_xorKey, &platformStr[33], sizeof(m_xorKey));
|
||||
memcpy(m_hashKey, &platformStr[49], sizeof(m_hashKey));
|
||||
|
||||
m_rc4 = Botan::StreamCipher::create("RC4")->clone();
|
||||
m_rc4->set_key(m_rc4Key, sizeof(m_rc4Key));
|
||||
m_rc4->cipher1(m_xorKey, sizeof(m_xorKey));
|
||||
m_rc4->set_key(m_rc4Key, sizeof(m_rc4Key));
|
||||
m_rc4->cipher1(m_hashKey, sizeof(m_hashKey));
|
||||
|
||||
delete m_rc4;
|
||||
}
|
||||
|
||||
ROSCryptoState::~ROSCryptoState()
|
||||
{
|
||||
delete m_rc4;
|
||||
}
|
||||
|
||||
const uint8_t* ROSCryptoState::GetXorKey() const
|
||||
{
|
||||
return m_xorKey;
|
||||
}
|
||||
|
||||
const uint8_t* ROSCryptoState::GetHashKey() const
|
||||
{
|
||||
return m_hashKey;
|
||||
}
|
||||
|
||||
string ROSCrypt::DecryptROSData(const char* data, size_t size, const string& sessionKey)
|
||||
{
|
||||
auto cryptoState = m_cryptoState.get();
|
||||
|
||||
uint8_t rc4Key[16];
|
||||
|
||||
bool hasSecurity = (!sessionKey.empty());
|
||||
|
||||
uint8_t sessKey[16];
|
||||
|
||||
if (hasSecurity)
|
||||
{
|
||||
auto keyData = Botan::base64_decode(sessionKey.data());
|
||||
memcpy(sessKey, keyData.data(), sizeof(sessKey));
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(rc4Key); i++)
|
||||
{
|
||||
rc4Key[i] = data[i] ^ cryptoState->GetXorKey()[i];
|
||||
|
||||
if (hasSecurity)
|
||||
{
|
||||
rc4Key[i] ^= sessKey[i];
|
||||
}
|
||||
}
|
||||
|
||||
Botan::StreamCipher* rc4 = Botan::StreamCipher::create("RC4")->clone();
|
||||
rc4->set_key(rc4Key, sizeof(rc4Key));
|
||||
|
||||
uint8_t blockSizeData[4];
|
||||
uint8_t blockSizeDataLE[4];
|
||||
rc4->cipher(reinterpret_cast<const uint8_t*>(&data[16]), blockSizeData, 4);
|
||||
|
||||
blockSizeDataLE[3] = blockSizeData[0];
|
||||
blockSizeDataLE[2] = blockSizeData[1];
|
||||
blockSizeDataLE[1] = blockSizeData[2];
|
||||
blockSizeDataLE[0] = blockSizeData[3];
|
||||
|
||||
uint32_t blockSize = (*(uint32_t*)&blockSizeDataLE) + 20;
|
||||
|
||||
vector<uint8_t> blockData(blockSize);
|
||||
|
||||
stringstream result;
|
||||
|
||||
size_t start = 20;
|
||||
|
||||
while (start < size)
|
||||
{
|
||||
int end = min(size, start + blockSize);
|
||||
|
||||
end -= 20;
|
||||
|
||||
int thisLen = end - start;
|
||||
|
||||
if (thisLen < 0)
|
||||
{
|
||||
return string{data, size};
|
||||
}
|
||||
|
||||
rc4->cipher(reinterpret_cast<const uint8_t*>(&data[start]), &blockData[0], thisLen);
|
||||
|
||||
result << string(reinterpret_cast<const char*>(&blockData[0]), thisLen);
|
||||
|
||||
start += blockSize;
|
||||
}
|
||||
|
||||
delete rc4;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
string ROSCrypt::EncryptROSData(const string& input, const string& sessionKey)
|
||||
{
|
||||
auto state = m_cryptoState.get();
|
||||
stringstream output;
|
||||
|
||||
bool hasSecurity = (!sessionKey.empty());
|
||||
|
||||
uint8_t sessKey[16];
|
||||
|
||||
if (hasSecurity)
|
||||
{
|
||||
auto keyData = Botan::base64_decode(sessionKey);
|
||||
memcpy(sessKey, keyData.data(), sizeof(sessKey));
|
||||
}
|
||||
|
||||
uint8_t rc4Key[16];
|
||||
|
||||
Botan::AutoSeeded_RNG rng;
|
||||
rng.randomize(rc4Key, sizeof(rc4Key));
|
||||
|
||||
for (int i = 0; i < sizeof(rc4Key); i++)
|
||||
{
|
||||
char thisChar = rc4Key[i] ^ state->GetXorKey()[i];
|
||||
|
||||
output << string(&thisChar, 1);
|
||||
|
||||
if (hasSecurity)
|
||||
{
|
||||
rc4Key[i] ^= sessKey[i];
|
||||
}
|
||||
}
|
||||
|
||||
Botan::StreamCipher* rc4 = Botan::StreamCipher::create("RC4")->clone();
|
||||
rc4->set_key(rc4Key, sizeof(rc4Key));
|
||||
|
||||
vector<uint8_t> inData(input.size());
|
||||
memcpy(&inData[0], input.c_str(), inData.size());
|
||||
|
||||
rc4->encipher(inData);
|
||||
|
||||
output << string(reinterpret_cast<const char*>(&inData[0]), inData.size());
|
||||
|
||||
string tempContent = output.str();
|
||||
|
||||
Botan::Buffered_Computation* sha1;
|
||||
|
||||
if (!hasSecurity)
|
||||
{
|
||||
sha1 = Botan::HashFunction::create("SHA1")->clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto hmac = Botan::MessageAuthenticationCode::create("HMAC(SHA1)")->clone();
|
||||
hmac->set_key(rc4Key, sizeof(rc4Key));
|
||||
|
||||
sha1 = hmac;
|
||||
}
|
||||
|
||||
sha1->update(reinterpret_cast<const uint8_t*>(tempContent.c_str()), tempContent.size());
|
||||
sha1->update(state->GetHashKey(), 16);
|
||||
|
||||
auto hashData = sha1->final();
|
||||
|
||||
delete rc4;
|
||||
delete sha1;
|
||||
|
||||
return tempContent + string(reinterpret_cast<const char*>(&hashData[0]), hashData.size());
|
||||
}
|
||||
|
||||
string ROSCrypt::url_encode(const string& value)
|
||||
{
|
||||
ostringstream escaped;
|
||||
escaped.fill('0');
|
||||
escaped << hex;
|
||||
|
||||
for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i)
|
||||
{
|
||||
string::value_type c = (*i);
|
||||
if (((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '_' || c == '.' || c == '~') && c != '+')
|
||||
{
|
||||
escaped << c;
|
||||
}
|
||||
else if (c == ' ')
|
||||
{
|
||||
escaped << '+';
|
||||
}
|
||||
else
|
||||
{
|
||||
escaped << '%' << setw(2) << ((int)(uint8_t)c) << setw(0);
|
||||
}
|
||||
}
|
||||
|
||||
return string(escaped.str().c_str());
|
||||
}
|
||||
|
||||
string ROSCrypt::ex_url_encode(const string& value)
|
||||
{
|
||||
ostringstream escaped;
|
||||
escaped.fill('0');
|
||||
escaped << hex;
|
||||
|
||||
for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i)
|
||||
{
|
||||
string::value_type c = (*i);
|
||||
if (((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '_' || c == '.' || c == '~') || c == '+')
|
||||
{
|
||||
escaped << c;
|
||||
}
|
||||
else if (c == ' ')
|
||||
{
|
||||
escaped << '+';
|
||||
}
|
||||
else
|
||||
{
|
||||
escaped << uppercase << '%' << setw(2) << ((int)(uint8_t)c) << setw(0);
|
||||
}
|
||||
}
|
||||
|
||||
return string(escaped.str().c_str());
|
||||
}
|
||||
|
||||
string ROSCrypt::BuildPostString(const map<string, string>& fields)
|
||||
{
|
||||
stringstream retval;
|
||||
|
||||
for (auto& field : fields)
|
||||
{
|
||||
retval << field.first << "=" << url_encode(field.second) << "&";
|
||||
}
|
||||
|
||||
string str = string(retval.str().c_str());
|
||||
return str.substr(0, str.length() - 1);
|
||||
}
|
||||
|
||||
string ROSCrypt::GetROSVersionString()
|
||||
{
|
||||
string baseString;
|
||||
if (m_launcher)
|
||||
baseString = "e=1,t=launcher,p=pcros,v=11";
|
||||
else
|
||||
baseString = "e=1,t=gta5,p=pcros,v=11";
|
||||
|
||||
vector<uint8_t> xorBuffer(baseString.length() + 4);
|
||||
|
||||
if (m_launcher)
|
||||
{
|
||||
*(uint32_t*)&xorBuffer[0] = 0xC5C5C5C5;
|
||||
|
||||
for (int i = 4; i < xorBuffer.size(); i++)
|
||||
{
|
||||
xorBuffer[i] = baseString[i - 4] ^ 0xC5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*(uint32_t*)&xorBuffer[0] = 0xCDCDCDCD;
|
||||
|
||||
for (int i = 4; i < xorBuffer.size(); i++)
|
||||
{
|
||||
xorBuffer[i] = baseString[i - 4] ^ 0xCD;
|
||||
}
|
||||
}
|
||||
|
||||
string base64str = Botan::base64_encode(reinterpret_cast<const Botan::byte*>(&xorBuffer[0]), xorBuffer.size());
|
||||
|
||||
return format("ros {}", base64str);
|
||||
}
|
106
src/ros_crypt.hpp
Normal file
106
src/ros_crypt.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include "botan_all.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class ROSCryptoState
|
||||
{
|
||||
private:
|
||||
Botan::StreamCipher* m_rc4;
|
||||
uint8_t m_rc4Key[32];
|
||||
uint8_t m_xorKey[16];
|
||||
uint8_t m_hashKey[16];
|
||||
|
||||
public:
|
||||
ROSCryptoState(const string& platformKey);
|
||||
~ROSCryptoState();
|
||||
|
||||
const uint8_t* GetXorKey() const;
|
||||
const uint8_t* GetHashKey() const;
|
||||
};
|
||||
|
||||
class ROSCrypt
|
||||
{
|
||||
public:
|
||||
constexpr ROSCrypt(const bool launcher) : m_launcher(launcher)
|
||||
{
|
||||
constexpr const char* launcherPlatformKey = "C6fU6TQTPgUVmy3KIB5g8ElA7DrenVpGogSZjsh+lqJaQHqv4Azoctd/v4trfX6cBjbEitUKBG/hRINF4AhQqcg=";
|
||||
constexpr const char* platformKey = "C4pWJwWIKGUxcHd69eGl2AOwH2zrmzZAoQeHfQFcMelybd32QFw9s10px6k0o75XZeB5YsI9Q9TdeuRgdbvKsxc=";
|
||||
|
||||
m_cryptoState = make_unique<ROSCryptoState>(launcher ? launcherPlatformKey : platformKey);
|
||||
}
|
||||
|
||||
string EncryptROSData(const string& input, const string& sessionKey = "");
|
||||
string DecryptROSData(const char* data, size_t size, const string& sessionKey);
|
||||
|
||||
string url_encode(const string& value);
|
||||
string ex_url_encode(const string& value);
|
||||
|
||||
string BuildPostString(const map<string, string>& fields);
|
||||
|
||||
string GetROSVersionString();
|
||||
|
||||
template<typename TAlloc>
|
||||
auto HeadersHmac(const vector<uint8_t, TAlloc>& challenge, const char* method, const string& path, const string& sessionKey, const string& sessionTicket);
|
||||
|
||||
private:
|
||||
unique_ptr<ROSCryptoState> m_cryptoState;
|
||||
bool m_launcher;
|
||||
};
|
||||
|
||||
// TODO compiler error when in .cpp?
|
||||
template<typename TAlloc>
|
||||
inline auto ROSCrypt::HeadersHmac(const vector<uint8_t, TAlloc>& challenge, const char* method, const string& path, const string& sessionKey, const string& sessionTicket)
|
||||
{
|
||||
auto hmac = unique_ptr<Botan::MessageAuthenticationCode>(Botan::MessageAuthenticationCode::create("HMAC(SHA1)")->clone());
|
||||
|
||||
auto cryptoState = m_cryptoState.get();
|
||||
|
||||
// set the key
|
||||
uint8_t hmacKey[16];
|
||||
|
||||
// xor the RC4 key with the platform key (and optionally the session key)
|
||||
auto rc4Xor = Botan::base64_decode(sessionKey);
|
||||
|
||||
for (int i = 0; i < sizeof(hmacKey); i++)
|
||||
{
|
||||
hmacKey[i] = rc4Xor[i] ^ cryptoState->GetXorKey()[i];
|
||||
}
|
||||
|
||||
hmac->set_key(hmacKey, sizeof(hmacKey));
|
||||
|
||||
// method
|
||||
hmac->update(method);
|
||||
hmac->update(0);
|
||||
|
||||
// path
|
||||
hmac->update(path);
|
||||
hmac->update(0);
|
||||
|
||||
// ros-SecurityFlags
|
||||
hmac->update("239");
|
||||
hmac->update(0);
|
||||
|
||||
// ros-SessionTicket
|
||||
hmac->update(sessionTicket);
|
||||
hmac->update(0);
|
||||
|
||||
// ros-Challenge
|
||||
hmac->update(Botan::base64_encode(challenge));
|
||||
hmac->update(0);
|
||||
|
||||
// platform hash key
|
||||
hmac->update(cryptoState->GetHashKey(), 16);
|
||||
|
||||
// set the request header
|
||||
auto hmacValue = hmac->final();
|
||||
|
||||
return hmacValue;
|
||||
}
|
Loading…
Reference in New Issue
Block a user