#include #include #include #include #include "config.h" using rfl::Error; using rfl::Result; // Function to read cache from file fn ReadCacheFromFile()->Result { #ifdef __WIN32__ const char* tempPath = getenv("TEMP"); const string path = string(tempPath) + "\\weather_cache.json"; std::ifstream ifs(path); #else std::ifstream ifs("/tmp/weather_cache.json"); #endif if (!ifs.is_open()) return Error("Cache file not found."); fmt::println("Reading from cache file..."); std::stringstream buf; buf << ifs.rdbuf(); Result val = rfl::json::read(buf.str()); fmt::println("Successfully read from cache file."); return val; } // Function to write cache to file fn WriteCacheToFile(const WeatherOutput& data)->Result { fmt::println("Writing to cache file..."); #ifdef __WIN32__ const char* tempPath = getenv("TEMP"); const string path = string(tempPath) + "\\weather_cache.json"; std::ofstream ofs(path); #else std::ofstream ofs("/tmp/weather_cache.json"); #endif if (!ofs.is_open()) return Error("Failed to open cache file for writing."); ofs << rfl::json::write(data); fmt::println("Successfully wrote to cache file."); return 0; } fn WriteCallback(void* contents, const size_t size, const size_t nmemb, string* str)->size_t { const size_t totalSize = size * nmemb; str->append(static_cast(contents), totalSize); return totalSize; } // Function to make API request fn MakeApiRequest(const string& url)->Result { fmt::println("Making API request to URL: {}", url); CURL* curl = curl_easy_init(); string responseBuffer; if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseBuffer); const CURLcode res = curl_easy_perform(curl); curl_easy_cleanup(curl); if (res != CURLE_OK) return Error(fmt::format("Failed to perform cURL request: {}", curl_easy_strerror(res))); fmt::println("Received response from API. Response size: {}", responseBuffer.size()); fmt::println("Response: {}", responseBuffer); WeatherOutput output = rfl::json::read(responseBuffer).value(); return output; // Return an empty result for now } return Error("Failed to initialize cURL."); } // Core function to get weather information fn Weather::getWeatherInfo() const->WeatherOutput { using namespace std::chrono; // Check if cache is valid if (Result data = ReadCacheFromFile()) { if (WeatherOutput dataVal = *data; system_clock::now() - system_clock::time_point(seconds(dataVal.dt)) < minutes(10)) { // Assuming cache duration is always 10 minutes fmt::println("Cache is valid. Returning cached data."); return dataVal; } fmt::println("Cache is expired."); } else { fmt::println("No valid cache found."); } WeatherOutput result; if (holds_alternative(location)) { const string city = get(location); const char* loc = curl_easy_escape(nullptr, city.c_str(), static_cast(city.length())); fmt::println("City: {}", loc); const string apiUrl = fmt::format( "https://api.openweathermap.org/data/2.5/" "weather?q={}&appid={}&units={}", loc, api_key, units ); result = MakeApiRequest(apiUrl).value(); } else { const auto [lat, lon] = get(location); fmt::println("Coordinates: lat = {:.3f}, lon = {:.3f}", lat, lon); const string apiUrl = fmt::format( "https://api.openweathermap.org/data/2.5/" "weather?lat={:.3f}&lon={:.3f}&appid={}&units={}", lat, lon, api_key, units ); result = MakeApiRequest(apiUrl).value(); } // Update the cache with the new data WriteCacheToFile(result); fmt::println("Returning new data."); return result; }