// 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 // for sprintf #include // for bool #include // for realloc #include // for memcpy #include // for sleep #include // MIT #include // MIT #include //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; }