diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d756b71e..83e9d6d53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -309,7 +309,7 @@ set(LIBFASTFETCH_SRC src/modules/users/users.c src/modules/vulkan/vulkan.c src/modules/wallpaper/wallpaper.c - src/modules/weather.c + src/modules/weather/weather.c src/modules/wifi/wifi.c src/modules/wm/wm.c src/modules/wmtheme/wmtheme.c diff --git a/src/common/init.c b/src/common/init.c index 20354358c..1437bf584 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -91,7 +91,7 @@ static void defaultConfig(FFinstance* instance) ffInitLocaleOptions(&instance->config.locale); ffInitLocalIpOptions(&instance->config.localIP); ffInitPublicIpOptions(&instance->config.publicIP); - initModuleArg(&instance->config.weather); + ffInitWeatherOptions(&instance->config.weather); ffInitWifiOptions(&instance->config.wifi); ffInitPlayerOptions(&instance->config.player); ffInitMediaOptions(&instance->config.media); @@ -132,9 +132,6 @@ static void defaultConfig(FFinstance* instance) ffStrbufInit(&instance->config.libwlanapi); ffStrbufInit(&instance->config.libnm); - instance->config.weatherTimeout = 0; - ffStrbufInitS(&instance->config.weatherOutputFormat, "%t+-+%C+(%l)"); - instance->config.percentType = 1; } @@ -306,7 +303,7 @@ static void destroyConfig(FFinstance* instance) ffDestroyLocalIpOptions(&instance->config.localIP); ffDestroyPublicIpOptions(&instance->config.publicIP); ffDestroyWallpaperOptions(&instance->config.wallpaper); - destroyModuleArg(&instance->config.weather); + ffDestroyWeatherOptions(&instance->config.weather); ffDestroyWifiOptions(&instance->config.wifi); ffDestroyPlayerOptions(&instance->config.player); ffDestroyMediaOptions(&instance->config.media); @@ -345,8 +342,6 @@ static void destroyConfig(FFinstance* instance) ffStrbufDestroy(&instance->config.libPulse); ffStrbufDestroy(&instance->config.libwlanapi); ffStrbufDestroy(&instance->config.libnm); - - ffStrbufDestroy(&instance->config.weatherOutputFormat); } static void destroyState(FFinstance* instance) diff --git a/src/fastfetch.c b/src/fastfetch.c index 1744bd57c..e52b6693b 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1010,7 +1010,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(ffParseLocaleCommandOptions(&instance->config.locale, key, value)) {} else if(ffParseLocalIpCommandOptions(&instance->config.localIP, key, value)) {} else if(ffParsePublicIpCommandOptions(&instance->config.publicIP, key, value)) {} - else if(optionParseModuleArgs(key, value, "weather", &instance->config.weather)) {} + else if(ffParseWeatherCommandOptions(&instance->config.weather, key, value)) {} else if(ffParsePlayerCommandOptions(&instance->config.player, key, value)) {} else if(ffParseMediaCommandOptions(&instance->config.media, key, value)) {} else if(ffParseDateTimeCommandOptions(&instance->config.dateTime, key, value)) {} @@ -1088,10 +1088,6 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con //Module options// ////////////////// - else if(strcasecmp(key, "--weather-output-format") == 0) - optionParseString(key, value, &instance->config.weatherOutputFormat); - else if(strcasecmp(key, "--weather-timeout") == 0) - instance->config.weatherTimeout = optionParseUInt32(key, value); else if(strcasecmp(key, "--percent-type") == 0) instance->config.percentType = optionParseUInt32(key, value); @@ -1222,8 +1218,8 @@ static void parseStructureCommand(FFinstance* instance, const char* line) ffPrintPublicIp(instance, &instance->config.publicIP); else if(strcasecmp(line, FF_WIFI_MODULE_NAME) == 0) ffPrintWifi(instance, &instance->config.wifi); - else if(strcasecmp(line, "weather") == 0) - ffPrintWeather(instance); + else if(strcasecmp(line, FF_WEATHER_MODULE_NAME) == 0) + ffPrintWeather(instance, &instance->config.weather); else if(strcasecmp(line, FF_PLAYER_MODULE_NAME) == 0) ffPrintPlayer(instance, &instance->config.player); else if(strcasecmp(line, FF_MEDIA_MODULE_NAME) == 0) @@ -1280,8 +1276,8 @@ int main(int argc, const char** argv) if(ffStrbufContainIgnCaseS(&data.structure, FF_PUBLICIP_MODULE_NAME)) ffPreparePublicIp(&instance.config.publicIP); - if(ffStrbufContainIgnCaseS(&data.structure, "Weather")) - ffPrepareWeather(&instance); + if(ffStrbufContainIgnCaseS(&data.structure, FF_WEATHER_MODULE_NAME)) + ffPrepareWeather(&instance.config.weather); } ffStart(&instance); diff --git a/src/fastfetch.h b/src/fastfetch.h index 2c159059f..1818934b6 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -84,7 +84,7 @@ typedef struct FFconfig FFLocaleOptions locale; FFLocalIpOptions localIP; FFPublicIpOptions publicIP; - FFModuleArgs weather; + FFWeatherOptions weather; FFPlayerOptions player; FFMediaOptions media; FFDateTimeOptions dateTime; @@ -123,9 +123,6 @@ typedef struct FFconfig FFstrbuf libwlanapi; FFstrbuf libnm; - FFstrbuf weatherOutputFormat; - uint32_t weatherTimeout; - uint32_t percentType; bool jsonConfig; @@ -175,15 +172,10 @@ void ffLogoBuiltinListAutocompletion(); // Module functions // ////////////////////// -//Common - -void ffPrepareWeather(FFinstance* instance); - //Printing void ffPrintChassis(FFinstance* instance); void ffPrintProcesses(FFinstance* instance); void ffPrintTheme(FFinstance* instance); -void ffPrintWeather(FFinstance* instance); #endif diff --git a/src/flashfetch.c b/src/flashfetch.c index e00d2b48b..ffa0a9040 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -64,7 +64,7 @@ int main(int argc, char** argv) //ffPrintOpenGL(&instance, &instance.config.openGL); //ffPrintOpenCL(&instance, &instance.config.openCL); //ffPrintUsers(&instance, &instance.config.users); - //ffPrintWeather(&instance); + //ffPrintWeather(&instance, &instance.config.weather); //ffPrintBluetooth(&instance); //ffPrintSound(&instance, &instance.config.sound); //ffPrintGamepad(&instance); diff --git a/src/modules/jsonconfig/jsonconfig.c b/src/modules/jsonconfig/jsonconfig.c index c248d0114..ba297c633 100644 --- a/src/modules/jsonconfig/jsonconfig.c +++ b/src/modules/jsonconfig/jsonconfig.c @@ -152,6 +152,7 @@ static bool parseModuleJsonObject(FFinstance* instance, const char* type, json_o case 'W': { return tryModule(instance, type, module, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperJsonObject) || + tryModule(instance, type, module, FF_WEATHER_MODULE_NAME, ffParseWeatherJsonObject) || tryModule(instance, type, module, FF_WM_MODULE_NAME, ffParseWMJsonObject) || tryModule(instance, type, module, FF_WIFI_MODULE_NAME, ffParseWifiJsonObject) || tryModule(instance, type, module, FF_WMTHEME_MODULE_NAME, ffParseWMThemeJsonObject) || diff --git a/src/modules/modules.h b/src/modules/modules.h index b28e1d1e4..c4b8af7b3 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -47,6 +47,7 @@ #include "modules/users/users.h" #include "modules/vulkan/vulkan.h" #include "modules/wallpaper/wallpaper.h" +#include "modules/weather/weather.h" #include "modules/wifi/wifi.h" #include "modules/wm/wm.h" #include "modules/wmtheme/wmtheme.h" diff --git a/src/modules/options.h b/src/modules/options.h index cfdefd52b..159f41e10 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -44,6 +44,7 @@ #include "modules/users/option.h" #include "modules/vulkan/option.h" #include "modules/wallpaper/option.h" +#include "modules/weather/option.h" #include "modules/wifi/option.h" #include "modules/wm/option.h" #include "modules/wmtheme/option.h" diff --git a/src/modules/weather.c b/src/modules/weather.c deleted file mode 100644 index f26cd4de9..000000000 --- a/src/modules/weather.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "fastfetch.h" -#include "common/printing.h" -#include "common/networking.h" - -#define FF_WEATHER_MODULE_NAME "Weather" -#define FF_WEATHER_NUM_FORMAT_ARGS 1 - -static FFNetworkingState state; -static int status = -1; - -void ffPrepareWeather(FFinstance* instance) -{ - FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/?format="); - ffStrbufAppend(&path, &instance->config.weatherOutputFormat); - status = ffNetworkingSendHttpRequest(&state, "wttr.in", path.chars, "User-Agent: curl/0.0.0\r\n"); -} - -void ffPrintWeather(FFinstance* instance) -{ - if(status == -1) - ffPrepareWeather(instance); - - if(status == 0) - { - ffPrintError(instance, FF_WEATHER_MODULE_NAME, 0, &instance->config.weather, "Failed to connect to 'wttr.in'"); - return; - } - - FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(4096); - bool success = ffNetworkingRecvHttpResponse(&state, &result, instance->config.weatherTimeout); - if (success) ffStrbufSubstrAfterFirstS(&result, "\r\n\r\n"); - - if(!success || result.length == 0) - { - ffPrintError(instance, FF_WEATHER_MODULE_NAME, 0, &instance->config.weather, "Failed to receive the server response"); - return; - } - - if(instance->config.weather.outputFormat.length == 0) - { - ffPrintLogoAndKey(instance, FF_WEATHER_MODULE_NAME, 0, &instance->config.weather.key); - ffStrbufPutTo(&result, stdout); - } - else - { - ffPrintFormat(instance, FF_WEATHER_MODULE_NAME, 0, &instance->config.weather, FF_WEATHER_NUM_FORMAT_ARGS, (FFformatarg[]) { - {FF_FORMAT_ARG_TYPE_STRBUF, &result} - }); - } -} diff --git a/src/modules/weather/option.h b/src/modules/weather/option.h new file mode 100644 index 000000000..d481fb6b7 --- /dev/null +++ b/src/modules/weather/option.h @@ -0,0 +1,14 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFWeatherOptions +{ + const char* moduleName; + FFModuleArgs moduleArgs; + + FFstrbuf outputFormat; + uint32_t timeout; +} FFWeatherOptions; diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c new file mode 100644 index 000000000..579cdf1cb --- /dev/null +++ b/src/modules/weather/weather.c @@ -0,0 +1,122 @@ +#include "fastfetch.h" +#include "common/printing.h" +#include "common/networking.h" +#include "modules/weather/weather.h" + +#define FF_WEATHER_MODULE_NAME "Weather" +#define FF_WEATHER_NUM_FORMAT_ARGS 1 + +static FFNetworkingState state; +static int status = -1; + +void ffPrepareWeather(FFWeatherOptions* options) +{ + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/?format="); + ffStrbufAppend(&path, &options->outputFormat); + status = ffNetworkingSendHttpRequest(&state, "wttr.in", path.chars, "User-Agent: curl/0.0.0\r\n"); +} + +void ffPrintWeather(FFinstance* instance, FFWeatherOptions* options) +{ + if(status == -1) + ffPrepareWeather(options); + + if(status == 0) + { + ffPrintError(instance, FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, "Failed to connect to 'wttr.in'"); + return; + } + + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(4096); + bool success = ffNetworkingRecvHttpResponse(&state, &result, options->timeout); + if (success) ffStrbufSubstrAfterFirstS(&result, "\r\n\r\n"); + + if(!success || result.length == 0) + { + ffPrintError(instance, FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, "Failed to receive the server response"); + return; + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs.key); + ffStrbufPutTo(&result, stdout); + } + else + { + ffPrintFormat(instance, FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_WEATHER_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &result} + }); + } +} + +void ffInitWeatherOptions(FFWeatherOptions* options) +{ + options->moduleName = FF_WEATHER_MODULE_NAME; + ffOptionInitModuleArg(&options->moduleArgs); + + ffStrbufInitS(&options->outputFormat, "%t+-+%C+(%l)"); + options->timeout = 0; +} + +bool ffParseWeatherCommandOptions(FFWeatherOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_WEATHER_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + if (strcasecmp(subKey, "output-format") == 0) + { + ffOptionParseString(key, value, &options->outputFormat); + return true; + } + + if (strcasecmp(subKey, "timeout") == 0) + { + options->timeout = ffOptionParseUInt32(key, value); + return true; + } + + return false; +} + +void ffDestroyWeatherOptions(FFWeatherOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); + + ffStrbufDestroy(&options->outputFormat); +} + +#ifdef FF_HAVE_JSONC +void ffParseWeatherJsonObject(FFinstance* instance, json_object* module) +{ + FFWeatherOptions __attribute__((__cleanup__(ffDestroyWeatherOptions))) options; + ffInitWeatherOptions(&options); + + if (module) + { + json_object_object_foreach(module, key, val) + { + if (ffJsonConfigParseModuleArgs(key, val, &options.moduleArgs)) + continue; + + if (strcasecmp(key, "outputFormat") == 0) + { + ffStrbufSetS(&options.outputFormat, json_object_get_string(val)); + continue; + } + + if (strcasecmp(key, "timeout") == 0) + { + options.timeout = (uint32_t) json_object_get_int(val); + continue; + } + + ffPrintError(instance, FF_WEATHER_MODULE_NAME, 0, &options.moduleArgs, "Unknown JSON key %s", key); + } + } + + ffPrintWeather(instance, &options); +} +#endif diff --git a/src/modules/weather/weather.h b/src/modules/weather/weather.h new file mode 100644 index 000000000..476a1586d --- /dev/null +++ b/src/modules/weather/weather.h @@ -0,0 +1,17 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_WEATHER_MODULE_NAME "Weather" + +void ffPrepareWeather(FFWeatherOptions* options); + +void ffPrintWeather(FFinstance* instance, FFWeatherOptions* options); +void ffInitWeatherOptions(FFWeatherOptions* options); +bool ffParseWeatherCommandOptions(FFWeatherOptions* options, const char* key, const char* value); +void ffDestroyWeatherOptions(FFWeatherOptions* options); + +#ifdef FF_HAVE_JSONC +#include "common/jsonconfig.h" +void ffParseWeatherJsonObject(FFinstance* instance, json_object* module); +#endif