From 59244c75bb98edf01b0f7d7d665996554700808f Mon Sep 17 00:00:00 2001 From: Andreas Maerten <24669514+Yimura@users.noreply.github.com> Date: Mon, 30 Oct 2023 21:18:32 +0100 Subject: [PATCH] refactor: Implement HTTP client with proxy support (#2146) --- .clang-format | 1 - scripts/cpr.cmake | 2 +- src/http_client/http_client.cpp | 46 ++++++ src/http_client/http_client.hpp | 38 +++++ src/http_client/proxy_mgr.cpp | 149 ++++++++++++++++++ src/http_client/proxy_mgr.hpp | 42 +++++ src/http_client/proxy_protocols.hpp | 34 ++++ src/http_client/proxy_settings.hpp | 25 +++ src/main.cpp | 5 + src/services/api/api_service.cpp | 25 ++- .../creator_storage_service.cpp | 4 +- .../creator_storage_service.hpp | 2 +- src/services/gui/gui_service.hpp | 2 + .../translation_service.cpp | 15 +- src/views/settings/view_proxy_settings.cpp | 72 +++++++++ src/views/view.hpp | 1 + 16 files changed, 435 insertions(+), 28 deletions(-) create mode 100644 src/http_client/http_client.cpp create mode 100644 src/http_client/http_client.hpp create mode 100644 src/http_client/proxy_mgr.cpp create mode 100644 src/http_client/proxy_mgr.hpp create mode 100644 src/http_client/proxy_protocols.hpp create mode 100644 src/http_client/proxy_settings.hpp create mode 100644 src/views/settings/view_proxy_settings.cpp diff --git a/.clang-format b/.clang-format index 8c858c52..a0ec550c 100644 --- a/.clang-format +++ b/.clang-format @@ -19,7 +19,6 @@ AlwaysBreakTemplateDeclarations: 'Yes' BinPackArguments: 'false' BinPackParameters: 'true' BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Allman BreakBeforeTernaryOperators: 'false' BreakConstructorInitializers: AfterColon BreakInheritanceList: AfterColon diff --git a/scripts/cpr.cmake b/scripts/cpr.cmake index 6918b58f..e730fae2 100644 --- a/scripts/cpr.cmake +++ b/scripts/cpr.cmake @@ -5,7 +5,7 @@ set(CURL_DISABLE_TESTS OFF) FetchContent_Declare( cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git - GIT_TAG 1986262ba4e0cb052161e9e7919aef5ef08217f0 + GIT_TAG 1.10.5 GIT_PROGRESS TRUE ) message("cpr") diff --git a/src/http_client/http_client.cpp b/src/http_client/http_client.cpp new file mode 100644 index 00000000..ea3b47b7 --- /dev/null +++ b/src/http_client/http_client.cpp @@ -0,0 +1,46 @@ +#include "http_client.hpp" + +namespace big +{ + http_client::http_client() : + m_proxy_mgr(m_session) + { + m_session.SetConnectTimeout(CONNECT_TIMEOUT); + m_session.SetTimeout(REQUEST_TIMEOUT); + } + + bool http_client::download(const cpr::Url& url, const std::filesystem::path& path, cpr::Header headers, cpr::Parameters query_params) + { + m_session.SetUrl(url); + m_session.SetHeader(headers); + m_session.SetParameters(query_params); + + std::ofstream of(path, std::ios::binary); + auto res = m_session.Download(of); + + return res.status_code == 200; + } + + cpr::Response http_client::get(const cpr::Url& url, cpr::Header headers, cpr::Parameters query_params) + { + m_session.SetUrl(url); + m_session.SetHeader(headers); + m_session.SetParameters(query_params); + + return m_session.Get(); + } + + cpr::Response http_client::post(const cpr::Url& url, cpr::Header headers, cpr::Body body) + { + m_session.SetUrl(url); + m_session.SetHeader(headers); + m_session.SetBody(body); + + return m_session.Post(); + } + + bool http_client::init(file proxy_settings_file) + { + return m_proxy_mgr.load(proxy_settings_file); + } +} \ No newline at end of file diff --git a/src/http_client/http_client.hpp b/src/http_client/http_client.hpp new file mode 100644 index 00000000..af4c4283 --- /dev/null +++ b/src/http_client/http_client.hpp @@ -0,0 +1,38 @@ +#pragma once +#include +#include "proxy_mgr.hpp" + +namespace big +{ + constexpr auto CONNECT_TIMEOUT = 1000; + constexpr auto REQUEST_TIMEOUT = 5000; + + class http_client + { + private: + cpr::Session m_session; + proxy_mgr m_proxy_mgr; + + public: + http_client(); + virtual ~http_client() = default; + http_client(const http_client&) = delete; + http_client(http_client&&) noexcept = delete; + http_client& operator=(const http_client&) = delete; + http_client& operator=(http_client&&) noexcept = delete; + + bool download(const cpr::Url& url, const std::filesystem::path& path, cpr::Header headers = {}, cpr::Parameters query_params = {}); + cpr::Response get(const cpr::Url& url, cpr::Header headers = {}, cpr::Parameters query_params = {}); + cpr::Response post(const cpr::Url& url, cpr::Header headers = {}, cpr::Body body = {}); + + proxy_mgr& proxy_mgr() + { + return m_proxy_mgr; + } + + bool init(file proxy_settings_file); + + }; + + inline auto g_http_client = http_client(); +} \ No newline at end of file diff --git a/src/http_client/proxy_mgr.cpp b/src/http_client/proxy_mgr.cpp new file mode 100644 index 00000000..a26dd6c6 --- /dev/null +++ b/src/http_client/proxy_mgr.cpp @@ -0,0 +1,149 @@ +#include "proxy_mgr.hpp" + +namespace big +{ + proxy_mgr::proxy_mgr(cpr::Session& session) : + m_session(session), + m_protocols({ + {ProxyProtocol::NONE, "none"}, + {ProxyProtocol::HTTP, "http"}, + {ProxyProtocol::HTTPS, "https"}, + {ProxyProtocol::SOCKS4, "socks4"}, + {ProxyProtocol::SOCKS4A, "socks4a"}, + {ProxyProtocol::SOCKS5, "socks5"}, + {ProxyProtocol::SOCKS5H, "socks5h"}, + }) + { + } + + bool proxy_mgr::load(file proxy_settings_file) + { + m_proxy_settings_file = proxy_settings_file; + + if (proxy_settings_file.exists()) + { + auto settings_file = std::ifstream(proxy_settings_file.get_path(), std::ios::binary); + try + { + nlohmann::json j; + settings_file >> j; + + m_proxy_settings = j.get(); + } + catch (const std::exception& e) + { + LOG(WARNING) << "Failed to parse proxy settings file: " << e.what(); + return false; + } + } + + if (m_proxy_settings.creds.uses_creds) + { + update(m_proxy_settings.proxy_host, + m_proxy_settings.proxy_port, + m_proxy_settings.protocol, + m_proxy_settings.creds.user, + m_proxy_settings.creds.password); + + return true; + } + update(m_proxy_settings.proxy_host, m_proxy_settings.proxy_port, m_proxy_settings.protocol); + + return true; + } + + void proxy_mgr::update(const std::string& host, const int port, const ProxyProtocol protocol) + { + m_proxy_settings.protocol = protocol; + m_proxy_settings.proxy_host = host; + m_proxy_settings.proxy_port = port; + + m_proxy_settings.creds = {}; + + apply_proxy_to_session(); + save(); + } + + void proxy_mgr::update(const std::string& host, const int port, const ProxyProtocol protocol, const std::string& user, const std::string& password) + { + m_proxy_settings.protocol = protocol; + m_proxy_settings.proxy_host = host; + m_proxy_settings.proxy_port = port; + + m_proxy_settings.creds.uses_creds = true; + m_proxy_settings.creds.user = user; + m_proxy_settings.creds.password = password; + + apply_proxy_to_session(); + save(); + } + + void proxy_mgr::reset() + { + m_proxy_settings = {}; + + save(); + } + + std::string proxy_mgr::protocol_str() const + { + return m_protocols.at(m_proxy_settings.protocol); + } + + const std::string& proxy_mgr::protocol_str(ProxyProtocol protocol) const + { + return m_protocols.at(protocol); + } + + void proxy_mgr::apply_proxy_to_session() + { + if (m_proxy_settings.protocol == ProxyProtocol::NONE) + { + m_session.SetProxies({}); + m_session.SetProxyAuth({}); + + return; + } + + std::map proxies; + std::map proxy_auths; + const auto proxy_auth = cpr::EncodedAuthentication{m_proxy_settings.creds.user, m_proxy_settings.creds.password}; + + for (const auto& supported_protocol : m_supported_protocols) + { + proxies.insert({supported_protocol, build_url(m_proxy_settings.proxy_host, std::to_string(m_proxy_settings.proxy_port))}); + if (m_proxy_settings.creds.uses_creds) + { + proxy_auths.insert({supported_protocol, proxy_auth}); + } + } + + m_session.SetProxies(proxies); + if (m_proxy_settings.creds.uses_creds) + m_session.SetProxyAuth(proxy_auths); + } + + std::string proxy_mgr::build_url(const std::string& host, const std::string& port) const + { + return protocol_str() + "://" + host + ":" + port; + } + + bool proxy_mgr::save() + { + try + { + auto settings_file = std::ofstream(m_proxy_settings_file.get_path(), std::ios::binary | std::ios::trunc); + + nlohmann::json j = m_proxy_settings; + settings_file << j; + } + catch (const std::exception& e) + { + std::cerr << e.what() << '\n'; + + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/src/http_client/proxy_mgr.hpp b/src/http_client/proxy_mgr.hpp new file mode 100644 index 00000000..9adceb3f --- /dev/null +++ b/src/http_client/proxy_mgr.hpp @@ -0,0 +1,42 @@ +#pragma once +#include +#include "proxy_protocols.hpp" +#include "proxy_settings.hpp" + +namespace big +{ + class proxy_mgr + { + private: + cpr::Session& m_session; + // protocols supported by CURL + std::unordered_map m_protocols; + // protocols to be proxied + std::array m_supported_protocols = { "http", "https" }; + + proxy_settings m_proxy_settings; + file m_proxy_settings_file; + + public: + proxy_mgr(cpr::Session& session); + + bool load(file proxy_settings_file); + void update(const std::string& host, const int port, const ProxyProtocol protocol); + void update(const std::string& host, const int port, const ProxyProtocol protocol, const std::string& user, const std::string& password); + void reset(); + + std::string protocol_str() const; + const std::string& protocol_str(ProxyProtocol protocol) const; + const auto& protocols() const + { return m_protocols; } + + const proxy_settings& settings() const + { return m_proxy_settings; } + + private: + void apply_proxy_to_session(); + std::string build_url(const std::string& host, const std::string& port) const; + bool save(); + + }; +} \ No newline at end of file diff --git a/src/http_client/proxy_protocols.hpp b/src/http_client/proxy_protocols.hpp new file mode 100644 index 00000000..b4fed279 --- /dev/null +++ b/src/http_client/proxy_protocols.hpp @@ -0,0 +1,34 @@ +#pragma once + +namespace big +{ + enum class ProxyProtocol : uint32_t + { + NONE, + HTTP, + HTTPS, + SOCKS4, + SOCKS4A, + SOCKS5, + SOCKS5H, + FTP, + SMTP, + POP3, + IMAP, + DNS, + FTP_GATEWAY, + TELNET, + SIP, + WEBSOCKETS, + RTSP, + PPTP, + L2TP, + MPLS, + IPSEC, + REVERSE_PROXY, + TRANSPARENT_PROXY, + ANONYMIZING_PROXY, + FORWARD_PROXY, + }; + NLOHMANN_JSON_SERIALIZE_ENUM(ProxyProtocol, {{ProxyProtocol::NONE, "none"}, {ProxyProtocol::HTTP, "http"}, {ProxyProtocol::HTTPS, "https"}, {ProxyProtocol::SOCKS4, "socks4"}, {ProxyProtocol::SOCKS5, "socks5"}, {ProxyProtocol::FTP, "ftp"}, {ProxyProtocol::SMTP, "smtp"}, {ProxyProtocol::POP3, "pop3"}, {ProxyProtocol::IMAP, "imap"}, {ProxyProtocol::DNS, "dns"}, {ProxyProtocol::FTP_GATEWAY, "ftp_gateway"}, {ProxyProtocol::TELNET, "telnet"}, {ProxyProtocol::SIP, "sip"}, {ProxyProtocol::WEBSOCKETS, "websockets"}, {ProxyProtocol::RTSP, "rtsp"}, {ProxyProtocol::PPTP, "pptp"}, {ProxyProtocol::L2TP, "l2tp"}, {ProxyProtocol::MPLS, "mpls"}, {ProxyProtocol::IPSEC, "ipsec"}, {ProxyProtocol::REVERSE_PROXY, "reverse_proxy"}, {ProxyProtocol::TRANSPARENT_PROXY, "transparent_proxy"}, {ProxyProtocol::ANONYMIZING_PROXY, "anonymizing_proxy"}, {ProxyProtocol::FORWARD_PROXY, "forward_proxy"}}) +} \ No newline at end of file diff --git a/src/http_client/proxy_settings.hpp b/src/http_client/proxy_settings.hpp new file mode 100644 index 00000000..59740ef1 --- /dev/null +++ b/src/http_client/proxy_settings.hpp @@ -0,0 +1,25 @@ +#pragma once +#include "proxy_protocols.hpp" + +namespace big +{ + struct proxy_settings + { + std::string proxy_host; + int proxy_port; + ProxyProtocol protocol = ProxyProtocol::NONE; + + struct credentials + { + bool uses_creds; + + std::string user; + std::string password; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(credentials, uses_creds, user, password) + } creds{}; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(proxy_settings, proxy_host, proxy_port, protocol, creds) + + }; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1a44d0dc..23cead36 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "fiber_pool.hpp" #include "gui.hpp" #include "hooking.hpp" +#include "http_client/http_client.hpp" #include "logger/exception_handler.hpp" #include "lua/lua_manager.hpp" #include "native_hooks/native_hooks.hpp" @@ -35,6 +36,7 @@ #include "util/migrate.hpp" #include "version.hpp" + BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) { using namespace big; @@ -84,6 +86,9 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) auto fiber_pool_instance = std::make_unique(11); LOG(INFO) << "Fiber pool initialized."; + g_http_client.init(g_file_manager.get_project_file("./proxy_settings.json")); + LOG(INFO) << "HTTP Client initialized."; + g_translation_service.init(); LOG(INFO) << "Translation Service initialized."; diff --git a/src/services/api/api_service.cpp b/src/services/api/api_service.cpp index d8aa97cd..fd489879 100644 --- a/src/services/api/api_service.cpp +++ b/src/services/api/api_service.cpp @@ -1,8 +1,10 @@ #include "api_service.hpp" +#include "http_client/http_client.hpp" #include "pointers.hpp" #include "services/creator_storage/creator_storage_service.hpp" + namespace big { @@ -18,8 +20,7 @@ namespace big 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)}}); - + const auto response = g_http_client.post("https://scui.rockstargames.com/api/friend/accountsearch", {{"Authorization", AUTHORIZATION_TICKET}, {"X-Requested-With", "XMLHttpRequest"}}, {std::format("searchNickname={}", username)}); if (response.status_code == 200) { try @@ -43,8 +44,7 @@ namespace big 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)}}); - + const auto response = g_http_client.post("https://scui.rockstargames.com/api/friend/getprofile", {{"Authorization", AUTHORIZATION_TICKET}, {"X-Requested-With", "XMLHttpRequest"}, {"Content-Type", "application/json"}}, std::format(R"({{"RockstarId":"{}"}})", rid)); if (response.status_code == 200) { try @@ -65,16 +65,16 @@ namespace big // Ratelimit: 10 per Minute, if exceeded than 5 min cooldown 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)}}); + const auto response = g_http_client.post("https://scui.rockstargames.com/api/messaging/sendmessage", {{"Authorization", AUTHORIZATION_TICKET}, {"X-Requested-With", "XMLHttpRequest"}, {"Content-Type", "application/json"}}, {std::format(R"({{"env":"prod","title":"gta5","version":11,"recipientRockstarId":"{}","messageText":"{}"}})", rid, message)}); return response.status_code == 200; } bool api_service::get_job_details(std::string_view content_id, nlohmann::json& result) { - 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()}}); + const auto response = g_http_client.get("https://scapi.rockstargames.com/ugc/mission/details", + {{"X-AMC", "true"}, {"X-Requested-With", "XMLHttpRequest"}}, + {{"title", "gtav"}, {"contentId", content_id.data()}}); if (response.status_code != 200) return false; @@ -92,18 +92,17 @@ namespace big bool api_service::download_job_metadata(std::string_view content_id, int f1, int f0, int lang) { - cpr::Response response = cpr::Get(cpr::Url{std::format("https://prod.cloud.rockstargames.com/ugc/gta5mission/{}/{}_{}_{}.json", + const auto response = g_http_client.get(std::format("https://prod.cloud.rockstargames.com/ugc/gta5mission/{}/{}_{}_{}.json", content_id, f1, f0, - languages.at(lang))}); + languages.at(lang))); if (response.status_code == 200) { - std::ofstream of = creator_storage_service::create_file(std::string(content_id) + ".json"); - cpr::Response r = cpr::Download(of, response.url); + const auto of = creator_storage_service::create_file(std::string(content_id) + ".json"); - return true; + return g_http_client.download(response.url, of); } return false; diff --git a/src/services/creator_storage/creator_storage_service.cpp b/src/services/creator_storage/creator_storage_service.cpp index 1dab6040..f5ea376c 100644 --- a/src/services/creator_storage/creator_storage_service.cpp +++ b/src/services/creator_storage/creator_storage_service.cpp @@ -21,9 +21,9 @@ namespace big return file_paths; } - std::ofstream creator_storage_service::create_file(std::string file) + std::filesystem::path creator_storage_service::create_file(std::string file) { - return std::ofstream(check_jobs_folder().get_file(file).get_path()); + return check_jobs_folder().get_file(file).get_path(); } void creator_storage_service::save_file(std::string_view filename) diff --git a/src/services/creator_storage/creator_storage_service.hpp b/src/services/creator_storage/creator_storage_service.hpp index bae6c6a5..cc5a7942 100644 --- a/src/services/creator_storage/creator_storage_service.hpp +++ b/src/services/creator_storage/creator_storage_service.hpp @@ -8,7 +8,7 @@ namespace big public: static std::vector list_files(); - static std::ofstream create_file(std::string name); + static std::filesystem::path create_file(std::string name); static void load_file(std::string_view file_name); static void save_file(std::string_view file_name); diff --git a/src/services/gui/gui_service.hpp b/src/services/gui/gui_service.hpp index 6bd1fbe7..9739e05d 100644 --- a/src/services/gui/gui_service.hpp +++ b/src/services/gui/gui_service.hpp @@ -53,6 +53,7 @@ namespace big REACTION_SETTINGS, PROTECTION_SETTINGS, TRANSLATION_SETTINGS, + PROXY_SETTINGS, DEBUG, PLAYER, @@ -155,6 +156,7 @@ namespace big {TAB_DECL(HOTKEY_SETTINGS), view::hotkey_settings}}, {TAB_DECL(REACTION_SETTINGS), view::reaction_settings}}, {TAB_DECL(PROTECTION_SETTINGS), view::protection_settings}}, + {TAB_DECL(PROXY_SETTINGS), view::proxy_settings}}, {TAB_DECL(DEBUG), nullptr}}, }, }, diff --git a/src/services/translation_service/translation_service.cpp b/src/services/translation_service/translation_service.cpp index ff9cbe3c..b769a0f7 100644 --- a/src/services/translation_service/translation_service.cpp +++ b/src/services/translation_service/translation_service.cpp @@ -2,11 +2,10 @@ #include "fiber_pool.hpp" #include "file_manager.hpp" +#include "http_client/http_client.hpp" #include "pointers.hpp" #include "thread_pool.hpp" -#include - namespace big { translation_service::translation_service() : @@ -190,8 +189,7 @@ namespace big { if (auto it = m_remote_index.translations.find(pack_id.data()); it != m_remote_index.translations.end()) { - cpr::Response response = download_file("/" + it->second.file); - + const auto response = download_file("/" + it->second.file); if (response.status_code == 200) { try @@ -217,8 +215,7 @@ namespace big bool translation_service::download_index() { - cpr::Response response = download_file("/index.json"); - + const auto response = download_file("/index.json"); if (response.status_code == 200) { try @@ -276,11 +273,9 @@ namespace big cpr::Response translation_service::download_file(const std::string& filename) { - cpr::Response response = cpr::Get(cpr::Url{m_url + filename}); - + auto response = g_http_client.get(m_url + filename); if (response.status_code != 200) - response = cpr::Get(cpr::Url{m_fallback_url + filename}); - + response = g_http_client.get(m_fallback_url + filename); return response; } diff --git a/src/views/settings/view_proxy_settings.cpp b/src/views/settings/view_proxy_settings.cpp new file mode 100644 index 00000000..f35baa6f --- /dev/null +++ b/src/views/settings/view_proxy_settings.cpp @@ -0,0 +1,72 @@ +#include "http_client/http_client.hpp" +#include "thread_pool.hpp" +#include "views/view.hpp" + +namespace big +{ + void view::proxy_settings() + { + ImGui::TextWrapped("PROXY_SETTINGS_DESCRIPTION"_T.data()); + + static auto settings = g_http_client.proxy_mgr().settings(); + if (ImGui::BeginCombo("PROXY_SETTINGS_PROTOCOL"_T.data(), g_http_client.proxy_mgr().protocol_str(settings.protocol).data())) + { + for (const auto [key, protocol] : g_http_client.proxy_mgr().protocols()) + { + if (ImGui::Selectable(protocol.data(), key == settings.protocol)) + { + settings.protocol = key; + } + } + ImGui::EndCombo(); + } + + if (settings.protocol != ProxyProtocol::NONE) + { + components::input_text_with_hint("PROXY_SETTINGS_HOST"_T, "example.com", settings.proxy_host); + ImGui::InputInt("PROXY_SETTINGS_PORT"_T.data(), &settings.proxy_port); + settings.proxy_port = std::clamp(settings.proxy_port, 0, 0xffff); + + ImGui::Checkbox("PROXY_SETTINGS_USES_CREDENTIALS"_T.data(), &settings.creds.uses_creds); + if (settings.creds.uses_creds) + { + components::input_text_with_hint("PROXY_SETTINGS_USER"_T, "user", settings.creds.user); + components::input_text_with_hint("PROXY_SETTINGS_PASSWORD"_T, "passw0rd", settings.creds.password); + } + } + + if (components::button("PROXY_SETTINGS_TEST_CURRENT"_T)) + { + g_thread_pool->push([] { + const auto response = g_http_client.get("https://github.com/YimMenu/YimMenu/raw/master/metadata.json"); + try + { + const auto j = nlohmann::json::parse(response.text); + g_notification_service->push_success("PROXY_SETTINGS"_T.data(), "PROXY_SETTINGS_TEST_CURRENT_SUCCESS"_T.data()); + } + catch (const std::exception& e) + { + g_notification_service->push_error("PROXY_SETTINGS"_T.data(), "PROXY_SETTINGS_TEST_CURRENT_FAIL"_T.data()); + } + }); + } + if (components::button("RESET"_T)) + { + settings = {}; + g_http_client.proxy_mgr().reset(); + } + ImGui::SameLine(); + if (components::button("PROXY_SETTINGS_UPDATE"_T)) + { + if (settings.protocol == ProxyProtocol::NONE) + settings = {}; + + if (settings.creds.uses_creds) + g_http_client.proxy_mgr().update(settings.proxy_host, settings.proxy_port, settings.protocol, settings.creds.user, settings.creds.password); + else + g_http_client.proxy_mgr().update(settings.proxy_host, settings.proxy_port, settings.protocol); + + g_notification_service->push("PROXY_SETTINGS"_T.data(), "PROXY_SETTINGS_UPDATE_SUCCESS"_T.data()); + } + } +} \ No newline at end of file diff --git a/src/views/view.hpp b/src/views/view.hpp index 3f47561a..50cb6599 100644 --- a/src/views/view.hpp +++ b/src/views/view.hpp @@ -49,6 +49,7 @@ namespace big static void spawn_vehicle(); static void pv(); static void persist_car(); + static void proxy_settings(); static void xml_vehicles(); static void fun_vehicle(); static void vehicle_control();