diff options
Diffstat (limited to 'c')
| -rw-r--r-- | c/.gitignore | 1 | ||||
| -rw-r--r-- | c/Makefile | 20 | ||||
| -rw-r--r-- | c/dynotify.c | 144 | 
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; +} | 
