:3
This commit is contained in:
parent
94d08a02d6
commit
4d1e69bbe5
|
@ -5,11 +5,13 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
#include "util/numtypes.h"
|
||||||
|
|
||||||
// Define an error type
|
// Define an error type
|
||||||
class Error {
|
class Error {
|
||||||
public:
|
public:
|
||||||
explicit Error(std::string message) : m_Message(std::move(message)) {}
|
explicit Error(std::string message) : m_Message(std::move(message)) {}
|
||||||
[[nodiscard]] const std::string& message() const { return m_Message; }
|
[[nodiscard]] fn message() const -> const std::string& { return m_Message; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_Message;
|
std::string m_Message;
|
||||||
|
@ -29,10 +31,10 @@ class Result<void> {
|
||||||
Result(Error&& error) : m_Result(std::move(error)) {}
|
Result(Error&& error) : m_Result(std::move(error)) {}
|
||||||
|
|
||||||
// Check if the result is an error
|
// Check if the result is an error
|
||||||
[[nodiscard]] bool isOk() const {
|
[[nodiscard]] fn isOk() const -> bool {
|
||||||
return std::holds_alternative<std::monostate>(m_Result);
|
return std::holds_alternative<std::monostate>(m_Result);
|
||||||
}
|
}
|
||||||
[[nodiscard]] bool isErr() const {
|
[[nodiscard]] fn isErr() const -> bool {
|
||||||
return std::holds_alternative<Error>(m_Result);
|
return std::holds_alternative<Error>(m_Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +46,7 @@ class Result<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the error or throw an exception if it is a value
|
// Get the error or throw an exception if it is a value
|
||||||
[[nodiscard]] const Error& error() const {
|
[[nodiscard]] fn error() const -> const Error& {
|
||||||
if (isOk()) {
|
if (isOk()) {
|
||||||
throw std::logic_error("Attempted to access error of an ok Result");
|
throw std::logic_error("Attempted to access error of an ok Result");
|
||||||
}
|
}
|
||||||
|
@ -66,15 +68,15 @@ class Result {
|
||||||
Result(Error&& error) : m_Result(std::move(error)) {}
|
Result(Error&& error) : m_Result(std::move(error)) {}
|
||||||
|
|
||||||
// Check if the result is an error
|
// Check if the result is an error
|
||||||
[[nodiscard]] bool isOk() const {
|
[[nodiscard]] fn isOk() const -> bool {
|
||||||
return std::holds_alternative<T>(m_Result);
|
return std::holds_alternative<T>(m_Result);
|
||||||
}
|
}
|
||||||
[[nodiscard]] bool isErr() const {
|
[[nodiscard]] fn isErr() const -> bool {
|
||||||
return std::holds_alternative<Error>(m_Result);
|
return std::holds_alternative<Error>(m_Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the value or throw an exception if it is an error
|
// Get the value or throw an exception if it is an error
|
||||||
const T& value() const {
|
fn value() const -> const T& {
|
||||||
if (isErr()) {
|
if (isErr()) {
|
||||||
throw std::logic_error("Attempted to access value of an error Result");
|
throw std::logic_error("Attempted to access value of an error Result");
|
||||||
}
|
}
|
||||||
|
@ -82,7 +84,7 @@ class Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the error or throw an exception if it is a value
|
// Get the error or throw an exception if it is a value
|
||||||
[[nodiscard]] const Error& error() const {
|
[[nodiscard]] fn error() const -> const Error& {
|
||||||
if (isOk()) {
|
if (isOk()) {
|
||||||
throw std::logic_error("Attempted to access error of an ok Result");
|
throw std::logic_error("Attempted to access error of an ok Result");
|
||||||
}
|
}
|
||||||
|
@ -90,7 +92,7 @@ class Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional: Get the value or provide a default
|
// Optional: Get the value or provide a default
|
||||||
T valueOr(const T& defaultValue) const {
|
fn valueOr(const T& defaultValue) const -> T {
|
||||||
return isOk() ? std::get<T>(m_Result) : defaultValue;
|
return isOk() ? std::get<T>(m_Result) : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +101,8 @@ class Result {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto Ok(T&& value) {
|
fn Ok(T&& value) {
|
||||||
return Result<std::decay_t<T>>(std::forward<T>(value));
|
return Result<std::decay_t<T>>(std::forward<T>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto Ok() { return Result<void>(); }
|
inline fn Ok() -> Result<void> { return {}; }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define DEFINE_GETTER(class_name, type, name) \
|
#define DEFINE_GETTER(class_name, type, name) \
|
||||||
type class_name::get##name() const { return m_##name; }
|
fn class_name::get##name() const->type { return m_##name; }
|
||||||
|
|
||||||
DEFINE_GETTER(Config, const General, General)
|
DEFINE_GETTER(Config, const General, General)
|
||||||
DEFINE_GETTER(Config, const NowPlaying, NowPlaying)
|
DEFINE_GETTER(Config, const NowPlaying, NowPlaying)
|
||||||
|
@ -12,7 +12,7 @@ DEFINE_GETTER(Weather, const Weather::Location, Location)
|
||||||
DEFINE_GETTER(Weather, const std::string, ApiKey)
|
DEFINE_GETTER(Weather, const std::string, ApiKey)
|
||||||
DEFINE_GETTER(Weather, const std::string, Units)
|
DEFINE_GETTER(Weather, const std::string, Units)
|
||||||
|
|
||||||
const Config& Config::getInstance() {
|
fn Config::getInstance() -> const Config& {
|
||||||
static const auto* INSTANCE =
|
static const auto* INSTANCE =
|
||||||
new Config(rfl::toml::load<Config>("./config.toml").value());
|
new Config(rfl::toml::load<Config>("./config.toml").value());
|
||||||
return *INSTANCE;
|
return *INSTANCE;
|
||||||
|
@ -25,14 +25,14 @@ Config::Config(General general, NowPlaying now_playing, Weather weather)
|
||||||
|
|
||||||
General::General(std::string name) : m_Name(std::move(name)) {}
|
General::General(std::string name) : m_Name(std::move(name)) {}
|
||||||
|
|
||||||
NowPlaying::NowPlaying(bool enable) : m_Enabled(enable) {}
|
NowPlaying::NowPlaying(bool enabled) : m_Enabled(enabled) {}
|
||||||
|
|
||||||
Weather::Weather(Location location, std::string api_key, std::string units)
|
Weather::Weather(Location location, std::string api_key, std::string units)
|
||||||
: m_Location(std::move(location)),
|
: m_Location(std::move(location)),
|
||||||
m_ApiKey(std::move(api_key)),
|
m_ApiKey(std::move(api_key)),
|
||||||
m_Units(std::move(units)) {}
|
m_Units(std::move(units)) {}
|
||||||
|
|
||||||
WeatherImpl WeatherImpl::from_class(const Weather& weather) noexcept {
|
fn WeatherImpl::from_class(const Weather& weather) noexcept -> WeatherImpl {
|
||||||
return {
|
return {
|
||||||
.location = weather.getLocation(),
|
.location = weather.getLocation(),
|
||||||
.api_key = weather.getApiKey(),
|
.api_key = weather.getApiKey(),
|
||||||
|
@ -40,22 +40,27 @@ WeatherImpl WeatherImpl::from_class(const Weather& weather) noexcept {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Weather WeatherImpl::to_class() const { return {location, api_key, units}; }
|
fn WeatherImpl::to_class() const -> Weather {
|
||||||
|
return {location, api_key, units};
|
||||||
|
}
|
||||||
|
|
||||||
GeneralImpl GeneralImpl::from_class(const General& general) noexcept {
|
fn GeneralImpl::from_class(const General& general) noexcept -> GeneralImpl {
|
||||||
return {general.getName()};
|
return {general.getName()};
|
||||||
}
|
}
|
||||||
|
|
||||||
General GeneralImpl::to_class() const { return {name}; }
|
fn GeneralImpl::to_class() const -> General { return {name}; }
|
||||||
|
|
||||||
NowPlayingImpl NowPlayingImpl::from_class(
|
// clang-format off
|
||||||
const NowPlaying& now_playing) noexcept {
|
fn NowPlayingImpl::from_class(
|
||||||
|
const NowPlaying& now_playing
|
||||||
|
) noexcept -> NowPlayingImpl {
|
||||||
return {.enabled = now_playing.getEnabled()};
|
return {.enabled = now_playing.getEnabled()};
|
||||||
}
|
}
|
||||||
|
//clang-format on
|
||||||
|
|
||||||
NowPlaying NowPlayingImpl::to_class() const { return {enabled}; }
|
fn NowPlayingImpl::to_class() const -> NowPlaying { return {enabled}; }
|
||||||
|
|
||||||
ConfigImpl ConfigImpl::from_class(const Config& config) noexcept {
|
fn ConfigImpl::from_class(const Config& config) noexcept -> ConfigImpl {
|
||||||
return {
|
return {
|
||||||
.general = config.getGeneral(),
|
.general = config.getGeneral(),
|
||||||
.now_playing = config.getNowPlaying(),
|
.now_playing = config.getNowPlaying(),
|
||||||
|
@ -63,4 +68,6 @@ ConfigImpl ConfigImpl::from_class(const Config& config) noexcept {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Config ConfigImpl::to_class() const { return {general, now_playing, weather}; }
|
fn ConfigImpl::to_class() const -> Config {
|
||||||
|
return {general, now_playing, weather};
|
||||||
|
}
|
||||||
|
|
|
@ -10,30 +10,30 @@
|
||||||
|
|
||||||
class Weather {
|
class Weather {
|
||||||
public:
|
public:
|
||||||
using percentage = rfl::Validator<i8, rfl::Minimum<0>, rfl::Maximum<100>>;
|
|
||||||
using degrees = rfl::Validator<u16, rfl::Minimum<0>, rfl::Maximum<360>>;
|
using degrees = rfl::Validator<u16, rfl::Minimum<0>, rfl::Maximum<360>>;
|
||||||
|
using percentage = rfl::Validator<i8, rfl::Minimum<0>, rfl::Maximum<100>>;
|
||||||
|
|
||||||
struct Condition {
|
struct Condition {
|
||||||
usize id;
|
|
||||||
rfl::Rename<"main", std::string> group;
|
|
||||||
std::string description;
|
std::string description;
|
||||||
rfl::Rename<"icon", std::string> icon_id;
|
std::string icon;
|
||||||
|
std::string main;
|
||||||
|
usize id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Main {
|
struct Main {
|
||||||
f64 temp;
|
f64 feels_like;
|
||||||
f64 temp_max;
|
f64 temp;
|
||||||
f64 temp_min;
|
f64 temp_max;
|
||||||
f64 feels_like;
|
f64 temp_min;
|
||||||
isize pressure;
|
isize pressure;
|
||||||
std::optional<isize> sea_level;
|
percentage humidity;
|
||||||
std::optional<isize> grnd_level;
|
std::optional<isize> grnd_level;
|
||||||
percentage humidity;
|
std::optional<isize> sea_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Wind {
|
struct Wind {
|
||||||
f64 speed;
|
degrees deg;
|
||||||
degrees deg;
|
f64 speed;
|
||||||
std::optional<f64> gust;
|
std::optional<f64> gust;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,10 +44,10 @@ class Weather {
|
||||||
|
|
||||||
struct Sys {
|
struct Sys {
|
||||||
std::string country;
|
std::string country;
|
||||||
usize id;
|
usize id;
|
||||||
usize sunrise;
|
usize sunrise;
|
||||||
usize sunset;
|
usize sunset;
|
||||||
usize type;
|
usize type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Clouds {
|
struct Clouds {
|
||||||
|
@ -60,47 +60,47 @@ class Weather {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WeatherOutput {
|
struct WeatherOutput {
|
||||||
isize timezone;
|
Clouds clouds;
|
||||||
isize visibility;
|
Main main;
|
||||||
Main main;
|
Sys sys;
|
||||||
Clouds clouds;
|
Wind wind;
|
||||||
|
isize timezone;
|
||||||
|
isize visibility;
|
||||||
rfl::Rename<"coord", Coords> coords;
|
rfl::Rename<"coord", Coords> coords;
|
||||||
std::optional<Precipitation> rain;
|
std::optional<Precipitation> rain;
|
||||||
std::optional<Precipitation> snow;
|
std::optional<Precipitation> snow;
|
||||||
std::vector<Condition> weather;
|
std::string base;
|
||||||
std::string base;
|
std::string name;
|
||||||
std::string name;
|
std::vector<Condition> weather;
|
||||||
Sys sys;
|
usize cod;
|
||||||
usize cod;
|
usize dt;
|
||||||
usize dt;
|
usize id;
|
||||||
usize id;
|
|
||||||
Wind wind;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using Location = std::variant<std::string, Coords>;
|
using Location = std::variant<std::string, Coords>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Location m_Location;
|
Location m_Location;
|
||||||
std::string m_ApiKey;
|
std::string m_ApiKey;
|
||||||
std::string m_Units;
|
std::string m_Units;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Weather(Location location, std::string api_key, std::string units);
|
Weather(Location location, std::string api_key, std::string units);
|
||||||
|
|
||||||
[[nodiscard]] WeatherOutput getWeatherInfo() const;
|
[[nodiscard]] fn getWeatherInfo() const -> WeatherOutput;
|
||||||
[[nodiscard]] const Location getLocation() const;
|
[[nodiscard]] fn getLocation() const -> const Location;
|
||||||
[[nodiscard]] const std::string getApiKey() const;
|
[[nodiscard]] fn getApiKey() const -> const std::string;
|
||||||
[[nodiscard]] const std::string getUnits() const;
|
[[nodiscard]] fn getUnits() const -> const std::string;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WeatherImpl {
|
struct WeatherImpl {
|
||||||
Weather::Location location;
|
Weather::Location location;
|
||||||
std::string api_key;
|
std::string api_key;
|
||||||
std::string units;
|
std::string units;
|
||||||
|
|
||||||
static WeatherImpl from_class(const Weather& weather) noexcept;
|
static fn from_class(const Weather& weather) noexcept -> WeatherImpl;
|
||||||
|
|
||||||
[[nodiscard]] Weather to_class() const;
|
[[nodiscard]] fn to_class() const -> Weather;
|
||||||
};
|
};
|
||||||
|
|
||||||
class General {
|
class General {
|
||||||
|
@ -110,15 +110,15 @@ class General {
|
||||||
public:
|
public:
|
||||||
General(std::string name);
|
General(std::string name);
|
||||||
|
|
||||||
[[nodiscard]] const std::string getName() const;
|
[[nodiscard]] fn getName() const -> const std::string;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GeneralImpl {
|
struct GeneralImpl {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
static GeneralImpl from_class(const General& general) noexcept;
|
static fn from_class(const General& general) noexcept -> GeneralImpl;
|
||||||
|
|
||||||
[[nodiscard]] General to_class() const;
|
[[nodiscard]] fn to_class() const -> General;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NowPlaying {
|
class NowPlaying {
|
||||||
|
@ -128,74 +128,79 @@ class NowPlaying {
|
||||||
public:
|
public:
|
||||||
NowPlaying(bool enabled);
|
NowPlaying(bool enabled);
|
||||||
|
|
||||||
[[nodiscard]] bool getEnabled() const;
|
[[nodiscard]] fn getEnabled() const -> bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NowPlayingImpl {
|
struct NowPlayingImpl {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
static NowPlayingImpl from_class(const NowPlaying& now_playing) noexcept;
|
static fn from_class(const NowPlaying& now_playing
|
||||||
|
) noexcept -> NowPlayingImpl;
|
||||||
|
|
||||||
[[nodiscard]] NowPlaying to_class() const;
|
[[nodiscard]] fn to_class() const -> NowPlaying;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Config {
|
class Config {
|
||||||
private:
|
private:
|
||||||
General m_General;
|
General m_General;
|
||||||
NowPlaying m_NowPlaying;
|
NowPlaying m_NowPlaying;
|
||||||
Weather m_Weather;
|
Weather m_Weather;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Config(General general, NowPlaying now_playing, Weather weather);
|
Config(General general, NowPlaying now_playing, Weather weather);
|
||||||
|
|
||||||
static const Config& getInstance();
|
static fn getInstance() -> const Config&;
|
||||||
|
|
||||||
[[nodiscard]] const Weather getWeather() const;
|
[[nodiscard]] fn getWeather() const -> const Weather;
|
||||||
[[nodiscard]] const General getGeneral() const;
|
[[nodiscard]] fn getGeneral() const -> const General;
|
||||||
[[nodiscard]] const NowPlaying getNowPlaying() const;
|
[[nodiscard]] fn getNowPlaying() const -> const NowPlaying;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConfigImpl {
|
struct ConfigImpl {
|
||||||
General general;
|
General general;
|
||||||
NowPlaying now_playing;
|
NowPlaying now_playing;
|
||||||
Weather weather;
|
Weather weather;
|
||||||
|
|
||||||
static ConfigImpl from_class(const Config& config) noexcept;
|
static fn from_class(const Config& config) noexcept -> ConfigImpl;
|
||||||
|
|
||||||
[[nodiscard]] Config to_class() const;
|
[[nodiscard]] fn to_class() const -> Config;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parsers for Config classes
|
// Parsers for Config classes
|
||||||
namespace rfl::parsing {
|
namespace rfl::parsing {
|
||||||
template <class ReaderType, class WriterType, class ProcessorsType>
|
template <class ReaderType, class WriterType, class ProcessorsType>
|
||||||
struct Parser<ReaderType, WriterType, Weather, ProcessorsType>
|
struct Parser<ReaderType, WriterType, Weather, ProcessorsType>
|
||||||
: public CustomParser<ReaderType,
|
: public CustomParser<
|
||||||
WriterType,
|
ReaderType,
|
||||||
ProcessorsType,
|
WriterType,
|
||||||
Weather,
|
ProcessorsType,
|
||||||
WeatherImpl> {};
|
Weather,
|
||||||
|
WeatherImpl> {};
|
||||||
|
|
||||||
template <class ReaderType, class WriterType, class ProcessorsType>
|
template <class ReaderType, class WriterType, class ProcessorsType>
|
||||||
struct Parser<ReaderType, WriterType, General, ProcessorsType>
|
struct Parser<ReaderType, WriterType, General, ProcessorsType>
|
||||||
: public CustomParser<ReaderType,
|
: public CustomParser<
|
||||||
WriterType,
|
ReaderType,
|
||||||
ProcessorsType,
|
WriterType,
|
||||||
General,
|
ProcessorsType,
|
||||||
GeneralImpl> {};
|
General,
|
||||||
|
GeneralImpl> {};
|
||||||
|
|
||||||
template <class ReaderType, class WriterType, class ProcessorsType>
|
template <class ReaderType, class WriterType, class ProcessorsType>
|
||||||
struct Parser<ReaderType, WriterType, NowPlaying, ProcessorsType>
|
struct Parser<ReaderType, WriterType, NowPlaying, ProcessorsType>
|
||||||
: public CustomParser<ReaderType,
|
: public CustomParser<
|
||||||
WriterType,
|
ReaderType,
|
||||||
ProcessorsType,
|
WriterType,
|
||||||
NowPlaying,
|
ProcessorsType,
|
||||||
NowPlayingImpl> {};
|
NowPlaying,
|
||||||
|
NowPlayingImpl> {};
|
||||||
|
|
||||||
template <class ReaderType, class WriterType, class ProcessorsType>
|
template <class ReaderType, class WriterType, class ProcessorsType>
|
||||||
struct Parser<ReaderType, WriterType, Config, ProcessorsType>
|
struct Parser<ReaderType, WriterType, Config, ProcessorsType>
|
||||||
: public CustomParser<ReaderType,
|
: public CustomParser<
|
||||||
WriterType,
|
ReaderType,
|
||||||
ProcessorsType,
|
WriterType,
|
||||||
Config,
|
ProcessorsType,
|
||||||
ConfigImpl> {};
|
Config,
|
||||||
|
ConfigImpl> {};
|
||||||
} // namespace rfl::parsing
|
} // namespace rfl::parsing
|
||||||
|
|
|
@ -8,11 +8,12 @@
|
||||||
using WeatherOutput = Weather::WeatherOutput;
|
using WeatherOutput = Weather::WeatherOutput;
|
||||||
|
|
||||||
// Function to read cache from file
|
// Function to read cache from file
|
||||||
Result<WeatherOutput> ReadCacheFromFile() {
|
fn ReadCacheFromFile() -> Result<WeatherOutput> {
|
||||||
const std::string cacheFile = "/tmp/weather_cache.json";
|
const std::string cacheFile = "/tmp/weather_cache.json";
|
||||||
std::ifstream ifs(cacheFile);
|
std::ifstream ifs(cacheFile);
|
||||||
|
|
||||||
if (!ifs.is_open()) return Error("Cache file not found.");
|
if (!ifs.is_open())
|
||||||
|
return Error("Cache file not found.");
|
||||||
|
|
||||||
fmt::println("Reading from cache file...");
|
fmt::println("Reading from cache file...");
|
||||||
|
|
||||||
|
@ -32,12 +33,13 @@ Result<WeatherOutput> ReadCacheFromFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to write cache to file
|
// Function to write cache to file
|
||||||
Result<> WriteCacheToFile(const WeatherOutput& data) {
|
fn WriteCacheToFile(const WeatherOutput& data) -> Result<> {
|
||||||
const std::string cacheFile = "/tmp/weather_cache.json";
|
const std::string cacheFile = "/tmp/weather_cache.json";
|
||||||
fmt::println("Writing to cache file...");
|
fmt::println("Writing to cache file...");
|
||||||
std::ofstream ofs(cacheFile);
|
std::ofstream ofs(cacheFile);
|
||||||
|
|
||||||
if (!ofs.is_open()) return Error("Failed to open cache file for writing.");
|
if (!ofs.is_open())
|
||||||
|
return Error("Failed to open cache file for writing.");
|
||||||
|
|
||||||
ofs << rfl::json::write(data);
|
ofs << rfl::json::write(data);
|
||||||
|
|
||||||
|
@ -46,10 +48,8 @@ Result<> WriteCacheToFile(const WeatherOutput& data) {
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t WriteCallback(void* contents,
|
fn WriteCallback(void* contents, size_t size, size_t nmemb, std::string* buffer)
|
||||||
size_t size,
|
-> size_t {
|
||||||
size_t nmemb,
|
|
||||||
std::string* buffer) {
|
|
||||||
size_t realsize = size * nmemb;
|
size_t realsize = size * nmemb;
|
||||||
|
|
||||||
buffer->append(static_cast<char*>(contents), realsize);
|
buffer->append(static_cast<char*>(contents), realsize);
|
||||||
|
@ -58,7 +58,7 @@ size_t WriteCallback(void* contents,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to make API request
|
// Function to make API request
|
||||||
Result<WeatherOutput> MakeApiRequest(const std::string& url) {
|
fn MakeApiRequest(const std::string& url) -> Result<WeatherOutput> {
|
||||||
fmt::println("Making API request...");
|
fmt::println("Making API request...");
|
||||||
|
|
||||||
CURL* curl = curl_easy_init();
|
CURL* curl = curl_easy_init();
|
||||||
|
@ -73,8 +73,9 @@ Result<WeatherOutput> MakeApiRequest(const std::string& url) {
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if (res != CURLE_OK)
|
if (res != CURLE_OK)
|
||||||
return Error(fmt::format("Failed to perform cURL request: {}",
|
return Error(fmt::format(
|
||||||
curl_easy_strerror(res)));
|
"Failed to perform cURL request: {}", curl_easy_strerror(res)
|
||||||
|
));
|
||||||
|
|
||||||
fmt::println("Received response from API.");
|
fmt::println("Received response from API.");
|
||||||
// Parse the JSON response
|
// Parse the JSON response
|
||||||
|
@ -88,10 +89,10 @@ Result<WeatherOutput> MakeApiRequest(const std::string& url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Core function to get weather information
|
// Core function to get weather information
|
||||||
WeatherOutput Weather::getWeatherInfo() const {
|
fn Weather::getWeatherInfo() const -> WeatherOutput {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
const Location loc = m_Location;
|
const Location loc = m_Location;
|
||||||
const std::string apiKey = m_ApiKey;
|
const std::string apiKey = m_ApiKey;
|
||||||
const std::string units = m_Units;
|
const std::string units = m_Units;
|
||||||
|
|
||||||
|
@ -116,15 +117,19 @@ WeatherOutput Weather::getWeatherInfo() const {
|
||||||
if (holds_alternative<std::string>(loc)) {
|
if (holds_alternative<std::string>(loc)) {
|
||||||
const std::string city = get<std::string>(loc);
|
const std::string city = get<std::string>(loc);
|
||||||
|
|
||||||
const char* location = curl_easy_escape(nullptr, city.c_str(),
|
const char* location = curl_easy_escape(
|
||||||
static_cast<int>(city.length()));
|
nullptr, city.c_str(), static_cast<int>(city.length())
|
||||||
|
);
|
||||||
|
|
||||||
fmt::println("City: {}", location);
|
fmt::println("City: {}", location);
|
||||||
|
|
||||||
const std::string apiUrl = fmt::format(
|
const std::string apiUrl = fmt::format(
|
||||||
"https://api.openweathermap.org/data/2.5/"
|
"https://api.openweathermap.org/data/2.5/"
|
||||||
"weather?q={}&appid={}&units={}",
|
"weather?q={}&appid={}&units={}",
|
||||||
location, apiKey, units);
|
location,
|
||||||
|
apiKey,
|
||||||
|
units
|
||||||
|
);
|
||||||
|
|
||||||
result = MakeApiRequest(apiUrl).value();
|
result = MakeApiRequest(apiUrl).value();
|
||||||
} else {
|
} else {
|
||||||
|
@ -135,7 +140,11 @@ WeatherOutput Weather::getWeatherInfo() const {
|
||||||
const std::string apiUrl = fmt::format(
|
const std::string apiUrl = fmt::format(
|
||||||
"https://api.openweathermap.org/data/2.5/"
|
"https://api.openweathermap.org/data/2.5/"
|
||||||
"weather?lat={:.3f}&lon={:.3f}&appid={}&units={}",
|
"weather?lat={:.3f}&lon={:.3f}&appid={}&units={}",
|
||||||
lat, lon, apiKey, units);
|
lat,
|
||||||
|
lon,
|
||||||
|
apiKey,
|
||||||
|
units
|
||||||
|
);
|
||||||
|
|
||||||
result = MakeApiRequest(apiUrl).value();
|
result = MakeApiRequest(apiUrl).value();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,14 @@ struct BytesToGiB {
|
||||||
u64 value;
|
u64 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr u64 GIB = 1'073'741'824;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct fmt::formatter<BytesToGiB> : formatter<double> {
|
struct fmt::formatter<BytesToGiB> : formatter<double> {
|
||||||
template <typename FmtCtx>
|
template <typename FmtCtx>
|
||||||
fn format(const BytesToGiB BTG, FmtCtx& ctx) -> typename FmtCtx::iterator {
|
fn format(const BytesToGiB BTG, FmtCtx& ctx) -> typename FmtCtx::iterator {
|
||||||
typename FmtCtx::iterator out = formatter<double>::format(
|
typename FmtCtx::iterator out =
|
||||||
static_cast<double>(BTG.value) / pow(1024, 3), ctx
|
formatter<double>::format(static_cast<double>(BTG.value) / GIB, ctx);
|
||||||
);
|
|
||||||
*out++ = 'G';
|
*out++ = 'G';
|
||||||
*out++ = 'i';
|
*out++ = 'i';
|
||||||
*out++ = 'B';
|
*out++ = 'B';
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "macos/bridge.h"
|
#include "macos/bridge.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
u64 GetMemInfo() {
|
fn GetMemInfo() -> u64 {
|
||||||
u64 mem = 0;
|
u64 mem = 0;
|
||||||
usize size = sizeof(mem);
|
usize size = sizeof(mem);
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ u64 GetMemInfo() {
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetNowPlaying() {
|
fn GetNowPlaying() -> std::string {
|
||||||
if (const char* title = GetCurrentPlayingTitle();
|
if (const char* title = GetCurrentPlayingTitle();
|
||||||
const char* artist = GetCurrentPlayingArtist())
|
const char* artist = GetCurrentPlayingArtist())
|
||||||
return "Now Playing: " + std::string(artist) + " - " + std::string(title);
|
return "Now Playing: " + std::string(artist) + " - " + std::string(title);
|
||||||
|
@ -22,6 +22,6 @@ std::string GetNowPlaying() {
|
||||||
return "No song playing";
|
return "No song playing";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetOSVersion() { return GetMacOSVersion(); };
|
fn GetOSVersion() -> const char* { return GetMacOSVersion(); };
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,10 +9,12 @@
|
||||||
+ (NSString*)macOSVersion;
|
+ (NSString*)macOSVersion;
|
||||||
@end
|
@end
|
||||||
#else
|
#else
|
||||||
|
#include "util/numtypes.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
const char* GetCurrentPlayingTitle();
|
fn GetCurrentPlayingTitle() -> const char*;
|
||||||
const char* GetCurrentPlayingArtist();
|
fn GetCurrentPlayingArtist() -> const char*;
|
||||||
const char* GetMacOSVersion();
|
fn GetMacOSVersion() -> const char*;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -79,7 +79,8 @@ using MRMediaRemoteGetNowPlayingInfoFunction = void (*)(
|
||||||
NSNumber* majorVersionNumber = @(osVersion.majorVersion);
|
NSNumber* majorVersionNumber = @(osVersion.majorVersion);
|
||||||
NSString* versionName = versionNames[majorVersionNumber];
|
NSString* versionName = versionNames[majorVersionNumber];
|
||||||
|
|
||||||
if (versionName == nil) versionName = @"Unknown";
|
if (versionName == nil)
|
||||||
|
versionName = @"Unknown";
|
||||||
|
|
||||||
NSString* fullVersion =
|
NSString* fullVersion =
|
||||||
[NSString stringWithFormat:@"macOS %@ %@", version, versionName];
|
[NSString stringWithFormat:@"macOS %@ %@", version, versionName];
|
||||||
|
@ -88,37 +89,44 @@ using MRMediaRemoteGetNowPlayingInfoFunction = void (*)(
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#include "util/numtypes.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
const char* GetCurrentPlayingTitle() {
|
fn GetCurrentPlayingTitle() -> const char* {
|
||||||
NSDictionary* metadata = [Bridge currentPlayingMetadata];
|
NSDictionary* metadata = [Bridge currentPlayingMetadata];
|
||||||
|
|
||||||
if (metadata == nil) return nullptr;
|
if (metadata == nil)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
NSString* title =
|
NSString* title =
|
||||||
[metadata objectForKey:@"kMRMediaRemoteNowPlayingInfoTitle"];
|
[metadata objectForKey:@"kMRMediaRemoteNowPlayingInfoTitle"];
|
||||||
|
|
||||||
if (title) return strdup([title UTF8String]);
|
if (title)
|
||||||
|
return strdup([title UTF8String]);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetCurrentPlayingArtist() {
|
fn GetCurrentPlayingArtist() -> const char* {
|
||||||
NSDictionary* metadata = [Bridge currentPlayingMetadata];
|
NSDictionary* metadata = [Bridge currentPlayingMetadata];
|
||||||
|
|
||||||
if (metadata == nil) return nullptr;
|
if (metadata == nil)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
NSString* artist =
|
NSString* artist =
|
||||||
[metadata objectForKey:@"kMRMediaRemoteNowPlayingInfoArtist"];
|
[metadata objectForKey:@"kMRMediaRemoteNowPlayingInfoArtist"];
|
||||||
|
|
||||||
if (artist) return strdup([artist UTF8String]);
|
if (artist)
|
||||||
|
return strdup([artist UTF8String]);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetMacOSVersion() {
|
fn GetMacOSVersion() -> const char* {
|
||||||
NSString* version = [Bridge macOSVersion];
|
NSString* version = [Bridge macOSVersion];
|
||||||
|
|
||||||
if (version) return strdup([version UTF8String]);
|
if (version)
|
||||||
|
return strdup([version UTF8String]);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue