From da521719963f242f2f59f82c3061304bd7e941dc Mon Sep 17 00:00:00 2001 From: Jesse <69196954+ThisAMJ@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:07:26 +1100 Subject: [PATCH] feat: sar_download_file This could potentially be unsafe, but it could also automate srconfigs updates, challenge_maplist, fast taunts, containerridesave, vaultsave, tram save, etc. Just be careful with usage, it overwrites! Smartly reads through game directories for existing file to overwrite (even p2common), falls back to main game directory i.e. portal2 / portalreloaded / whatever if file doesn't exist. also fixed a bug with createTempPath -- instead of creating tmp_0_1_2 now it creates tmp_2 --- src/Features/ConfigPlus.cpp | 61 +++++++++++++++++++++++++++++++++++++ src/Features/Updater.cpp | 4 +-- src/Features/Updater.hpp | 2 ++ 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/Features/ConfigPlus.cpp b/src/Features/ConfigPlus.cpp index e88775f74..29b41d8a9 100644 --- a/src/Features/ConfigPlus.cpp +++ b/src/Features/ConfigPlus.cpp @@ -1,5 +1,6 @@ #include "Event.hpp" #include "Features/Session.hpp" +#include "Features/Updater.hpp" #include "Modules/Client.hpp" #include "Modules/Engine.hpp" #include "Modules/FileSystem.hpp" @@ -12,6 +13,8 @@ #include #include #include +#include +#include // Fuck you Windows #ifdef _WIN32 @@ -55,6 +58,64 @@ static void SavePersistentSvars() { } } +CON_COMMAND_F(sar_download_file, "sar_download_file [directory] - Downloads a file from a URL and saves it to a path relative to game directory (e.g. portal2)\nIf directory isn't specified or invalid, looks for and overwrites existing file or uses base game directory\n", FCVAR_DONTRECORD) { + if (args.ArgC() < 3 || args.ArgC() > 4 || !args[1][0] || !args[2][0]) { + return console->Print(sar_download_file.ThisPtr()->m_pszHelpString); + } + + if (!Utils::StartsWith(args[1], "https://s.portal2.sr/") && !Utils::StartsWith(args[1], "https://raw.githubusercontent.com/p2sr/")) { + return console->Print("URL domain is not portal2.sr.\n"); + } + + std::string filepath = args[2]; + std::string gamedir = args.ArgC() > 3 ? args[3] : ""; + + auto result = fileSystem->FindFileSomewhere(filepath, gamedir); + if (result.has_value()) { + filepath = result.value(); + } else { + filepath = std::string(engine->GetGameDirectory()) + "/" + filepath; + if (gamedir != "") for (auto path : fileSystem->GetSearchPaths()) { + if (path.find(gamedir) != std::string::npos) { + filepath = path + filepath; + break; + } + } + } + + CURL *curl = curl_easy_init(); + FILE *fp; + CURLcode res; + auto temp = createTempPath("sar_download_file.tmp"); + if (curl) { + fp = fopen(temp.c_str(), "wb"); + curl_easy_setopt(curl, CURLOPT_URL, args[1]); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &fwrite); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); + res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + fclose(fp); + } + + if (res == CURLE_OK) { + + // Create any intermediate directories + std::string dirpath = filepath; + std::replace(dirpath.begin(), dirpath.end(), '\\', '/'); + dirpath = dirpath.substr(0, dirpath.rfind('/')); + std::filesystem::create_directories(dirpath); + + std::filesystem::remove(filepath); + std::filesystem::copy(temp, filepath); // for some reason moving the file doesn't work + + } else { + console->Print("An error occurred\n"); + } + + std::filesystem::remove(temp); + +} + static void SetSvar(std::string name, std::string val) { g_svars[name] = val; if (g_persistentSvars.count(name) != 0) SavePersistentSvars(); diff --git a/src/Features/Updater.cpp b/src/Features/Updater.cpp index e049e68de..1ddb26d70 100644 --- a/src/Features/Updater.cpp +++ b/src/Features/Updater.cpp @@ -199,7 +199,7 @@ static bool getLatestVersion(std::string *name, std::string *dlUrl, std::string return true; } -static std::string createTempPath(const char *filename) { +std::string createTempPath(const char *filename) { auto base = std::filesystem::temp_directory_path().append(filename); if (!std::filesystem::exists(base)) { return base.string(); @@ -209,7 +209,7 @@ static std::string createTempPath(const char *filename) { std::filesystem::path p; do { - p = base.concat(Utils::ssprintf("_%d", n++)); + p = base.string() + Utils::ssprintf("_%d", n++); } while (std::filesystem::exists(p)); return p.string(); diff --git a/src/Features/Updater.hpp b/src/Features/Updater.hpp index 6f70f09be..74be5c883 100644 --- a/src/Features/Updater.hpp +++ b/src/Features/Updater.hpp @@ -1 +1,3 @@ #pragma once + +extern std::string createTempPath(const char *filename);