aboutsummaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
Diffstat (limited to 'c')
-rw-r--r--c/.gitignore1
-rw-r--r--c/Makefile20
-rw-r--r--c/dynotify.c144
3 files changed, 165 insertions, 0 deletions
diff --git a/c/.gitignore b/c/.gitignore
new file mode 100644
index 0000000..061bc35
--- /dev/null
+++ b/c/.gitignore
@@ -0,0 +1 @@
+dynotify
diff --git a/c/Makefile b/c/Makefile
new file mode 100644
index 0000000..bab4f8f
--- /dev/null
+++ b/c/Makefile
@@ -0,0 +1,20 @@
+PREFIX = /usr/local
+
+all: dynotify
+
+dynotify: dynotify.c
+# https://stackoverflow.com/q/28533059
+# https://stackoverflow.com/q/3220277
+ cc -Wall $$(pkg-config --cflags --libs libnotify libcurl json-c) -o $@ $<
+
+clean:
+ rm -f dynotify
+
+install: all
+ mkdir -p ${DESTDIR}${PREFIX}/bin
+ cp -f dynotify ${DESTDIR}${PREFIX}/bin
+
+uninstall:
+ rm -f ${DESTDIR}${PREFIX}/bin/dynotify
+
+.PHONY: all clean install uninstall
diff --git a/c/dynotify.c b/c/dynotify.c
new file mode 100644
index 0000000..ec7cea8
--- /dev/null
+++ b/c/dynotify.c
@@ -0,0 +1,144 @@
+// curl:
+// man curl_easy_init CURLOPT_URL curl_easy_setopt CURLOPT_WRITEFUNCTION libcurl-errors curl_easy_strerror
+// https://curl.se/libcurl/
+// https://curl.se/libcurl/c/
+// https://curl.se/libcurl/c/libcurl-tutorial.html
+// https://stackoverflow.com/a/2329792
+
+// json-c:
+// pacman -Qs json c
+// https://github.com/json-c/json-c#using
+// https://github.com/json-c/json-c/blob/master/tests/test2.c
+// https://github.com/rbtylee/tutorial-jsonc/blob/master/tutorial/legacy.md
+// https://github.com/rbtylee/tutorial-jsonc/blob/master/tutorial/parsing2.md
+
+// libnotify:
+// https://gitlab.gnome.org/GNOME/libnotify/-/blob/master/tests/test-basic.c?ref_type=heads
+// https://gnome.pages.gitlab.gnome.org/libnotify/index.html
+
+// compile, maybe wrong:
+// https://stackoverflow.com/a/39120702
+// cc -Wall -lcurl -ljson-c $(pkg-config --cflags --libs libnotify) ./dynotify.c
+// or:
+// cc -Wall $(pkg-config --cflags --libs libnotify libcurl json-c) ./dynotify.c
+// misc:
+// /usr/lib/pkgconfig/libnotify.pc
+
+#include<stdio.h> // for sprintf
+#include<stdbool.h> // for bool
+#include<stdlib.h> // for realloc
+#include<string.h> // for memcpy
+#include<unistd.h> // for sleep
+#include<curl/curl.h> // MIT
+#include<json-c/json.h> // MIT
+#include<libnotify/notify.h> //LGPL
+
+#define DYROOM_ID_LEN 9
+// utf-8 most chinese characters 3 bytes, my longest name currently is 2 chinese characters, 2*3=6, +1 for \0
+// but gcc will not error when not consider \0, maybe the complier auto add one more element?
+#define DYROOM_NAME_LEN 6
+
+struct memory {
+ char *response;
+ size_t size;
+};
+
+struct dyroom {
+ // another way: `const char *name;`
+ const char name[DYROOM_NAME_LEN];
+ const unsigned int id;
+ bool up;
+};
+
+// /home/xyz/archive/programs/private_archive_codes/c/c_primer_plus/practices/Chapter14/14-1monthStruct.c
+struct dyroom room[5]={
+ {"阿冉",4605243,false},
+ {"甜汤",2766480,false},
+ {"少君",9640128,false},
+ {"她她",236288,false},
+ {"郑正",10883525,false}
+};
+
+// copy from `man CURLOPT_WRITEFUNCTION`
+static size_t cb(char *data, size_t size, size_t nmemb, void *clientp)
+{
+ size_t realsize = size * nmemb;
+ struct memory *mem = (struct memory *)clientp;
+
+ char *ptr = realloc(mem->response, mem->size + realsize + 1);
+ if(!ptr)
+ return 0; /* out of memory! */
+
+ mem->response = ptr;
+ memcpy(&(mem->response[mem->size]), data, realsize);
+ mem->size += realsize;
+ mem->response[mem->size] = 0;
+
+ return realsize;
+}
+
+int main (void)
+{
+ // man libcurl-errors
+ CURLcode res;
+ // `man curl_easy_init`: "It is encouraged to reuse easy handles for repeated transfers.", so I choose to reuse it
+ CURL *curl = curl_easy_init();
+ NotifyNotification *n;
+ notify_init ("dynotify");
+
+ if(curl) {
+ for(;;)
+ {
+ for(int i=0;i<5;i++)
+ {
+ // manpage assign 0 to struct, it seems because C11 when cast 0 to void* is same as NULL? see:
+ // https://www.geeksforgeeks.org/null-pointer-in-c/
+ struct memory chunk = {0};
+ char url[29+DYROOM_ID_LEN];
+ sprintf(url, "https://www.douyu.com/betard/%d", room[i].id);
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+ res = curl_easy_perform(curl);
+ // man curl_easy_strerror
+ if(res != CURLE_OK)
+ {
+ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+ free(chunk.response);
+ break;
+ }
+ //printf("%s\n",chunk.response);
+
+ json_object *root;
+ root=json_tokener_parse(chunk.response);
+ if (json_object_get_int(json_object_object_get(json_object_object_get(root,"room"),"show_status")) == 1)
+ {
+ if(!room[i].up)
+ {
+ // 开播 is 2*3=6 bytes
+ char msg[DYROOM_NAME_LEN+6];
+ sprintf(msg,"%s开播",room[i].name);
+
+ n = notify_notification_new (msg, NULL, NULL);
+ notify_notification_set_urgency(n, NOTIFY_URGENCY_CRITICAL);
+ notify_notification_show (n, NULL);
+
+ room[i].up=true;
+ }
+ }
+ else if(room[i].up)
+ room[i].up=false;
+
+ free(chunk.response);
+ // must call json_object_put to free *root, else memory leak!
+ json_object_put(root);
+ }
+ sleep(60);
+ }
+ curl_easy_cleanup(curl);
+ }
+
+ g_object_unref (G_OBJECT (n));
+ return 0;
+}