HttpLib/SteamUtils: Endpoint to get Steam User config as JSON

pull/239/head
Peter Repukat 1 year ago
parent e6db328273
commit 00127dcd2b

@ -21,6 +21,7 @@ limitations under the License.
#include "AppLauncher.h" #include "AppLauncher.h"
#include "../common/Settings.h" #include "../common/Settings.h"
#include "../common/steam_util.h"
HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) : app_launcher_(app_launcher), close_(std::move(close)) HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) : app_launcher_(app_launcher), close_(std::move(close))
{ {
@ -28,12 +29,17 @@ HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) :
void HttpServer::run() void HttpServer::run()
{ {
server_.Get("/launched-pids", [this](const httplib::Request& req, httplib::Response& res) { auto setCorsHeader = [](httplib::Response& res) {
res.set_header("Access-Control-Allow-Origin", "*");
};
server_.Get("/launched-pids", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
const nlohmann::json j = app_launcher_.launchedPids(); const nlohmann::json j = app_launcher_.launchedPids();
res.set_content(j.dump(), "text/json"); res.set_content(j.dump(), "text/json");
setCorsHeader(res);
}); });
server_.Post("/launched-pids", [this](const httplib::Request& req, httplib::Response& res) { server_.Post("/launched-pids", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
try { try {
const nlohmann::json postbody = nlohmann::json::parse(req.body); const nlohmann::json postbody = nlohmann::json::parse(req.body);
app_launcher_.addPids(postbody.get<std::vector<DWORD>>()); app_launcher_.addPids(postbody.get<std::vector<DWORD>>());
@ -63,21 +69,28 @@ void HttpServer::run()
res.set_content(j.dump(), "text/json"); res.set_content(j.dump(), "text/json");
}); });
server_.Post("/quit", [this](const httplib::Request& req, httplib::Response& res) { server_.Post("/quit", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
close_(); close_();
}); });
server_.Get("/settings", [this](const httplib::Request& req, httplib::Response& res) { server_.Get("/settings", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
res.set_content(Settings::toJson().dump(), "text/json"); res.set_content(Settings::toJson().dump(), "text/json");
}); });
server_.Get("/steam_settings", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
res.set_content(util::steam::getSteamConfig().dump(4), "text/json");
});
server_thread_ = std::thread([this]() { server_thread_ = std::thread([this]() {
if (!server_.listen("0.0.0.0", port_)) { if (!server_.listen("0.0.0.0", port_)) {
spdlog::error("Couldn't start http-server"); spdlog::error("Couldn't start http-server");
return; return;
} }
spdlog::debug("Started http-server on port {}", static_cast<int>(port_)); spdlog::debug("Started http-server on port {}", static_cast<int>(port_));
}); });
} }
void HttpServer::stop() void HttpServer::stop()

@ -30,152 +30,192 @@ namespace util
namespace steam namespace steam
{ {
static constexpr std::wstring_view user_data_path = L"/userdata/"; static constexpr std::wstring_view user_data_path = L"/userdata/";
static constexpr std::wstring_view config_file_name = L"/config/localconfig.vdf"; static constexpr std::wstring_view config_file_name = L"/config/localconfig.vdf";
static constexpr std::string_view overlay_hotkey_name = "InGameOverlayShortcutKey "; static constexpr std::string_view overlay_hotkey_name = "InGameOverlayShortcutKey ";
static constexpr std::string_view screenshot_hotkey_name = "InGameOverlayScreenshotHotKey "; static constexpr std::string_view screenshot_hotkey_name = "InGameOverlayScreenshotHotKey ";
inline std::filesystem::path getSteamPath() inline std::filesystem::path getSteamPath()
{ {
#ifdef _WIN32 #ifdef _WIN32
try { try {
// TODO: check if keys/value exist // TODO: check if keys/value exist
// steam should always be open and have written reg values... // steam should always be open and have written reg values...
winreg::RegKey key{ HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam" }; winreg::RegKey key{ HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam" };
const auto res = key.GetStringValue(L"SteamPath"); const auto res = key.GetStringValue(L"SteamPath");
spdlog::info(L"Detected Steam Path: {}", res); spdlog::info(L"Detected Steam Path: {}", res);
return res; return res;
} }
catch (const winreg::RegException& e) { catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what()); spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
} }
return Settings::common.steamPath; return Settings::common.steamPath;
#else #else
return L""; // TODO return L""; // TODO
#endif #endif
} }
inline std::wstring getSteamUserId() inline std::wstring getSteamUserId()
{ {
#ifdef _WIN32 #ifdef _WIN32
try { try {
// TODO: check if keys/value exist // TODO: check if keys/value exist
// steam should always be open and have written reg values... // steam should always be open and have written reg values...
winreg::RegKey key{ HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess" }; winreg::RegKey key{ HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess" };
const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser")); const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser"));
spdlog::info(L"Detected Steam UserId: {}", res); spdlog::info(L"Detected Steam UserId: {}", res);
return res; return res;
} }
catch (const winreg::RegException& e) { catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what()); spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
} }
return Settings::common.steamUserId; return Settings::common.steamUserId;
#else #else
return L""; // TODO return L""; // TODO
#endif #endif
} }
inline std::vector<std::string> getOverlayHotkey(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath()) inline std::vector<std::string> getOverlayHotkey(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath())
{ {
const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name); const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name);
if (!std::filesystem::exists(config_path)) { if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path); spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return { "Shift", "KEY_TAB" }; // default return { "Shift", "KEY_TAB" }; // default
} }
std::ifstream config_file(config_path); std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file); auto root = tyti::vdf::read(config_file);
std::shared_ptr<tyti::vdf::basic_object<char>> children = root.childs["system"]; std::shared_ptr<tyti::vdf::basic_object<char>> children = root.childs["system"];
if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayShortcutKey")) { if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayShortcutKey")) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab"); spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return { "Shift", "KEY_TAB" }; // default return { "Shift", "KEY_TAB" }; // default
} }
auto hotkeys = children->attribs.at("InGameOverlayShortcutKey"); auto hotkeys = children->attribs.at("InGameOverlayShortcutKey");
// has anyone more than 4 keys to open overlay?! // has anyone more than 4 keys to open overlay?!
std::smatch m; std::smatch m;
if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) { if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab"); spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return { "Shift", "KEY_TAB" }; // default return { "Shift", "KEY_TAB" }; // default
} }
std::vector<std::string> res; std::vector<std::string> res;
for (auto i = 1; i < m.size(); i++) { for (auto i = 1; i < m.size(); i++) {
const auto s = std::string(m[i]); const auto s = std::string(m[i]);
if (!s.empty()) { if (!s.empty()) {
res.push_back(s); res.push_back(s);
} }
} }
if (res.empty()) { if (res.empty()) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab"); spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return { "Shift", "KEY_TAB" }; // default return { "Shift", "KEY_TAB" }; // default
} }
spdlog::info("Detected Overlay hotkey(s): {}", std::accumulate( spdlog::info("Detected Overlay hotkey(s): {}", std::accumulate(
res.begin() + 1, res.end(), res[0], res.begin() + 1, res.end(), res[0],
[](auto acc, const auto curr) { return acc += "+" + curr; })); [](auto acc, const auto curr) { return acc += "+" + curr; }));
return res; return res;
} }
inline std::vector<std::string> getScreenshotHotkey(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath()) inline std::vector<std::string> getScreenshotHotkey(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath())
{ {
const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name); const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name);
if (!std::filesystem::exists(config_path)) { if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path); spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return { "KEY_F12" }; // default return { "KEY_F12" }; // default
} }
std::ifstream config_file(config_path); std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file); auto root = tyti::vdf::read(config_file);
std::shared_ptr<tyti::vdf::basic_object<char>> children = root.childs["system"]; std::shared_ptr<tyti::vdf::basic_object<char>> children = root.childs["system"];
if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayScreenshotHotKey")) { if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayScreenshotHotKey")) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12"); spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return { "KEY_F12" }; // default return { "KEY_F12" }; // default
} }
auto hotkeys = children->attribs.at("InGameOverlayScreenshotHotKey"); auto hotkeys = children->attribs.at("InGameOverlayScreenshotHotKey");
// has anyone more than 4 keys to screenshot?! // has anyone more than 4 keys to screenshot?!
std::smatch m; std::smatch m;
if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) { if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12"); spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return { "KEY_F12" }; // default return { "KEY_F12" }; // default
} }
std::vector<std::string> res; std::vector<std::string> res;
for (auto i = 1; i < m.size(); i++) { for (auto i = 1; i < m.size(); i++) {
const auto s = std::string(m[i]); const auto s = std::string(m[i]);
if (!s.empty()) { if (!s.empty()) {
res.push_back(s); res.push_back(s);
} }
} }
if (res.empty()) { if (res.empty()) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12"); spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return { "KEY_F12" }; // default return { "KEY_F12" }; // default
} }
spdlog::info("Detected screenshot hotkey(s): {}", std::accumulate( spdlog::info("Detected screenshot hotkey(s): {}", std::accumulate(
res.begin() + 1, res.end(), res[0], res.begin() + 1, res.end(), res[0],
[](auto acc, const auto curr) { return acc += "+" + curr; })); [](auto acc, const auto curr) { return acc += "+" + curr; }));
return res; return res;
} }
inline bool getXBCRebindingEnabled(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath()) inline bool getXBCRebindingEnabled(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath())
{ {
const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name); const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name);
if (!std::filesystem::exists(config_path)) { if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path); spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return false; return false;
} }
std::ifstream config_file(config_path); std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file); auto root = tyti::vdf::read(config_file);
if (root.attribs.empty() || !root.attribs.contains("SteamController_XBoxSupport")) { if (root.attribs.empty() || !root.attribs.contains("SteamController_XBoxSupport")) {
spdlog::warn("\"Xbox Configuration Support\" is disabled in Steam. This may cause doubled Inputs!"); spdlog::warn("\"Xbox Configuration Support\" is disabled in Steam. This may cause doubled Inputs!");
return false; return false;
} }
auto xbsup = root.attribs.at("SteamController_XBoxSupport"); auto xbsup = root.attribs.at("SteamController_XBoxSupport");
if (xbsup != "1") { if (xbsup != "1") {
spdlog::warn("\"Xbox Configuration Support\" is disabled in Steam. This may cause doubled Inputs!"); spdlog::warn("\"Xbox Configuration Support\" is disabled in Steam. This may cause doubled Inputs!");
} }
return xbsup == "1"; return xbsup == "1";
} }
inline nlohmann::json getSteamConfig(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamUserId())
{
const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name);
if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return nlohmann::json();
}
std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file);
if (root.attribs.empty())
{
return {};
}
auto res = nlohmann::json::object();
res[root.name] = nlohmann::json::object();
for (auto& [key, value] : root.attribs)
{
res[root.name][key] = value;
}
auto parse_child = [](nlohmann::json& j, std::shared_ptr<tyti::vdf::basic_object<char>> child, auto&& recurse) -> void
{
for (auto& [key, value] : child->attribs)
{
j[key] = value;
for (auto& [childkey, childval] : child->childs)
{
j[childkey] = {};
recurse(j[childkey], childval, recurse);
}
}
};
for (auto& [key, value] : root.childs)
{
res[root.name][key] = {};
parse_child(res[root.name][key], value, parse_child);
}
return res;
}
} }
} }
Loading…
Cancel
Save