weather-tool: Use a geoip service to get location

Since OpenWeather doesn't provide this with their API,
we query ip-api.com, which has a free geoip location service
and we can even restrict the data pulled in from it so we're
not storing more sensitive data than just a city. Seems to
work okay in Japan, but I'll try it from other locations...
This commit is contained in:
K. Lange 2021-07-25 18:06:59 +09:00
parent fd7f8f103b
commit 14027e83dc
2 changed files with 33 additions and 6 deletions

View File

@ -10,8 +10,13 @@
typedef struct JSON_Value Value;
#define WEATHER_CONF_PATH "/etc/weather.json"
#define WEATHER_DATA_PATH "/tmp/weather-data.json"
#define WEATHER_OUT_PATH "/tmp/weather-parsed.conf"
#define LOCATION_DATA_PATH "/tmp/location-data.json"
int main(int argc, char * argv[]) {
Value * config = json_parse_file("/etc/weather.json");
Value * config = json_parse_file(WEATHER_CONF_PATH);
if (!config) {
fprintf(stderr, "No weather config data\n");
return 1;
@ -20,19 +25,41 @@ int main(int argc, char * argv[]) {
char * city = JSON_KEY(config, "city")->string;
char * key = JSON_KEY(config, "key")->string;
char * units = JSON_KEY(config, "units")->string;
char cmdline[1024];
sprintf(cmdline, "fetch -o /tmp/weather-data.json \"http://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=%s\"", city, key, units);
/* If the city is 'guess', we'll make a single query to a separate service to
* get a location from the user's external IP... */
if (!strcmp(city, "guess")) {
/* See if the location data already exists... */
if (access(LOCATION_DATA_PATH, R_OK)) {
sprintf(cmdline, "fetch -o \"" LOCATION_DATA_PATH "\" \"http://ip-api.com/json/?fields=countryCode,regionName,city\"");
system(cmdline);
}
Value * locationData = json_parse_file(LOCATION_DATA_PATH);
if (!locationData) {
fprintf(stderr, "%s: city field was set to 'guess' but failed to acquire data from IP geolocation service\n", argv[0]);
return 1;
}
char * cityName = JSON_KEY(locationData, "city")->string;
char * regionName = JSON_KEY(locationData, "regionName")->string;
char * countryCode = JSON_KEY(locationData, "countryCode")->string;
city = malloc(strlen(cityName) + strlen(regionName) + strlen(countryCode) + 10);
sprintf(city, "%s, %s, %s", cityName, regionName, countryCode);
}
sprintf(cmdline, "fetch -o \"" WEATHER_DATA_PATH "\" \"http://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=%s\"", city, key, units);
system(cmdline);
Value * result = json_parse_file("/tmp/weather-data.json");
Value * result = json_parse_file(WEATHER_DATA_PATH);
assert(result && result->type == JSON_TYPE_OBJECT);
Value * _main = JSON_KEY(result,"main");
Value * conditions = (JSON_KEY(result,"weather") && JSON_KEY(result,"weather")->array->length > 0) ?
JSON_IND(JSON_KEY(result,"weather"),0) : NULL;
FILE * out = fopen("/tmp/weather-parsed.conf", "w");
FILE * out = fopen(WEATHER_OUT_PATH, "w");
fprintf(out, "%.2lf\n", JSON_KEY(_main,"temp")->number);
fprintf(out, "%d\n", (int)JSON_KEY(_main,"temp")->number);
fprintf(out, "%s\n", conditions ? JSON_KEY(conditions,"main")->string : "");

View File

@ -1,5 +1,5 @@
{
"city": "Tokyo",
"city": "guess",
"units": "metric",
"--comment": "The key below is provided for use in ToaruOS for free from OpenWeatherMap.org. We must provide the key so that the weather widget can make API queries. Use of this key for other purposes is against OpenWeatherMap's terms of service.",