#pragma once #ifdef _WIN32 #include #else #include // For getpwuid #include // For getuid #endif #include #include "src/util/macros.h" #include "weather.h" using Location = std::variant; struct General { string name = []() -> string { #ifdef _WIN32 std::array username; DWORD size = sizeof(username); return GetUserNameA(username.data(), &size) ? username.data() : "User"; #else if (struct passwd* pwd = getpwuid(getuid()); pwd) return pwd->pw_name; if (const char* envUser = getenv("USER")) return envUser; return "User"; #endif }(); static fn fromToml(const toml::table& tbl) -> General { General gen; if (const std::optional name = tbl["name"].value()) gen.name = *name; return gen; } }; struct NowPlaying { bool enabled = false; static fn fromToml(const toml::table& tbl) -> NowPlaying { NowPlaying nowPlaying; nowPlaying.enabled = tbl["enabled"].value().value_or(false); return nowPlaying; } }; struct Weather { bool enabled = false; bool show_town_name = false; Location location; string api_key; string units; static fn fromToml(const toml::table& tbl) -> Weather { Weather weather; weather.enabled = tbl["enabled"].value_or(false); if (auto apiKey = tbl["api_key"].value()) { const string& keyVal = apiKey.value(); if (keyVal.empty()) weather.enabled = false; weather.api_key = keyVal; } else { weather.enabled = false; } if (!weather.enabled) return weather; weather.show_town_name = tbl["show_town_name"].value_or(false); weather.units = tbl["units"].value().value_or("metric"); if (const toml::node_view location = tbl["location"]) { if (location.is_string()) { weather.location = location.value().value(); } else if (location.is_table()) { const auto* coord = location.as_table(); Coords coords; coords.lat = coord->get("lat")->value().value(); coords.lon = coord->get("lon")->value().value(); weather.location = coords; } else { throw std::runtime_error("Invalid location type"); } } return weather; } [[nodiscard]] fn getWeatherInfo() const -> WeatherOutput; }; struct Config { General general; NowPlaying now_playing; Weather weather; static fn fromToml(const toml::table& tbl) -> Config { Config cfg; if (const auto* general = tbl["general"].as_table()) cfg.general = General::fromToml(*general); if (const auto* nowPlaying = tbl["now_playing"].as_table()) cfg.now_playing = NowPlaying::fromToml(*nowPlaying); if (const auto* weather = tbl["weather"].as_table()) cfg.weather = Weather::fromToml(*weather); return cfg; } static fn getInstance() -> Config; };