aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrow Savcik <krow@savcik.xyz>2024-01-07 15:18:29 +0200
committerKrow Savcik <krow@savcik.xyz>2024-01-07 15:18:29 +0200
commit5138d33e0c0adb0c4d13977af047e375eee934d8 (patch)
tree543825c957813dca637acacc8e5b7574c0979fb3
initial commit
-rw-r--r--Makefile25
-rw-r--r--config.def.h2
-rw-r--r--config.mk2
-rw-r--r--wcli-gen.c147
-rwxr-xr-xwcli-query9
-rw-r--r--wcli.c192
6 files changed, 377 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..dd9869f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,25 @@
+include config.mk
+
+build: config.h
+ ${CC} -ljson-c wcli-gen.c -o wcli-gen
+ ${CC} wcli.c -o wcli
+
+config.h: config.def.h
+ cp config.def.h config.h
+
+install: build
+ mkdir -p $(PREFIX)/bin
+ cp -f wcli wcli-gen wcli-query $(PREFIX)/bin
+ chmod 755 ${PREFIX}/bin/wcli
+ chmod 755 ${PREFIX}/bin/wcli-gen
+ chmod 755 ${PREFIX}/bin/wcli-query
+
+uninstall:
+ rm -f ${PREFIX}/bin/wcli\
+ ${PREFIX}/bin/wcli-gen\
+ ${PREFIX}/bin/wcli-query
+
+clean:
+ rm wcli wcli-gen
+
+.PHONY: build install uninstall clean
diff --git a/config.def.h b/config.def.h
new file mode 100644
index 0000000..0f2f277
--- /dev/null
+++ b/config.def.h
@@ -0,0 +1,2 @@
+static char* working_dir="~/.local/share/wcli/";
+#define VERBOSE
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..79c37b0
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,2 @@
+PREFIX = ~/.local
+CC = cc
diff --git a/wcli-gen.c b/wcli-gen.c
new file mode 100644
index 0000000..b872255
--- /dev/null
+++ b/wcli-gen.c
@@ -0,0 +1,147 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <json-c/json.h>
+
+#define VERBOSE
+
+#include "config.h"
+char *wdir;
+
+void error(const char* restrict format, ...);
+int printv(const char* restrict format, ...);
+static int _printv(const char* restrict format, va_list args);
+
+void
+error(const char* restrict format, ...)
+{
+ va_list args;
+ va_start(args,format);
+ _printv(format,args);
+ va_end(args);
+
+ exit(1);
+ return;
+}
+
+int
+printv(const char* restrict format, ...)
+{
+ va_list args;
+ va_start(args,format);
+ int ret = _printv(format,args);
+ va_end(args);
+
+ return ret;
+}
+
+int
+_printv(const char* restrict format, va_list args)
+{
+#ifndef VERBOSE
+ return 0;
+#endif
+
+ int ret = vprintf(format,args);
+ return ret;
+}
+
+void
+str_conc_const(const char *s1, const char *s2, char *res)
+{
+ const size_t l1 = strlen(s1);
+ const size_t l2 = strlen(s2);
+
+ memcpy(res,s1,l1);
+ memcpy(res+l1,s2,l2+1);
+ return;
+}
+
+char*
+str_conc(const char *s1, const char *s2)
+{
+ const size_t l1 = strlen(s1);
+ const size_t l2 = strlen(s2);
+
+ char* res = malloc(l1 + l2 + 1);
+ if (res == NULL)
+ error("Error while concatenating \"%s\" and \"%s\".\n", s1, s2);
+
+ str_conc_const(s1, s2, res);
+ return res;
+}
+
+void
+parse(char *fn)
+{
+ json_object *weather, *root, *day, *hly, *hour;
+ char *file, *pref, suf[3];
+ FILE *fl;
+ int i, j, s, h;
+ root = json_object_from_file(fn);
+ if (!root)
+ error("Error\n");
+ /* Assuming no errors */
+
+ weather = json_object_object_get(root, "weather");
+ s = json_object_array_length(weather);
+ suf[0] = '-';
+ suf[2] = '\0';
+ for (i = 0; i < s; i++) {
+ day = json_object_array_get_idx(weather,i);
+ hly = json_object_object_get(day, "hourly");
+
+ if (!i)
+ pref = str_conc(wdir,json_object_get_string(json_object_object_get(day, "date")));
+ else
+ str_conc_const(wdir,json_object_get_string(json_object_object_get(day, "date")),pref);
+
+ h = json_object_array_length(hly);
+ for (j = 0; j < h; j++) {
+ suf[1] = j+'0';
+ if (!i && !j)
+ file = str_conc(pref,suf);
+ else
+ str_conc_const(pref,suf,file);
+
+ hour = json_object_array_get_idx(hly,j);
+ fl = fopen(file,"w");
+
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "tempC")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "tempF")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "FeelsLikeC")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "FeelsLikeF")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "windspeedKmph")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "WindGustKmph")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "winddir16Point")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "winddirDegree")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "visibility")));
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "weatherCode")));
+ hour = json_object_array_get_idx(json_object_object_get(hour, "weatherDesc"),0);
+ fprintf(fl, "%s\n", json_object_get_string(json_object_object_get(hour, "value")));
+ fclose(fl);
+ }
+ }
+
+ free(file);
+ free(pref);
+
+ json_object_put(root);
+ return;
+}
+
+int
+main(int argc, char** argv)
+{
+ if (argc < 2)
+ error("Not enough arguments.\n");
+
+ if (working_dir[0] == '~') {
+ wdir = str_conc(getenv("HOME"), &working_dir[1]);
+ } else {
+ wdir = working_dir;
+ }
+
+ parse(argv[1]);
+}
diff --git a/wcli-query b/wcli-query
new file mode 100755
index 0000000..109723f
--- /dev/null
+++ b/wcli-query
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+dir="$HOME/.local/share/wcli"
+file="$dir/$(date +info_%F_%H-%M.json)"
+country=""
+
+mkdir -p "$dir" || exit 1
+curl "wttr.in/${country}?format=j1" -o "$file" || exit 1
+wcli-gen "$file"
diff --git a/wcli.c b/wcli.c
new file mode 100644
index 0000000..30e6957
--- /dev/null
+++ b/wcli.c
@@ -0,0 +1,192 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include "config.h"
+
+#define DLEN 25
+
+time_t rawtime;
+struct tm *timeinfo;
+
+struct data {
+ int temp_c;
+ int temp_f;
+ int feel_temp_c;
+ int feel_temp_f;
+ int wind_speed;
+ int wind_gust;
+ char wind_dir_16[4];
+ int wind_dir_deg;
+ int vis;
+ int weather_code;
+ char weather_desc[DLEN];
+} w;
+
+void
+error()
+{
+ printf("doom");
+ exit(1);
+ return;
+}
+
+void
+str_conc_const(const char *s1, const char *s2, char *res)
+{
+ const size_t l1 = strlen(s1);
+ const size_t l2 = strlen(s2);
+
+ memcpy(res,s1,l1);
+ memcpy(res+l1,s2,l2+1);
+ return;
+}
+
+char*
+str_conc(const char *s1, const char *s2)
+{
+ const size_t l1 = strlen(s1);
+ const size_t l2 = strlen(s2);
+
+ char* res = malloc(l1 + l2 + 1);
+ if (res == NULL)
+ error();
+
+ str_conc_const(s1, s2, res);
+
+ return res;
+}
+
+char
+get_dig(short int u, int x)
+{
+ while (--x)
+ u /= 10;
+ return (u % 10) + '0';
+}
+
+void
+get_file(char *file)
+{
+ int i, of;
+ of = 0;
+
+ for (i = 0; i < 4; ++i)
+ file[of++] = get_dig(timeinfo->tm_year+1900, 4-i);
+ file[of++] = '-';
+
+ for (i = 0; i < 2; ++i)
+ file[of++] = get_dig(timeinfo->tm_mon+1, 2-i);
+ file[of++] = '-';
+
+ for (i = 0; i < 2; ++i)
+ file[of++] = get_dig(timeinfo->tm_mday, 2-i);
+ file[of++] = '-';
+
+ file[of++] = (timeinfo->tm_hour/3) + '0';
+ file[of] = '\0';
+}
+
+void
+read_data(char *file)
+{
+ FILE *f = fopen(file, "r");
+ if (!f)
+ error();
+
+ fscanf(f, "%d\n", &w.temp_c);
+ fscanf(f, "%d\n", &w.temp_f);
+ fscanf(f, "%d\n", &w.feel_temp_c);
+ fscanf(f, "%d\n", &w.feel_temp_f);
+ fscanf(f, "%d\n", &w.wind_speed);
+ fscanf(f, "%d\n", &w.wind_gust);
+ fscanf(f, "%s\n", w.wind_dir_16);
+ fscanf(f, "%d\n", &w.wind_dir_deg);
+ fscanf(f, "%d\n", &w.vis);
+ fscanf(f, "%d\n", &w.weather_code);
+ fgets(w.weather_desc, DLEN, f);
+ if (strlen(w.weather_desc) &&
+ w.weather_desc[strlen(w.weather_desc)-1] == '\n')
+ w.weather_desc[strlen(w.weather_desc)-1] = '\0';
+
+ fclose(f);
+ return;
+}
+
+void
+place_holder(char c)
+{
+ switch(c) {
+ case 'c': printf("%d", w.temp_c); break;
+ case 'f': printf("%d", w.temp_f); break;
+ case 'C': printf("%d", w.feel_temp_c); break;
+ case 'F': printf("%d", w.feel_temp_f); break;
+ case 's': printf("%d", w.wind_speed); break;
+ case 'g': printf("%d", w.wind_gust); break;
+ case 'd': printf("%s", w.wind_dir_16); break;
+ case 'D': printf("%d", w.wind_dir_deg); break;
+ case 'v': printf("%d", w.vis); break;
+ case 'w': printf("%d", w.weather_code); break;
+ case 'W': printf("%s", w.weather_desc); break;
+ case '%': printf("%c", '%'); break;
+ }
+ return;
+}
+
+void
+print(char *f)
+{
+ short int sp = 0;
+ int p = 0;
+
+ while (f[p] != '\0') {
+ if (sp) {
+ place_holder(f[p]);
+ sp = 0;
+ } else {
+ if (f[p] == '%')
+ sp = 1;
+ else
+ printf("%c", f[p]);
+ }
+
+ ++p;
+ }
+
+ return;
+}
+
+
+int
+main(int argc, char** argv)
+{
+ char file[28];
+ char *filename, *tempn;
+
+ if (argc < 2)
+ error();
+
+ time(&rawtime);
+ rawtime += (time_t)5400; /* adds 1.5h because time between data is 3 hours */
+ timeinfo = localtime(&rawtime);
+
+ get_file(file);
+
+ if (working_dir[0] == '~') {
+ tempn = str_conc(getenv("HOME"), &working_dir[1]);
+ filename = str_conc(tempn,file);
+ free(tempn);
+ } else {
+ filename = str_conc(working_dir,file);
+ }
+
+
+ read_data(filename);
+ free(filename);
+
+ print(argv[1]);
+
+ return 0;
+}