summaryrefslogtreecommitdiff
path: root/mastoapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'mastoapi.c')
-rw-r--r--mastoapi.c177
1 files changed, 102 insertions, 75 deletions
diff --git a/mastoapi.c b/mastoapi.c
index d702c47..78fd802 100644
--- a/mastoapi.c
+++ b/mastoapi.c
@@ -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);