From 29fb43079761796e34209611ec93bd651b871cab Mon Sep 17 00:00:00 2001 From: default Date: Mon, 29 Apr 2024 09:26:37 +0200 Subject: [PATCH] More work in lists. --- data.c | 38 ++++++++++++++++++- httpd.c | 2 +- mastoapi.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++----- snac.h | 6 ++- 4 files changed, 140 insertions(+), 14 deletions(-) diff --git a/data.c b/data.c index 46d95b4..ed65d32 100644 --- a/data.c +++ b/data.c @@ -1732,6 +1732,7 @@ xs_list *tag_search(char *tag, int skip, int show) /** lists **/ xs_val *list_maint(snac *user, const char *list, int op) +/* list maintenance */ { xs_val *l = NULL; @@ -1810,15 +1811,48 @@ xs_val *list_maint(snac *user, const char *list, int op) fn = xs_replace_i(fn, ".id", ".lst"); unlink(fn); - fn = xs_replace_i(fn, ".list", ".idx"); + fn = xs_replace_i(fn, ".lst", ".idx"); unlink(fn); } } break; + } + + return l; +} + + +xs_val *list_content(snac *user, const char *list, const char *actor_md5, int op) +/* list content management */ +{ + xs_val *l = NULL; + + if (!xs_is_hex(list)) + return NULL; + + if (actor_md5 != NULL && !xs_is_hex(actor_md5)) + return NULL; + + xs *fn = xs_fmt("%s/list/%s.lst", user->basedir, list); + + switch (op) { + case 0: /** list content **/ + l = index_list(fn, XS_ALL); - case 3: /** list content (list is the id) **/ break; + + case 1: /** append actor to list **/ + if (actor_md5 != NULL) { + if (!index_in(fn, actor_md5)) + index_add_md5(fn, actor_md5); + } + + break; + + case 2: /** delete actor from list **/ + if (actor_md5 != NULL) + index_del_md5(fn, actor_md5); } return l; diff --git a/httpd.c b/httpd.c index e402e61..bda8159 100644 --- a/httpd.c +++ b/httpd.c @@ -360,7 +360,7 @@ void httpd_connection(FILE *f) #ifndef NO_MASTODON_API if (status == 0) status = mastoapi_delete_handler(req, q_path, - &body, &b_size, &ctype); + payload, p_size, &body, &b_size, &ctype); #endif } diff --git a/mastoapi.c b/mastoapi.c index 54d2777..8c41efb 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1765,7 +1765,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, status = 200; } else - if (strcmp(cmd, "/v1/lists") == 0) { /** **/ + if (strcmp(cmd, "/v1/lists") == 0) { /** list of lists **/ if (logged_in) { xs *lol = list_maint(&snac1, NULL, 0); xs *l = xs_list_new(); @@ -1789,6 +1789,36 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, } } else + if (xs_startswith(cmd, "/v1/lists/")) { /** list information **/ + if (logged_in) { + xs *l = xs_split(cmd, "/"); + char *op = xs_list_get(l, -1); + char *id = xs_list_get(l, -2); + + if (op && id && xs_is_hex(id)) { + if (strcmp(op, "accounts") == 0) { + xs *actors = list_content(&snac1, id, NULL, 0); + xs *out = xs_list_new(); + int c = 0; + char *v; + + while (xs_list_next(actors, &v, &c)) { + xs *actor = NULL; + + if (valid_status(object_get_by_md5(v, &actor))) { + xs *acct = mastoapi_account(actor); + out = xs_list_append(out, acct); + } + } + + *body = xs_json_dumps(out, 4); + *ctype = "application/json"; + status = 200; + } + } + } + } + else if (strcmp(cmd, "/v1/scheduled_statuses") == 0) { /** **/ /* snac does not schedule notes */ *body = xs_dup("[]"); @@ -2676,6 +2706,29 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, status = 422; } } + if (xs_startswith(cmd, "/v1/lists/")) { /** list maintenance **/ + if (logged_in) { + xs *l = xs_split(cmd, "/"); + char *op = xs_list_get(l, -1); + char *id = xs_list_get(l, -2); + + if (op && id && xs_is_hex(id)) { + if (strcmp(op, "accounts") == 0) { + xs_list *accts = xs_dict_get(args, "account_ids[]"); + int c = 0; + char *v; + + while (xs_list_next(accts, &v, &c)) { + list_content(&snac, id, v, 1); + } + + status = 200; + } + } + } + else + status = 422; + } /* user cleanup */ if (logged_in) @@ -2688,18 +2741,39 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, int mastoapi_delete_handler(const xs_dict *req, const char *q_path, - char **body, int *b_size, char **ctype) { - - (void)req; + const char *payload, int p_size, + char **body, int *b_size, char **ctype) +{ + (void)p_size; (void)body; (void)b_size; (void)ctype; - int status = 404; - if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) return 0; + int status = 404; + xs *args = NULL; + char *i_ctype = xs_dict_get(req, "content-type"); + + if (i_ctype && xs_startswith(i_ctype, "application/json")) { + if (!xs_is_null(payload)) + args = xs_json_loads(payload); + } + else if (i_ctype && xs_startswith(i_ctype, "application/x-www-form-urlencoded")) + { + // Some apps send form data instead of json so we should cater for those + if (!xs_is_null(payload)) { + xs *upl = xs_url_dec(payload); + args = xs_url_vars(upl); + } + } + else + args = xs_dup(xs_dict_get(req, "p_vars")); + + if (args == NULL) + return 400; + snac snac = {0}; int logged_in = process_auth_token(&snac, req); @@ -2713,10 +2787,26 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path, if (xs_startswith(cmd, "/v1/lists/")) { if (logged_in) { xs *l = xs_split(cmd, "/"); - char *id = xs_list_get(l, -1); + char *p = xs_list_get(l, -1); - if (xs_is_hex(id)) { - list_maint(&snac, id, 2); + if (p) { + if (strcmp(p, "accounts") == 0) { + /* delete account from list */ + p = xs_list_get(l, -2); + xs_list *accts = xs_dict_get(args, "account_ids[]"); + int c = 0; + char *v; + + while (xs_list_next(accts, &v, &c)) { + list_content(&snac, p, v, 2); + } + } + else { + /* delete list */ + if (xs_is_hex(p)) { + list_maint(&snac, p, 2); + } + } } status = 200; diff --git a/snac.h b/snac.h index f76f8e0..da8b6f9 100644 --- a/snac.h +++ b/snac.h @@ -175,6 +175,7 @@ void tag_index(const char *id, const xs_dict *obj); xs_list *tag_search(char *tag, int skip, int show); xs_val *list_maint(snac *user, const char *list, int op); +xs_val *list_content(snac *user, const char *list_id, const char *actor_md5, int op); int actor_add(const char *actor, xs_dict *msg); int actor_get(const char *actor, xs_dict **data); @@ -339,11 +340,12 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, char **body, int *b_size, char **ctype); int mastoapi_get_handler(const xs_dict *req, const char *q_path, char **body, int *b_size, char **ctype); -int mastoapi_delete_handler(const xs_dict *req, const char *q_path, - char **body, int *b_size, char **ctype); int mastoapi_post_handler(const xs_dict *req, const char *q_path, const char *payload, int p_size, char **body, int *b_size, char **ctype); +int mastoapi_delete_handler(const xs_dict *req, const char *q_path, + const char *payload, int p_size, + char **body, int *b_size, char **ctype); int mastoapi_put_handler(const xs_dict *req, const char *q_path, const char *payload, int p_size, char **body, int *b_size, char **ctype);