mirror of
https://github.com/acidicoala/SmokeAPI.git
synced 2025-12-05 21:15:39 -05:00
Reworked logging
This commit is contained in:
@@ -4,7 +4,7 @@ project(smoke-api-tools LANGUAGES CXX)
|
||||
|
||||
### Install CPM package manager
|
||||
|
||||
include(../KoalaBox/cmake/get_cpm.cmake)
|
||||
#include(../KoalaBox/cmake/get_cpm.cmake)
|
||||
|
||||
### Install parser library
|
||||
|
||||
@@ -54,6 +54,7 @@ CPMAddPackage(
|
||||
|
||||
add_executable(steamworks_downloader steamworks_downloader.cpp)
|
||||
target_link_libraries(steamworks_downloader PRIVATE
|
||||
KoalaBox
|
||||
cpr # HTTP client
|
||||
miniz # ZIP library
|
||||
)
|
||||
|
||||
@@ -1,111 +1,21 @@
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
#include <cpr/cpr.h>
|
||||
#include <miniz.h>
|
||||
|
||||
#include <koalabox/zip.hpp>
|
||||
|
||||
namespace {
|
||||
namespace fs = std::filesystem;
|
||||
namespace zip = koalabox::zip;
|
||||
|
||||
// Function to extract files from a ZIP archive that match multiple regex patterns
|
||||
void extract_files(
|
||||
const fs::path& zip_path,
|
||||
const std::function<fs::path(const std::string& name, bool is_dir)>& predicate
|
||||
) {
|
||||
mz_zip_archive zip = {};
|
||||
|
||||
if (!mz_zip_reader_init_file(&zip, zip_path.string().c_str(), 0)) {
|
||||
throw std::runtime_error("mz_zip_reader_init_file() failed for: " + zip_path.string());
|
||||
}
|
||||
|
||||
[[maybe_unused]] auto guard = [&zip] { mz_zip_reader_end(&zip); };
|
||||
try {
|
||||
std::error_code ec;
|
||||
const mz_uint num_files = mz_zip_reader_get_num_files(&zip);
|
||||
|
||||
for (mz_uint i = 0; i < num_files; ++i) {
|
||||
mz_zip_archive_file_stat st;
|
||||
if (!mz_zip_reader_file_stat(&zip, i, &st)) {
|
||||
mz_zip_reader_end(&zip);
|
||||
throw std::runtime_error(
|
||||
"mz_zip_reader_file_stat() failed at index " + std::to_string(i));
|
||||
}
|
||||
|
||||
const std::string name = st.m_filename;
|
||||
|
||||
// Skip dangerous names early
|
||||
if (name.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool is_dir = mz_zip_reader_is_file_a_directory(&zip, i) != 0;
|
||||
|
||||
const auto out_path = predicate(name, is_dir);
|
||||
if (out_path.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_dir) {
|
||||
fs::create_directories(out_path, ec);
|
||||
if (ec) {
|
||||
mz_zip_reader_end(&zip);
|
||||
throw std::runtime_error(
|
||||
"Failed to create directory: " + out_path.string() + " (" + ec.message()
|
||||
+ ")");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure parent directories exist
|
||||
fs::create_directories(out_path.parent_path(), ec);
|
||||
if (ec) {
|
||||
mz_zip_reader_end(&zip);
|
||||
throw std::runtime_error(
|
||||
"Failed to create parent directories for: " + out_path.string() + " (" + ec.
|
||||
message() + ")");
|
||||
}
|
||||
|
||||
// Extract to heap then write to file
|
||||
size_t uncomp_size = 0;
|
||||
void* p = mz_zip_reader_extract_to_heap(&zip, i, &uncomp_size, 0);
|
||||
if (!p) {
|
||||
mz_zip_reader_end(&zip);
|
||||
throw std::runtime_error("Extraction failed for entry: " + name);
|
||||
}
|
||||
|
||||
std::ofstream ofs(out_path, std::ios::binary);
|
||||
if (!ofs) {
|
||||
mz_free(p);
|
||||
mz_zip_reader_end(&zip);
|
||||
throw std::runtime_error(
|
||||
"Failed to open output file for writing: " + out_path.string());
|
||||
}
|
||||
ofs.write(static_cast<const char*>(p),
|
||||
static_cast<std::streamsize>(uncomp_size));
|
||||
ofs.close();
|
||||
mz_free(p);
|
||||
|
||||
if (!ofs) {
|
||||
mz_zip_reader_end(&zip);
|
||||
throw std::runtime_error("Failed to write output file: " + out_path.string());
|
||||
}
|
||||
}
|
||||
|
||||
mz_zip_reader_end(&zip);
|
||||
} catch (...) {
|
||||
// Ensure cleanup on exceptions
|
||||
guard();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable once CppDFAConstantParameter
|
||||
std::string generate_random_string(const size_t length) {
|
||||
static constexpr char charset[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
static constexpr char charset[] = "0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
thread_local std::mt19937_64 rng{std::random_device{}()};
|
||||
thread_local std::uniform_int_distribution<std::size_t> dist(0, sizeof(charset) - 2);
|
||||
@@ -121,50 +31,41 @@ namespace {
|
||||
|
||||
void print_help() {
|
||||
std::cout << "Steamworks SDK downloader for SmokeAPI v1.0" << std::endl
|
||||
<< "Usage: steamworks_downloader version1 version2 ... versionN" << std::endl
|
||||
<< "Example: steamworks_downloader 100 158a 162" << std::endl
|
||||
<< "SDK version list available at: "
|
||||
<< "https://partner.steamgames.com/downloads/list" << std::endl;
|
||||
<< "Usage: steamworks_downloader version1 version2 ... versionN" << std::endl
|
||||
<< "Example: steamworks_downloader 100 158a 162" << std::endl
|
||||
<< "SDK version list available at: "
|
||||
<< "https://partner.steamgames.com/downloads/list" << std::endl;
|
||||
}
|
||||
|
||||
void unzip_sdk(const fs::path& zip_file_path, const fs::path& unzip_dir) {
|
||||
extract_files(zip_file_path, [&](const std::string& name, const bool) {
|
||||
zip::extract_files(zip_file_path, [&](const std::string& name, const bool) {
|
||||
if (name.starts_with("sdk/public/steam/") && name.ends_with(".h")) {
|
||||
return unzip_dir / "headers" / fs::path(name).filename();
|
||||
}
|
||||
|
||||
if (
|
||||
name.starts_with("sdk/redistributable_bin/") &&
|
||||
name.ends_with(".dll") &&
|
||||
name.find("steam_api") != std::string::npos
|
||||
) {
|
||||
if (name.starts_with("sdk/redistributable_bin/") && name.ends_with(".dll") &&
|
||||
name.find("steam_api") != std::string::npos) {
|
||||
return unzip_dir / "binaries" / fs::path(name).filename();
|
||||
}
|
||||
|
||||
return fs::path();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void download_sdk(
|
||||
const fs::path& steamworks_dir,
|
||||
const std::string_view& version
|
||||
) {
|
||||
void download_sdk(const fs::path& steamworks_dir, const std::string_view& version) {
|
||||
const auto download_url = std::format(
|
||||
"https://github.com/acidicoala/cdn/raw/refs/heads/main/valve/steamworks_sdk_{}.zip",
|
||||
version
|
||||
);
|
||||
|
||||
const auto zip_file_path = fs::temp_directory_path()
|
||||
/ (generate_random_string(16) + ".zip");
|
||||
const auto zip_file_path =
|
||||
fs::temp_directory_path() / (generate_random_string(16) + ".zip");
|
||||
|
||||
std::cout << "Downloading " << download_url << " to " << zip_file_path << std::endl;
|
||||
|
||||
std::ofstream of(zip_file_path, std::ios::binary);
|
||||
if (
|
||||
const auto res = cpr::Download(of, cpr::Url{download_url});
|
||||
res.error.code != cpr::ErrorCode::OK
|
||||
) {
|
||||
if (const auto res = cpr::Download(of, cpr::Url{download_url});
|
||||
res.error.code != cpr::ErrorCode::OK) {
|
||||
std::cerr << "Download error: " << res.error.message << std::endl;
|
||||
return;
|
||||
}
|
||||
@@ -180,7 +81,7 @@ namespace {
|
||||
fs::remove(zip_file_path);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* A tool for downloading Steamworks SDK and unpacking its headers and binaries
|
||||
@@ -198,9 +99,8 @@ int main(const int argc, const char** argv) {
|
||||
try {
|
||||
download_sdk(streamworks_dir, argv[i]);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr
|
||||
<< std::format("Error downloading SDK '{}'. Reason: {}", argv[i], e.what())
|
||||
<< std::endl;
|
||||
std::cerr << std::format("Error downloading SDK '{}'. Reason: {}", argv[i], e.what())
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user