feat(Api): Implemented SCUI Api (#712)
* feat(Api): Async joining via rid joiner * feat(cmake): disable cpr tests Co-authored-by: Yimura <24669514+Yimura@users.noreply.github.com>
This commit is contained in:
parent
792d765ffa
commit
551c165367
@ -13,6 +13,7 @@ include(scripts/minhook.cmake)
|
||||
include(scripts/g3log.cmake)
|
||||
include(scripts/pugixml.cmake)
|
||||
include(scripts/json.cmake)
|
||||
include(scripts/cpr.cmake)
|
||||
|
||||
message("\nFetching custom modules")
|
||||
include(scripts/imgui.cmake)
|
||||
@ -44,7 +45,7 @@ target_include_directories(YimMenu PRIVATE
|
||||
)
|
||||
|
||||
target_precompile_headers(YimMenu PRIVATE "${SRC_DIR}/common.hpp")
|
||||
target_link_libraries(YimMenu PRIVATE pugixml minhook g3log imgui)
|
||||
target_link_libraries(YimMenu PRIVATE pugixml minhook g3log imgui cpr)
|
||||
|
||||
# Warnings as errors
|
||||
set_property(TARGET YimMenu PROPERTY COMPILE_WARNING_AS_ERROR ON)
|
||||
|
11
scripts/cpr.cmake
Normal file
11
scripts/cpr.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
include(FetchContent)
|
||||
|
||||
set(BUILD_CPR_TESTS OFF CACHE INTERNAL "")
|
||||
FetchContent_Declare(
|
||||
cpr
|
||||
GIT_REPOSITORY https://github.com/libcpr/cpr.git
|
||||
GIT_TAG 1986262ba4e0cb052161e9e7919aef5ef08217f0
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
message("cpr")
|
||||
FetchContent_MakeAvailable(cpr)
|
@ -27,6 +27,7 @@
|
||||
#include "services/player_database/player_database_service.hpp"
|
||||
#include "services/hotkey/hotkey_service.hpp"
|
||||
#include "services/matchmaking/matchmaking_service.hpp"
|
||||
#include "services/api/api_service.hpp"
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
{
|
||||
@ -38,7 +39,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
g_hmodule = hmod;
|
||||
g_main_thread = CreateThread(nullptr, 0, [](PVOID) -> DWORD
|
||||
{
|
||||
while (!FindWindow("grcWindow", "Grand Theft Auto V"))
|
||||
while (!FindWindow("grcWindow", nullptr))
|
||||
std::this_thread::sleep_for(100ms);
|
||||
|
||||
std::filesystem::path base_dir = std::getenv("appdata");
|
||||
@ -95,6 +96,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
auto player_database_service_instance = std::make_unique<player_database_service>();
|
||||
auto hotkey_service_instance = std::make_unique<hotkey_service>();
|
||||
auto matchmaking_service_instance = std::make_unique<matchmaking_service>();
|
||||
auto api_service_instance = std::make_unique<api_service>();
|
||||
LOG(INFO) << "Registered service instances...";
|
||||
|
||||
g_script_mgr.add_script(std::make_unique<script>(&gui::script_func, "GUI", false));
|
||||
@ -147,6 +149,8 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
|
||||
matchmaking_service_instance.reset();
|
||||
LOG(INFO) << "Matchmaking Service reset.";
|
||||
player_database_service_instance.reset();
|
||||
LOG(INFO) << "API Service reset.";
|
||||
api_service_instance.reset();
|
||||
LOG(INFO) << "Player Database Service reset.";
|
||||
script_patcher_service_instance.reset();
|
||||
LOG(INFO) << "Script Patcher Service reset.";
|
||||
|
@ -636,6 +636,12 @@ namespace big
|
||||
m_chat_data = ptr.add(3).rip().as<ChatData**>();
|
||||
});
|
||||
|
||||
// Social Club Info
|
||||
main_batch.add("SCI", "48 8B D3 48 8D 4C 24 ? 48 69 D2", [this](memory::handle ptr)
|
||||
{
|
||||
m_sc_info = ptr.sub(4).rip().as<ScInfo*>();
|
||||
});
|
||||
|
||||
// Create Script Handler
|
||||
main_batch.add("CSH", "48 8D 05 ? ? ? ? 4C 8D 0D ? ? ? ? 41 83 C8 FF 48 89 03 89 53 70 88 53 74 4C 89 4B 68 48 89 93", [this](memory::handle ptr)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "common.hpp"
|
||||
#include "base/HashTable.hpp"
|
||||
#include "socialclub/ScInfo.hpp"
|
||||
#include "function_types.hpp"
|
||||
#include "gta/fwddec.hpp"
|
||||
#include "gta/replay.hpp"
|
||||
@ -68,6 +69,7 @@ namespace big
|
||||
functions::write_player_game_state_data_node m_write_player_game_state_data_node{};
|
||||
|
||||
ChatData** m_chat_data;
|
||||
ScInfo* m_sc_info;
|
||||
FriendRegistry* m_friend_registry{};
|
||||
|
||||
functions::get_screen_coords_for_world_coords m_get_screen_coords_for_world_coords{};
|
||||
|
63
src/services/api/api_service.cpp
Normal file
63
src/services/api/api_service.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "api_service.hpp"
|
||||
#include "pointers.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
|
||||
api_service::api_service()
|
||||
{
|
||||
g_api_service = this;
|
||||
}
|
||||
|
||||
api_service::~api_service()
|
||||
{
|
||||
g_api_service = nullptr;
|
||||
}
|
||||
|
||||
bool api_service::get_rid_from_username(std::string_view username, uint64_t& result)
|
||||
{
|
||||
cpr::Response response = cpr::Post(
|
||||
cpr::Url{ "https://scui.rockstargames.com/api/friend/accountsearch" },
|
||||
cpr::Header{ {"Authorization", AUTHORIZATION_TICKET) }, { "X-Requested-With", "XMLHttpRequest"}},
|
||||
cpr::Body{ { std::format("searchNickname={}", username) } });
|
||||
|
||||
if (response.status_code == 200)
|
||||
{
|
||||
nlohmann::json obj = nlohmann::json::parse(response.text);
|
||||
if (obj["Total"] > 0 && username.compare(obj["Accounts"].at(0)["Nickname"]) == 0)
|
||||
{
|
||||
result = obj["Accounts"].at(0)["RockstarId"];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool api_service::get_username_from_rid(uint64_t rid, std::string& result)
|
||||
{
|
||||
cpr::Response response = cpr::Post(
|
||||
cpr::Url{ "https://scui.rockstargames.com/api/friend/getprofile" },
|
||||
cpr::Header{ {"Authorization", AUTHORIZATION_TICKET) }, { "X-Requested-With", "XMLHttpRequest"}, {"Content-Type", "application/json"} },
|
||||
cpr::Body{ { std::format(R"({{"RockstarId":"{}"}})", rid) } });
|
||||
|
||||
if (response.status_code == 200)
|
||||
{
|
||||
nlohmann::json obj = nlohmann::json::parse(response.text);
|
||||
result = obj["Accounts"].at(0)["RockstarAccount"]["Name"];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool api_service::send_socialclub_message(uint64_t rid, std::string_view message)
|
||||
{
|
||||
cpr::Response response = cpr::Post(
|
||||
cpr::Url{ "https://scui.rockstargames.com/api/messaging/sendmessage" },
|
||||
cpr::Header{ {"Authorization", AUTHORIZATION_TICKET) }, { "X-Requested-With", "XMLHttpRequest"}, {"Content-Type", "application/json"} },
|
||||
cpr::Body{ { std::format(R"({{"env":"prod","title":"gta5","version":11,"recipientRockstarId":"{}","messageText":"{}"}})", rid, message) } });
|
||||
|
||||
return response.status_code == 200;
|
||||
}
|
||||
}
|
30
src/services/api/api_service.hpp
Normal file
30
src/services/api/api_service.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "pointers.hpp"
|
||||
#include <cpr/cpr.h>
|
||||
#define AUTHORIZATION_TICKET std::format("SCAUTH val=\"{}\"", get_ticket()
|
||||
|
||||
namespace big
|
||||
{
|
||||
class api_service
|
||||
{
|
||||
public:
|
||||
api_service();
|
||||
~api_service();
|
||||
|
||||
// Returns true if an valid profile matching his username has been found
|
||||
bool get_rid_from_username(std::string_view username, uint64_t& result);
|
||||
|
||||
// Returns true if an valid profile matching his rid has been found
|
||||
bool get_username_from_rid(uint64_t rid, std::string& result);
|
||||
|
||||
// Returns true if the message has been successfully sended to the target
|
||||
bool send_socialclub_message(uint64_t rid, std::string_view message);
|
||||
private:
|
||||
inline std::string get_ticket()
|
||||
{
|
||||
return g_pointers->m_sc_info->m_ticket;
|
||||
}
|
||||
};
|
||||
|
||||
inline api_service* g_api_service;
|
||||
}
|
@ -10,6 +10,9 @@
|
||||
#include "pointers.hpp"
|
||||
#include "services/players/player_service.hpp"
|
||||
#include "services/player_database/player_database_service.hpp"
|
||||
#include "services/api/api_service.hpp"
|
||||
#include "thread_pool.hpp"
|
||||
#include "fiber_pool.hpp"
|
||||
|
||||
namespace big::session
|
||||
{
|
||||
@ -72,7 +75,7 @@ namespace big::session
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
inline void join_by_rockstar_id(uint64_t rid)
|
||||
{
|
||||
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) != 0 ||
|
||||
@ -101,6 +104,23 @@ namespace big::session
|
||||
g_notification_service->push_error("RID Joiner", "Target player is offline?");
|
||||
}
|
||||
|
||||
inline void join_by_username(std::string username)
|
||||
{
|
||||
g_thread_pool->push([username]
|
||||
{
|
||||
uint64_t rid;
|
||||
if (g_api_service->get_rid_from_username(username, rid))
|
||||
{
|
||||
g_fiber_pool->queue_job([rid]
|
||||
{
|
||||
join_by_rockstar_id(rid);
|
||||
});
|
||||
return;
|
||||
}
|
||||
g_notification_service->push_error("RID Joiner", "Target player is offline?");
|
||||
});
|
||||
}
|
||||
|
||||
inline void add_infraction(player_ptr player, Infraction infraction)
|
||||
{
|
||||
auto plyr = g_player_database_service->get_or_create_player(player);
|
||||
|
@ -16,11 +16,18 @@ namespace big
|
||||
{
|
||||
static uint64_t rid = 0;
|
||||
ImGui::InputScalar("Input RID", ImGuiDataType_U64, &rid);
|
||||
components::button("Join RID", []
|
||||
components::button("Join by RID", []
|
||||
{
|
||||
session::join_by_rockstar_id(rid);
|
||||
});
|
||||
|
||||
static char username[20];
|
||||
ImGui::InputText("Input Username", username, sizeof(username));
|
||||
if (components::button("Join by Username"))
|
||||
{
|
||||
session::join_by_username(username);
|
||||
};
|
||||
|
||||
static char base64[500]{};
|
||||
ImGui::InputText("Session Info", base64, sizeof(base64));
|
||||
components::button("Join Session Info", []
|
||||
|
Reference in New Issue
Block a user