#define _POSIX_C_SOURCE 200809L #include #include #include #include #include "timeline.h" #include "auth.h" #include "http.h" #include "string-util.h" #include "log.h" static char *timeline_url = "/api/v1/timelines/home"; struct timeline *timeline_from_json(const char *json_data) { json_t *root; json_error_t error; struct timeline *t; root = json_loads(json_data, 0, &error); if (!root) { log_msg(LOG_ERROR, "timeline_free", "json root it null"); return NULL; } if (!json_is_array(root)) { log_msg(LOG_ERROR, "timeline_free", "timeline not initialized"); json_decref(root); return NULL; } t = calloc(1, sizeof(struct timeline)); if (!t) { err(1, NULL); json_decref(root); return NULL; } t->size = json_array_size(root); t->statuses = calloc(t->size, sizeof(struct status *)); if (!(t->statuses)) { err(1, NULL); json_decref(root); return NULL; } for (size_t i = 0; i < t->size; i++) { json_t *data; data = json_array_get(root, i); if (!data) goto error; t->statuses[i] = status_from_json_t(data); if (!(t->statuses[i])) goto error; } json_decref(root); return t; error: timeline_free(t); json_decref(root); return NULL; } void timeline_free(struct timeline *t) { if (!t) { log_msg(LOG_ERROR, "timeline_free", "timeline not initialized"); return; } for (size_t i = 0; i < t->size; i++) { if (t->statuses[i]) status_free(t->statuses[i]); } free(t); } struct load_timeline_call_arg { char *url; void (*callback)(bool, struct timeline *t); }; static void *load_timeline_call(void *req_arg) { struct load_timeline_call_arg *arg; char *resp; struct timeline *t; arg = (struct load_timeline_call_arg *)req_arg; if (!(arg->url)) { log_msg(LOG_ERROR, "load_timeline_call", "invalid arguments"); goto error; } resp = get_request(arg->url); if (!resp) { log_msg(LOG_ERROR, "load_timeline_call", "failed to send http request"); goto error; } if (!resp) { log_msg(LOG_ERROR, "load_timeline_call", "null response"); goto error; } t = timeline_from_json(resp); if (!t) { log_msg(LOG_ERROR, "load_timeline_call", "null response"); goto error; } free(arg->url); free(arg); free(resp); (*(arg->callback))(true, t); return NULL; error: if (arg->url) free(arg->url); free(arg); if (resp) free(resp); (*(arg->callback))(false, NULL); return NULL; } int get_timeline(const char *max_id, const char *since_id, const char *min_id, int limit, void (*callback)(bool success, struct timeline *t)) { size_t size; char *url; struct load_timeline_call_arg *arg; pthread_t t; size = strlen(get_instance_url()) + strlen(timeline_url) + 1; url = malloc(size); if (!url) { err(1, NULL); return -1; } strlcpy(url, get_instance_url(), size); strlcat(url, timeline_url, size); arg = calloc(1, sizeof(struct load_timeline_call_arg)); if (!arg) { err(1, NULL); return -1; } arg->url = url; arg->callback = callback; return pthread_create(&t, NULL, &load_timeline_call, arg); }