diff options
Diffstat (limited to 'mastoapi.c')
-rw-r--r-- | mastoapi.c | 177 |
1 files changed, 102 insertions, 75 deletions
@@ -289,7 +289,11 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, *body = xs_dup(code); } else { - *body = xs_fmt("%s?code=%s", redir, code); + if (xs_str_in(redir, "?")) + *body = xs_fmt("%s&code=%s", redir, code); + else + *body = xs_fmt("%s?code=%s", redir, code); + status = 303; } @@ -335,8 +339,8 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, /* FIXME: this 'scope' parameter is mandatory for the official Mastodon API, but if it's enabled, it makes it crash after some more steps, which is FAR WORSE */ -// const char *scope = xs_dict_get(args, "scope"); const char *scope = NULL; +// scope = xs_dict_get(args, "scope"); /* no client_secret? check if it's inside an authorization header (AndStatus does it this way) */ @@ -359,9 +363,9 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, } } - /* no code? - I'm not sure of the impacts of this right now, but Subway Tooter does not - provide a code so one must be generated */ + /* no code? + I'm not sure of the impacts of this right now, but Subway Tooter does not + provide a code so one must be generated */ if (xs_is_null(code)){ code = random_str(); } @@ -522,6 +526,12 @@ xs_dict *mastoapi_account(const xs_dict *actor) acct = xs_dict_append(acct, "id", acct_md5); acct = xs_dict_append(acct, "username", prefu); acct = xs_dict_append(acct, "display_name", display_name); + acct = xs_dict_append(acct, "discoverable", xs_stock(XSTYPE_TRUE)); + acct = xs_dict_append(acct, "group", xs_stock(XSTYPE_FALSE)); + acct = xs_dict_append(acct, "hide_collections", xs_stock(XSTYPE_FALSE)); + acct = xs_dict_append(acct, "indexable", xs_stock(XSTYPE_TRUE)); + acct = xs_dict_append(acct, "noindex", xs_stock(XSTYPE_FALSE)); + acct = xs_dict_append(acct, "roles", xs_stock(XSTYPE_LIST)); { /* create the acct field as user@host */ @@ -543,13 +553,14 @@ xs_dict *mastoapi_account(const xs_dict *actor) note = ""; if (strcmp(xs_dict_get(actor, "type"), "Service") == 0) - acct = xs_dict_append(acct, "bot", xs_stock_true); + acct = xs_dict_append(acct, "bot", xs_stock(XSTYPE_TRUE)); else - acct = xs_dict_append(acct, "bot", xs_stock_false); + acct = xs_dict_append(acct, "bot", xs_stock(XSTYPE_FALSE)); acct = xs_dict_append(acct, "note", note); acct = xs_dict_append(acct, "url", id); + acct = xs_dict_append(acct, "uri", id); xs *avatar = NULL; xs_dict *av = xs_dict_get(actor, "icon"); @@ -574,7 +585,7 @@ xs_dict *mastoapi_account(const xs_dict *actor) header = xs_dup(xs_dict_get(hd, "url")); if (xs_is_null(header)) - header = xs_dup(""); + header = xs_fmt("%s/header.png", srv_baseurl); acct = xs_dict_append(acct, "header", header); acct = xs_dict_append(acct, "header_static", header); @@ -602,7 +613,7 @@ xs_dict *mastoapi_account(const xs_dict *actor) d1 = xs_dict_append(d1, "shortcode", nm); d1 = xs_dict_append(d1, "url", url); d1 = xs_dict_append(d1, "static_url", url); - d1 = xs_dict_append(d1, "visible_in_picker", xs_stock_true); + d1 = xs_dict_append(d1, "visible_in_picker", xs_stock(XSTYPE_TRUE)); eml = xs_list_append(eml, d1); } @@ -613,10 +624,10 @@ xs_dict *mastoapi_account(const xs_dict *actor) acct = xs_dict_append(acct, "emojis", eml); } - acct = xs_dict_append(acct, "locked", xs_stock_false); - acct = xs_dict_append(acct, "followers_count", xs_stock_0); - acct = xs_dict_append(acct, "following_count", xs_stock_0); - acct = xs_dict_append(acct, "statuses_count", xs_stock_0); + acct = xs_dict_append(acct, "locked", xs_stock(XSTYPE_FALSE)); + acct = xs_dict_append(acct, "followers_count", xs_stock(0)); + acct = xs_dict_append(acct, "following_count", xs_stock(0)); + acct = xs_dict_append(acct, "statuses_count", xs_stock(0)); xs *fields = xs_list_new(); p = xs_dict_get(actor, "attachment"); @@ -624,19 +635,19 @@ xs_dict *mastoapi_account(const xs_dict *actor) /* dict of validated links */ xs_dict *val_links = NULL; - xs_dict *metadata = xs_stock_dict; + xs_dict *metadata = xs_stock(XSTYPE_DICT); snac user = {0}; if (xs_startswith(id, srv_baseurl)) { /* if it's a local user, open it and pick its validated links */ if (user_open(&user, prefu)) { val_links = user.links; - metadata = xs_dict_get_def(user.config, "metadata", xs_stock_dict); + metadata = xs_dict_get_def(user.config, "metadata", xs_stock(XSTYPE_DICT)); } } if (xs_is_null(val_links)) - val_links = xs_stock_dict; + val_links = xs_stock(XSTYPE_DICT); while (xs_list_iter(&p, &v)) { char *type = xs_dict_get(v, "type"); @@ -665,7 +676,7 @@ xs_dict *mastoapi_account(const xs_dict *actor) d = xs_dict_append(d, "value", value); d = xs_dict_append(d, "verified_at", xs_type(val_date) == XSTYPE_STRING && *val_date ? - val_date : xs_stock_null); + val_date : xs_stock(XSTYPE_NULL)); fields = xs_list_append(fields, d); } @@ -703,13 +714,13 @@ xs_dict *mastoapi_poll(snac *snac, const xs_dict *msg) xs *fd = mastoapi_date(xs_dict_get(msg, "endTime")); poll = xs_dict_append(poll, "expires_at", fd); poll = xs_dict_append(poll, "expired", - xs_dict_get(msg, "closed") != NULL ? xs_stock_true : xs_stock_false); + xs_dict_get(msg, "closed") != NULL ? xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE)); if ((opts = xs_dict_get(msg, "oneOf")) != NULL) - poll = xs_dict_append(poll, "multiple", xs_stock_false); + poll = xs_dict_append(poll, "multiple", xs_stock(XSTYPE_FALSE)); else { opts = xs_dict_get(msg, "anyOf"); - poll = xs_dict_append(poll, "multiple", xs_stock_true); + poll = xs_dict_append(poll, "multiple", xs_stock(XSTYPE_TRUE)); } while (xs_list_iter(&opts, &v)) { @@ -736,7 +747,7 @@ xs_dict *mastoapi_poll(snac *snac, const xs_dict *msg) poll = xs_dict_append(poll, "voted", (snac && was_question_voted(snac, xs_dict_get(msg, "id"))) ? - xs_stock_true : xs_stock_false); + xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE)); return poll; } @@ -746,7 +757,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) /* converts an ActivityPub note to a Mastodon status */ { xs *actor = NULL; - actor_get(get_atto(msg), &actor); + actor_get_refresh(snac, get_atto(msg), &actor); /* if the author is not here, discard */ if (actor == NULL) @@ -802,7 +813,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) tmp = xs_dict_get(msg, "sensitive"); if (xs_is_null(tmp)) - tmp = xs_stock_false; + tmp = xs_stock(XSTYPE_FALSE); st = xs_dict_append(st, "sensitive", tmp); @@ -921,7 +932,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) d1 = xs_dict_append(d1, "shortcode", nm); d1 = xs_dict_append(d1, "url", url); d1 = xs_dict_append(d1, "static_url", url); - d1 = xs_dict_append(d1, "visible_in_picker", xs_stock_true); + d1 = xs_dict_append(d1, "visible_in_picker", xs_stock(XSTYPE_TRUE)); d1 = xs_dict_append(d1, "category", "Emojis"); eml = xs_list_append(eml, d1); @@ -942,7 +953,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) st = xs_dict_append(st, "favourites_count", ixc); st = xs_dict_append(st, "favourited", - (snac && xs_list_in(idx, snac->md5) != -1) ? xs_stock_true : xs_stock_false); + (snac && xs_list_in(idx, snac->md5) != -1) ? xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE)); xs_free(idx); xs_free(ixc); @@ -951,7 +962,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) st = xs_dict_append(st, "reblogs_count", ixc); st = xs_dict_append(st, "reblogged", - (snac && xs_list_in(idx, snac->md5) != -1) ? xs_stock_true : xs_stock_false); + (snac && xs_list_in(idx, snac->md5) != -1) ? xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE)); /* get the last person who boosted this */ xs *boosted_by_md5 = NULL; @@ -966,8 +977,8 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) st = xs_dict_append(st, "replies_count", ixc); /* default in_reply_to values */ - st = xs_dict_append(st, "in_reply_to_id", xs_stock_null); - st = xs_dict_append(st, "in_reply_to_account_id", xs_stock_null); + st = xs_dict_append(st, "in_reply_to_id", xs_stock(XSTYPE_NULL)); + st = xs_dict_append(st, "in_reply_to_account_id", xs_stock(XSTYPE_NULL)); tmp = xs_dict_get(msg, "inReplyTo"); if (!xs_is_null(tmp)) { @@ -985,9 +996,9 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) } } - st = xs_dict_append(st, "reblog", xs_stock_null); - st = xs_dict_append(st, "card", xs_stock_null); - st = xs_dict_append(st, "language", xs_stock_null); + st = xs_dict_append(st, "reblog", xs_stock(XSTYPE_NULL)); + st = xs_dict_append(st, "card", xs_stock(XSTYPE_NULL)); + st = xs_dict_append(st, "language", xs_stock(XSTYPE_NULL)); tmp = xs_dict_get(msg, "sourceContent"); if (xs_is_null(tmp)) @@ -998,7 +1009,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) tmp = xs_dict_get(msg, "updated"); xs *fd2 = NULL; if (xs_is_null(tmp)) - tmp = xs_stock_null; + tmp = xs_stock(XSTYPE_NULL); else { fd2 = mastoapi_date(tmp); tmp = fd2; @@ -1011,12 +1022,12 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) st = xs_dict_append(st, "poll", poll); } else - st = xs_dict_append(st, "poll", xs_stock_null); + st = xs_dict_append(st, "poll", xs_stock(XSTYPE_NULL)); - st = xs_dict_append(st, "bookmarked", xs_stock_false); + st = xs_dict_append(st, "bookmarked", xs_stock(XSTYPE_FALSE)); st = xs_dict_append(st, "pinned", - (snac && is_pinned(snac, id)) ? xs_stock_true : xs_stock_false); + (snac && is_pinned(snac, id)) ? xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE)); /* is it a boost? */ if (!xs_is_null(boosted_by_md5)) { @@ -1060,21 +1071,21 @@ xs_dict *mastoapi_relationship(snac *snac, const char *md5) rel = xs_dict_append(rel, "id", md5); rel = xs_dict_append(rel, "following", - following_check(snac, actor) ? xs_stock_true : xs_stock_false); + following_check(snac, actor) ? xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE)); - rel = xs_dict_append(rel, "showing_reblogs", xs_stock_true); - rel = xs_dict_append(rel, "notifying", xs_stock_false); + rel = xs_dict_append(rel, "showing_reblogs", xs_stock(XSTYPE_TRUE)); + rel = xs_dict_append(rel, "notifying", xs_stock(XSTYPE_FALSE)); rel = xs_dict_append(rel, "followed_by", - follower_check(snac, actor) ? xs_stock_true : xs_stock_false); + follower_check(snac, actor) ? xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE)); rel = xs_dict_append(rel, "blocking", - is_muted(snac, actor) ? xs_stock_true : xs_stock_false); + is_muted(snac, actor) ? xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE)); - rel = xs_dict_append(rel, "muting", xs_stock_false); - rel = xs_dict_append(rel, "muting_notifications", xs_stock_false); - rel = xs_dict_append(rel, "requested", xs_stock_false); - rel = xs_dict_append(rel, "domain_blocking", xs_stock_false); - rel = xs_dict_append(rel, "endorsed", xs_stock_false); + rel = xs_dict_append(rel, "muting", xs_stock(XSTYPE_FALSE)); + rel = xs_dict_append(rel, "muting_notifications", xs_stock(XSTYPE_FALSE)); + rel = xs_dict_append(rel, "requested", xs_stock(XSTYPE_FALSE)); + rel = xs_dict_append(rel, "domain_blocking", xs_stock(XSTYPE_FALSE)); + rel = xs_dict_append(rel, "endorsed", xs_stock(XSTYPE_FALSE)); rel = xs_dict_append(rel, "note", ""); } @@ -1142,9 +1153,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, acct = xs_dict_append(acct, "last_status_at", xs_dict_get(snac1.config, "published")); acct = xs_dict_append(acct, "note", xs_dict_get(snac1.config, "bio")); acct = xs_dict_append(acct, "url", snac1.actor); - acct = xs_dict_append(acct, "header", ""); - acct = xs_dict_append(acct, "header_static", ""); - acct = xs_dict_append(acct, "locked", xs_stock_false); + acct = xs_dict_append(acct, "locked", xs_stock(XSTYPE_FALSE)); acct = xs_dict_append(acct, "bot", xs_dict_get(snac1.config, "bot")); xs *src = xs_json_loads("{\"privacy\":\"public\"," @@ -1162,6 +1171,17 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, acct = xs_dict_append(acct, "avatar", avatar); acct = xs_dict_append(acct, "avatar_static", avatar); + xs *header = NULL; + char *hd = xs_dict_get(snac1.config, "header"); + + if (!xs_is_null(hd)) + header = xs_dup(hd); + else + header = xs_fmt("%s/header.png", srv_baseurl); + + acct = xs_dict_append(acct, "header", header); + acct = xs_dict_append(acct, "header_static", header); + xs_dict *metadata = xs_dict_get(snac1.config, "metadata"); if (xs_type(metadata) == XSTYPE_DICT) { xs *fields = xs_list_new(); @@ -1170,7 +1190,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, xs_dict *val_links = snac1.links; if (xs_is_null(val_links)) - val_links = xs_stock_dict; + val_links = xs_stock(XSTYPE_DICT); int c = 0; while (xs_dict_next(metadata, &k, &v, &c)) { @@ -1190,7 +1210,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, d = xs_dict_append(d, "value", v); d = xs_dict_append(d, "verified_at", xs_type(val_date) == XSTYPE_STRING && *val_date ? - val_date : xs_stock_null); + val_date : xs_stock(XSTYPE_NULL)); fields = xs_list_append(fields, d); } @@ -1198,9 +1218,9 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, acct = xs_dict_set(acct, "fields", fields); } - acct = xs_dict_append(acct, "followers_count", xs_stock_0); - acct = xs_dict_append(acct, "following_count", xs_stock_0); - acct = xs_dict_append(acct, "statuses_count", xs_stock_0); + acct = xs_dict_append(acct, "followers_count", xs_stock(0)); + acct = xs_dict_append(acct, "following_count", xs_stock(0)); + acct = xs_dict_append(acct, "statuses_count", xs_stock(0)); *body = xs_json_dumps(acct, 4); *ctype = "application/json"; @@ -1716,8 +1736,8 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, else if (strcmp(cmd, "/v2/filters") == 0) { /** **/ /* snac will never have filters - * but still, without a v2 endpoint a short delay is introduced - * in some apps */ + * but still, without a v2 endpoint a short delay is introduced + * in some apps */ *body = xs_dup("[]"); *ctype = "application/json"; status = 200; @@ -1797,7 +1817,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, ins = xs_dict_append(ins, "email", v); - ins = xs_dict_append(ins, "rules", xs_stock_list); + ins = xs_dict_append(ins, "rules", xs_stock(XSTYPE_LIST)); xs *l1 = xs_list_append(xs_list_new(), "en"); ins = xs_dict_append(ins, "languages", l1); @@ -1808,14 +1828,14 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, ins = xs_dict_append(ins, "urls", urls); - xs *d2 = xs_dict_append(xs_dict_new(), "user_count", xs_stock_0); - d2 = xs_dict_append(d2, "status_count", xs_stock_0); - d2 = xs_dict_append(d2, "domain_count", xs_stock_0); + xs *d2 = xs_dict_append(xs_dict_new(), "user_count", xs_stock(0)); + d2 = xs_dict_append(d2, "status_count", xs_stock(0)); + d2 = xs_dict_append(d2, "domain_count", xs_stock(0)); ins = xs_dict_append(ins, "stats", d2); - ins = xs_dict_append(ins, "registrations", xs_stock_false); - ins = xs_dict_append(ins, "approval_required", xs_stock_false); - ins = xs_dict_append(ins, "invites_enabled", xs_stock_false); + ins = xs_dict_append(ins, "registrations", xs_stock(XSTYPE_FALSE)); + ins = xs_dict_append(ins, "approval_required", xs_stock(XSTYPE_FALSE)); + ins = xs_dict_append(ins, "invites_enabled", xs_stock(XSTYPE_FALSE)); xs *cfg = xs_dict_new(); @@ -2063,7 +2083,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, d = xs_dict_append(d, "name", q); xs *url = xs_fmt("%s?t=%s", srv_baseurl, q); d = xs_dict_append(d, "url", url); - d = xs_dict_append(d, "history", xs_stock_list); + d = xs_dict_append(d, "history", xs_stock(XSTYPE_LIST)); htl = xs_list_append(htl, d); } @@ -2103,8 +2123,6 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) return 0; - srv_debug(1, xs_fmt("mastoapi_post_handler %s", q_path)); - int status = 404; xs *args = NULL; char *i_ctype = xs_dict_get(req, "content-type"); @@ -2115,7 +2133,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, } 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 + // 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); @@ -2241,7 +2259,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, strcmp(visibility, "public") == 0 ? 0 : 1); if (!xs_is_null(summary) && *summary) { - msg = xs_dict_set(msg, "sensitive", xs_stock_true); + msg = xs_dict_set(msg, "sensitive", xs_stock(XSTYPE_TRUE)); msg = xs_dict_set(msg, "summary", summary); } @@ -2298,11 +2316,13 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, } else if (strcmp(op, "unfavourite") == 0) { /** **/ - /* partial support: as the original Like message - is not stored anywhere here, it's not possible - to send an Undo + Like; the only thing done here - is to delete the actor from the list of likes */ - object_unadmire(id, snac.actor, 1); + xs *n_msg = msg_repulsion(&snac, id, "Like"); + + if (n_msg != NULL) { + enqueue_message(&snac, n_msg); + + out = mastoapi_status(&snac, msg); + } } else if (strcmp(op, "reblog") == 0) { /** **/ @@ -2317,8 +2337,13 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, } else if (strcmp(op, "unreblog") == 0) { /** **/ - /* partial support: see comment in 'unfavourite' */ - object_unadmire(id, snac.actor, 0); + xs *n_msg = msg_repulsion(&snac, id, "Announce"); + + if (n_msg != NULL) { + enqueue_message(&snac, n_msg); + + out = mastoapi_status(&snac, msg); + } } else if (strcmp(op, "bookmark") == 0) { /** **/ @@ -2603,6 +2628,8 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, if (logged_in) user_free(&snac); + srv_debug(1, xs_fmt("mastoapi_post_handler %s %d", q_path, status)); + return status; } @@ -2701,7 +2728,7 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path, if (valid_status(timeline_get_by_md5(&snac, md5, &msg))) { const char *content = xs_dict_get(args, "status"); xs *atls = xs_list_new(); - xs *f_content = not_really_markdown(content, &atls); + xs *f_content = not_really_markdown(content, &atls, NULL); /* replace fields with new content */ msg = xs_dict_set(msg, "sourceContent", content); |