i think i got everything

This commit is contained in:
Mars 2025-04-23 02:17:26 -04:00
parent 8293ef42b6
commit cf51e3e569
Signed by: pupbrained
GPG key ID: 0FF5B8826803F895
19 changed files with 671 additions and 805 deletions

View file

@ -1,6 +1,5 @@
#include <chrono>
#include <curl/curl.h>
#include <expected>
#include <filesystem>
#include <fstream>
@ -15,27 +14,27 @@ using namespace std::string_literals;
namespace {
constexpr glz::opts glaze_opts = { .error_on_unknown_keys = false };
fn GetCachePath() -> std::expected<fs::path, String> {
fn GetCachePath() -> Result<fs::path, String> {
std::error_code errc;
fs::path cachePath = fs::temp_directory_path(errc);
if (errc)
return std::unexpected("Failed to get temp directory: " + errc.message());
return Err("Failed to get temp directory: " + errc.message());
cachePath /= "weather_cache.json";
return cachePath;
}
fn ReadCacheFromFile() -> std::expected<WeatherOutput, String> {
std::expected<fs::path, String> cachePath = GetCachePath();
fn ReadCacheFromFile() -> Result<WeatherOutput, String> {
Result<fs::path, String> cachePath = GetCachePath();
if (!cachePath)
return std::unexpected(cachePath.error());
return Err(cachePath.error());
std::ifstream ifs(*cachePath, std::ios::binary);
if (!ifs.is_open())
return std::unexpected("Cache file not found: " + cachePath->string());
return Err("Cache file not found: " + cachePath->string());
DEBUG_LOG("Reading from cache file...");
@ -44,18 +43,18 @@ namespace {
WeatherOutput result;
if (const glz::error_ctx errc = glz::read<glaze_opts>(result, content); errc.ec != glz::error_code::none)
return std::unexpected("JSON parse error: " + glz::format_error(errc, content));
return Err("JSON parse error: " + glz::format_error(errc, content));
DEBUG_LOG("Successfully read from cache file.");
return result;
} catch (const std::exception& e) { return std::unexpected("Error reading cache: "s + e.what()); }
} catch (const std::exception& e) { return Err("Error reading cache: "s + e.what()); }
}
fn WriteCacheToFile(const WeatherOutput& data) -> std::expected<void, String> {
std::expected<fs::path, String> cachePath = GetCachePath();
fn WriteCacheToFile(const WeatherOutput& data) -> Result<void, String> {
Result<fs::path, String> cachePath = GetCachePath();
if (!cachePath)
return std::unexpected(cachePath.error());
return Err(cachePath.error());
DEBUG_LOG("Writing to cache file...");
fs::path tempPath = *cachePath;
@ -65,28 +64,28 @@ namespace {
{
std::ofstream ofs(tempPath, std::ios::binary | std::ios::trunc);
if (!ofs.is_open())
return std::unexpected("Failed to open temp file: " + tempPath.string());
return Err("Failed to open temp file: " + tempPath.string());
String jsonStr;
if (const glz::error_ctx errc = glz::write_json(data, jsonStr); errc.ec != glz::error_code::none)
return std::unexpected("JSON serialization error: " + glz::format_error(errc, jsonStr));
return Err("JSON serialization error: " + glz::format_error(errc, jsonStr));
ofs << jsonStr;
if (!ofs)
return std::unexpected("Failed to write to temp file");
return Err("Failed to write to temp file");
}
std::error_code errc;
fs::rename(tempPath, *cachePath, errc);
if (errc) {
fs::remove(tempPath, errc);
return std::unexpected("Failed to replace cache file: " + errc.message());
return Err("Failed to replace cache file: " + errc.message());
}
DEBUG_LOG("Successfully wrote to cache file.");
return {};
} catch (const std::exception& e) { return std::unexpected("File operation error: "s + e.what()); }
} catch (const std::exception& e) { return Err("File operation error: "s + e.what()); }
}
fn WriteCallback(void* contents, const size_t size, const size_t nmemb, String* str) -> size_t {
@ -95,13 +94,13 @@ namespace {
return totalSize;
}
fn MakeApiRequest(const String& url) -> std::expected<WeatherOutput, String> {
fn MakeApiRequest(const String& url) -> Result<WeatherOutput, String> {
DEBUG_LOG("Making API request to URL: {}", url);
CURL* curl = curl_easy_init();
String responseBuffer;
if (!curl)
return std::unexpected("Failed to initialize cURL");
return Err("Failed to initialize cURL");
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
@ -113,12 +112,12 @@ namespace {
curl_easy_cleanup(curl);
if (res != CURLE_OK)
return std::unexpected(std::format("cURL error: {}", curl_easy_strerror(res)));
return Err(std::format("cURL error: {}", curl_easy_strerror(res)));
WeatherOutput output;
if (const glz::error_ctx errc = glz::read<glaze_opts>(output, responseBuffer); errc.ec != glz::error_code::none)
return std::unexpected("API response parse error: " + glz::format_error(errc, responseBuffer));
return Err("API response parse error: " + glz::format_error(errc, responseBuffer));
return std::move(output);
}
@ -127,7 +126,7 @@ namespace {
fn Weather::getWeatherInfo() const -> WeatherOutput {
using namespace std::chrono;
if (std::expected<WeatherOutput, String> data = ReadCacheFromFile()) {
if (Result<WeatherOutput, String> data = ReadCacheFromFile()) {
const WeatherOutput& dataVal = *data;
if (const duration<double> cacheAge = system_clock::now() - system_clock::time_point(seconds(dataVal.dt));
@ -141,13 +140,13 @@ fn Weather::getWeatherInfo() const -> WeatherOutput {
DEBUG_LOG("Cache error: {}", data.error());
}
fn handleApiResult = [](const std::expected<WeatherOutput, String>& result) -> WeatherOutput {
fn handleApiResult = [](const Result<WeatherOutput, String>& result) -> WeatherOutput {
if (!result) {
ERROR_LOG("API request failed: {}", result.error());
return WeatherOutput {};
}
if (std::expected<void, String> writeResult = WriteCacheToFile(*result); !writeResult)
if (Result<void, String> writeResult = WriteCacheToFile(*result); !writeResult)
ERROR_LOG("Failed to write cache: {}", writeResult.error());
return *result;
@ -155,7 +154,7 @@ fn Weather::getWeatherInfo() const -> WeatherOutput {
if (std::holds_alternative<String>(location)) {
const auto& city = std::get<String>(location);
char* escaped = curl_easy_escape(nullptr, city.c_str(), static_cast<int>(city.length()));
char* escaped = curl_easy_escape(nullptr, city.c_str(), static_cast<i32>(city.length()));
DEBUG_LOG("Requesting city: {}", escaped);
const String apiUrl =