From d97e23e11121d41a014fb452ecdd236ee389e0c3 Mon Sep 17 00:00:00 2001 From: rjindael Date: Thu, 7 Sep 2023 15:45:19 -0700 Subject: [PATCH] feat: add discord rich presence integration code --- Kiseki.Patcher/Header/Discord.hpp | 21 ++++ Kiseki.Patcher/Header/Hooks/CRoblox.hpp | 4 + Kiseki.Patcher/Source/Discord.cpp | 122 ++++++++++++++++++++++++ Kiseki.Patcher/Source/Hooks/CRoblox.cpp | 4 + Kiseki.Patcher/Source/main.cpp | 8 ++ 5 files changed, 159 insertions(+) create mode 100644 Kiseki.Patcher/Header/Discord.hpp create mode 100644 Kiseki.Patcher/Source/Discord.cpp diff --git a/Kiseki.Patcher/Header/Discord.hpp b/Kiseki.Patcher/Header/Discord.hpp new file mode 100644 index 0000000..c3d5523 --- /dev/null +++ b/Kiseki.Patcher/Header/Discord.hpp @@ -0,0 +1,21 @@ +#ifdef PLAYER + +#pragma once + +#include +#include +#include + +#include "Hooks/CRoblox.hpp" + +#include "Globals.hpp" + +class Discord { +public: + static void Initialize(const std::string joinScriptUrl); + static void Cleanup(); +private: + static void Update(); +}; + +#endif \ No newline at end of file diff --git a/Kiseki.Patcher/Header/Hooks/CRoblox.hpp b/Kiseki.Patcher/Header/Hooks/CRoblox.hpp index 06db5d0..6038f7a 100644 --- a/Kiseki.Patcher/Header/Hooks/CRoblox.hpp +++ b/Kiseki.Patcher/Header/Hooks/CRoblox.hpp @@ -7,6 +7,10 @@ #include "Globals.hpp" #include "Helpers.hpp" +#ifdef PLAYER +#include "Discord.hpp" +#endif + class CWorkspace; const auto CWorkspace__ExecUrlScript = (HRESULT(__stdcall*)(CWorkspace * workspace, LPCWSTR, VARIANTARG, VARIANTARG, VARIANTARG, VARIANTARG, LPVOID))ADDRESS_CWORKSPACE__EXECURLSCRIPT; diff --git a/Kiseki.Patcher/Source/Discord.cpp b/Kiseki.Patcher/Source/Discord.cpp new file mode 100644 index 0000000..df4ef3e --- /dev/null +++ b/Kiseki.Patcher/Source/Discord.cpp @@ -0,0 +1,122 @@ +#ifdef PLAYER + +#include "Discord.hpp" + +bool isRunning = false; +std::string username; +int placeId; + +void Discord::Initialize(const std::string joinScriptUrl) +{ + std::pair> parsed = Helpers::parseURL(joinScriptUrl); + + if (!parsed.first) + { + return; + } + + if (parsed.second["query"].empty()) + { + return; + } + + std::map query = Helpers::parseQueryString(parsed.second["query"]); + + if (query.find("ticket") == query.end()) + { + return; + } + + if (query.find("discord") == query.end()) + { + return; + } + + if (query["ticket"].empty()) + { + return; + } + + if (query["discord"] == "0") + { + return; + } + + // Get the username and placeId + std::pair response = Helpers::httpGet(Helpers::getBaseUrl() + std::string("/api/places/information?ticket=" + query["ticket"])); + if (!response.first) + { + return; + } + + rapidjson::Document document; + document.Parse(response.second.c_str()); + + if (document.HasParseError() || !document.HasMember("username") || !document.HasMember("placeId")) + { + return; + } + + username = document["username"].GetString(); + placeId = document["placeId"].GetInt(); + + Discord::Update(); + + // Run the updater + std::thread updater(Discord::Update); + updater.join(); +} + +void Discord::Update() +{ + isRunning = true; + + while (isRunning) + { + std::this_thread::sleep_for(std::chrono::milliseconds(60 * 1000)); + + std::string title = ""; + int size = 0; + int max = 0; + + // Get title, size, and max + std::pair response = Helpers::httpGet(Helpers::getBaseUrl() + std::string("/api/places/information?id=" + placeId)); + if (!response.first) + { + return; + } + + rapidjson::Document document; + document.Parse(response.second.c_str()); + + if (document.HasParseError() || !document.HasMember("title") || !document.HasMember("size") || !document.HasMember("max")) + { + return; + } + + title = document["title"].GetString(); + size = document["size"].GetInt(); + max = document["max"].GetInt(); + + DiscordRichPresence presence; + memset(&presence, 0, sizeof(presence)); + + presence.largeImageText = username.c_str(); + presence.largeImageKey = "logo"; + presence.smallImageText = "2011"; + presence.smallImageKey = "2011"; + + presence.details = title.c_str(); + presence.state = "In a game"; + presence.partySize = size; + presence.partyMax = max; + } +} + +void Discord::Cleanup() +{ + isRunning = false; + Discord_Shutdown(); +} + +#endif \ No newline at end of file diff --git a/Kiseki.Patcher/Source/Hooks/CRoblox.cpp b/Kiseki.Patcher/Source/Hooks/CRoblox.cpp index 7c73baa..5c7d0fa 100644 --- a/Kiseki.Patcher/Source/Hooks/CRoblox.cpp +++ b/Kiseki.Patcher/Source/Hooks/CRoblox.cpp @@ -79,6 +79,10 @@ void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this->m_bRunAutomated = TRUE; CCommandLineInfo__ParseLast(_this, bLast); + +#ifdef PLAYER + Discord::Initialize(Helpers::ws2s(joinScriptUrl)); +#endif } if (hasAuthenticationUrl && authenticationUrl.empty()) diff --git a/Kiseki.Patcher/Source/main.cpp b/Kiseki.Patcher/Source/main.cpp index 862d74a..6aadd36 100644 --- a/Kiseki.Patcher/Source/main.cpp +++ b/Kiseki.Patcher/Source/main.cpp @@ -3,6 +3,10 @@ #include "Globals.hpp" #include "Patcher.hpp" +#ifdef PLAYER +#include "Discord.hpp" +#endif + #include "Hooks/Http.hpp" #include "Hooks/Crypt.hpp" #include "Hooks/CRoblox.hpp" @@ -59,6 +63,10 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv if (ul_reason_for_call == DLL_PROCESS_DETACH) { curl_global_cleanup(); + +#ifdef PLAYER + Discord::Cleanup(); +#endif } return TRUE;