summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/stweath.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/stweath.c b/src/stweath.c
new file mode 100644
index 0000000..6e5bef3
--- /dev/null
+++ b/src/stweath.c
@@ -0,0 +1,215 @@
+/* Copyright (C) 2025 awy <awy@awy.one>
+
+ stweath is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation,
+ either version 3 of the License, or (at your option) any later version.
+
+ stweath is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with stweath. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <curl/curl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include "cjson/cJSON.h"
+
+int
+getforecast(char *path)
+{
+ FILE *report;
+ CURL* handle;
+ CURLcode res;
+
+ report = fopen(path, "w");
+ if (!report) { return 1; }
+
+ handle = curl_easy_init();
+
+ if (!handle) {
+ fclose(report);
+ return 1;
+ }
+
+ curl_easy_setopt(handle, CURLOPT_URL, "https://wttr.in/?format=j1");
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, NULL);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, report);
+
+ res = curl_easy_perform(handle);
+
+ if (res != CURLE_OK) {
+ fclose(report);
+ return 1;
+ }
+
+ curl_easy_cleanup(handle);
+
+ fclose(report);
+ return 0;
+}
+
+int
+showforecast(char *path)
+{
+ long size;
+ char *data;
+ char *icon;
+ cJSON *root, *temp, *wcode, *rain;
+ FILE *report;
+
+ report = fopen(path, "rb");
+ if (!report) { return 1; }
+
+ fseek(report, 0, SEEK_END);
+ size = ftell(report);
+ fseek(report, 0, SEEK_SET);
+
+ data = malloc(size + 1);
+ if (!data) {
+ perror("malloc");
+ fclose(report);
+ return 1;
+ }
+ fread(data, 1, size, report);
+ data[size] = '\0';
+ fclose(report);
+
+ root = cJSON_Parse(data);
+ free(data);
+ if (!root) { return 1; }
+
+ rain = cJSON_GetArrayItem(cJSON_GetObjectItem(root, "weather"), 0);
+ rain = cJSON_GetArrayItem(cJSON_GetObjectItem(rain, "hourly"), 0);
+ rain = cJSON_GetObjectItem(rain, "chanceofrain");
+ temp = cJSON_GetObjectItem(root, "current_condition");
+ temp = cJSON_GetArrayItem(temp, 0);
+ wcode = cJSON_GetObjectItem(temp, "weatherCode");
+ temp = cJSON_GetObjectItem(temp, "temp_C");
+
+ switch (atoi(wcode->valuestring)) {
+ case 113: icon = ""; break;
+ case 116: icon = ""; break;
+ case 119:
+ case 122:
+ case 143:
+ case 248:
+ case 260:
+ icon = ""; break;
+ case 176:
+ case 179:
+ case 182:
+ case 185:
+ case 263:
+ case 266:
+ case 281:
+ case 284:
+ case 293:
+ case 296:
+ case 299:
+ case 302:
+ case 305:
+ case 308:
+ case 311:
+ case 314:
+ case 317:
+ case 350:
+ case 353:
+ case 356:
+ case 359:
+ case 362:
+ case 365:
+ case 368:
+ case 392:
+ icon = ""; break;
+ case 200: icon = ""; break;
+ case 227:
+ case 230:
+ case 320:
+ case 323:
+ case 326:
+ case 374:
+ case 377:
+ case 386:
+ case 389:
+ icon = ""; break;
+ case 329:
+ case 332:
+ case 335:
+ case 338:
+ case 371:
+ case 395:
+ icon = ""; break;
+ default: icon = "❓"; break;
+ }
+
+ if (atoi(rain->valuestring) != 0) {
+ printf(" %s%% ", rain->valuestring);
+ }
+ printf("%s %s°C", icon, temp->valuestring);
+
+ cJSON_Delete(root);
+ return 0;
+}
+
+int
+checkforecast(char *path)
+{
+ time_t now;
+ char *buff;
+ struct stat st;
+ int tries, force;
+
+ /* Check if there is WEATHERFORCEUPDATE
+ environment variable */
+ force = 0;
+ buff = getenv("WEATHERFORCEUPDATE");
+ if (buff && buff[0] == '1') { force = 1; }
+
+ if (stat(path, &st) != 0) { return 1; }
+
+ now = time(NULL);
+ if (now == ((time_t)-1)) { return 1; }
+
+ /* Check if 30 mins passed
+ then get new forecast */
+ if (((now - st.st_mtime) >= 1800) || force) {
+ tries = 0;
+ /* Try 100 fast retries */
+ while (tries < 100) {
+ if(getforecast(path) == 0) {
+ break;
+ }
+ tries++;
+ sleep(1);
+ }
+ }
+
+ showforecast(path);
+ return 0;
+}
+
+int
+main(void)
+{
+ char *path;
+
+ path = getenv("XDG_CACHE_HOME");
+ if (!path) { puts("XDG_CACHE_HOME is not set"); return 1; }
+ strcat(path, "/weatherreport.json");
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ checkforecast(path);
+
+ curl_global_cleanup();
+ return 0;
+}