/* compiled with: * clang `pkg-config --libs json-c libcurl` fm.c */ #include #include #include #include #include #include #define MAX_NAME 30 #define ESC_FIN "\x1b[0m" /* Copy of libcurl docs getinmemory.c + main */ struct MemoryStruct { char *memory; size_t size; }; static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)userp; char *ptr = realloc(mem->memory, mem->size + realsize + 1); if (!ptr) { printf("not enough memory (realloc returned NULL\n)"); return 0; } mem->memory = ptr; memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } char *rgb_to_esc(const char *rgb) { int r, g, b; char *esc = malloc(24); sscanf(rgb, "#%02x%02x%02x", &r, &g, &b); sprintf(esc, "\x1b[38;2;%d;%d;%dm", r, g, b); return esc; } void print_details(json_object *details) { json_object *name_obj = json_object_object_get(details, "name"); const char *name_str = json_object_get_string(name_obj); json_object *country_obj = json_object_object_get(details, "country"); const char *country_str = json_object_get_string(country_obj); json_object *selectedSeason_obj = json_object_object_get(details, "selectedSeason"); const char *selectedSeason_str = json_object_get_string(selectedSeason_obj); printf("%s (%s) %s\n", name_str, country_str, selectedSeason_str); } char *make_name(json_object *name) { const char *name_raw = json_object_get_string(name); char *name_str = malloc(MAX_NAME); int name_len = strlen(name_raw); if (name_len < MAX_NAME) { strcpy(name_str, name_raw); memset(&name_str[name_len], ' ', MAX_NAME-name_len); } else { strncpy(name_str, name_raw, MAX_NAME-3); strcat(name_str, "..."); } return name_str; } void print_line(json_object *team) { json_object *name= json_object_object_get(team, "name"); json_object *pos = json_object_object_get(team, "idx"); json_object *w_o = json_object_object_get(team, "wins"); json_object *d_o = json_object_object_get(team, "draws"); json_object *l_o = json_object_object_get(team, "losses"); json_object *qualColor = json_object_object_get(team, "qualColor"); char *col; if (!json_object_is_type(qualColor, json_type_null)) col = rgb_to_esc(json_object_get_string(qualColor)); else col = rgb_to_esc("#FFFFFF"); int w = json_object_get_int(w_o), d = json_object_get_int(d_o), l = json_object_get_int(l_o); printf("%s%2d %s %2d %2d %2d %3d%s\n", col, json_object_get_int(pos), make_name(name), w, d, l, w*3 + d, ESC_FIN); } /* printing matches from the current round (WIP) *//* void show_current_round(json_object *matches) { json_object *__round = json_object_object_get(matches, "firstUnplayedMatch"); json_object *round_n = json_object_object_get(__round, "firstRoundWithUnplayedMatch"); int r = json_object_get_int(round_n); json_object *all_matches = json_object_object_get(matches, "allMatches"); } */ void table_from_json(char *json_raw) { json_object *root = json_tokener_parse(json_raw); //json_object *root = json_object_from_file("laliga.json"); if (!root) return; // json_object *table_all = json_object_from_path(root, ".table"); json_object *table_data = json_object_array_get_idx(json_object_object_get(root, "table"), 0); json_object *details = json_object_object_get(root, "details"); table_data = json_object_object_get(table_data, "data"); json_object *legend = json_object_object_get(table_data, "legend"); json_object *table = json_object_object_get(table_data, "table"); json_object *table_all = json_object_object_get(table, "all"); print_details(details); int n = json_object_array_length(table_all); printf(" P Name W D L Pts\n"); for (int i = 0; i < n; i++) { json_object *team; team = json_object_array_get_idx(table_all, i); print_line(team); } puts("\n"); n = json_object_array_length(legend); for (int i = 0; i < n; i++) { json_object *qual = json_object_array_get_idx(legend, i); json_object *col = json_object_object_get(qual, "color"); const char *col_str = json_object_get_string(col); json_object *comp = json_object_object_get(qual, "title"); printf("%s# %s%s\n", rgb_to_esc(col_str), json_object_get_string(comp), ESC_FIN); } json_object_put(root); } int main(int argc, char **argv) { int opt, id; char *season = malloc(16); season = ""; while ((opt = getopt(argc, argv, "i:s:")) != -1) { switch (opt) { case 'i': id = atoi(optarg); if (!id) return 1; break; case 's': season = optarg; break; } } CURL *curl_handle; CURLcode res; struct MemoryStruct chunk; char *url = malloc(100); sprintf(url, "https://www.fotmob.com/api/leagues?id=%d&season=%s", id, season); chunk.memory = malloc(1); chunk.size = 0; curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_URL, url); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); res = curl_easy_perform(curl_handle); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); return -1; } else { table_from_json(chunk.memory); } curl_easy_cleanup(curl_handle); free(chunk.memory); curl_global_cleanup(); return 0; }