diff --git a/activitypub.c b/activitypub.c index 2306eb5..33ddd0f 100644 --- a/activitypub.c +++ b/activitypub.c @@ -156,6 +156,34 @@ int actor_request(snac *user, const char *actor, xs_dict **data) } +char *get_atto(const xs_dict *msg) +/* gets the attributedTo field (an actor) */ +{ + char *actor = xs_dict_get(msg, "attributedTo"); + + /* if the actor is a list of objects (like on Peertube videos), pick the Person */ + if (xs_type(actor) == XSTYPE_LIST) { + xs_list *p = actor; + xs_dict *v; + actor = NULL; + + while (actor == NULL && xs_list_iter(&p, &v)) { + if (xs_type(v) == XSTYPE_DICT) { + char *type = xs_dict_get(v, "type"); + if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Person") == 0) { + actor = xs_dict_get(v, "id"); + + if (xs_type(actor) != XSTYPE_STRING) + actor = NULL; + } + } + } + } + + return actor; +} + + int timeline_request(snac *snac, char **id, xs_str **wrk, int level) /* ensures that an entry and its ancestors are in the timeline */ { @@ -203,7 +231,7 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level) } if (xs_match(type, "Note|Page|Article")) { - const char *actor = xs_dict_get(object, "attributedTo"); + const char *actor = get_atto(object); /* request (and drop) the actor for this entry */ if (!xs_is_null(actor)) @@ -531,7 +559,7 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) } /* accept if it's by someone we follow */ - char *atto = xs_dict_get(msg, "attributedTo"); + char *atto = get_atto(msg); if (pub_msg && !xs_is_null(atto) && following_check(snac, atto)) return 3; @@ -543,7 +571,7 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) /* try to get the replied message */ if (valid_status(object_get(irt, &r_msg))) { - atto = xs_dict_get(r_msg, "attributedTo"); + atto = get_atto(r_msg); /* accept if the replied message is from someone we follow */ if (pub_msg && !xs_is_null(atto) && following_check(snac, atto)) @@ -958,7 +986,7 @@ xs_dict *msg_admiration(snac *snac, char *object, char *type) if (is_msg_public(a_msg)) rcpts = xs_list_append(rcpts, public_address); - rcpts = xs_list_append(rcpts, xs_dict_get(a_msg, "attributedTo")); + rcpts = xs_list_append(rcpts, get_atto(a_msg)); msg = xs_dict_append(msg, "to", rcpts); } @@ -1085,7 +1113,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object) xs_dict *msg = msg_base(snac, "Create", "@wrapper", snac->actor, NULL, object); xs_val *v; - if ((v = xs_dict_get(object, "attributedTo"))) + if ((v = get_atto(object))) msg = xs_dict_append(msg, "attributedTo", v); if ((v = xs_dict_get(object, "cc"))) @@ -1213,7 +1241,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, /* add this author as recipient */ char *a, *v; - if ((a = xs_dict_get(p_msg, "attributedTo")) && xs_list_in(to, a) == -1) + if ((a = get_atto(p_msg)) && xs_list_in(to, a) == -1) to = xs_list_append(to, a); /* add this author to the tag list as a mention */ @@ -1447,7 +1475,7 @@ int update_question(snac *user, const char *id) continue; const char *name = xs_dict_get(obj, "name"); - const char *atto = xs_dict_get(obj, "attributedTo"); + const char *atto = get_atto(obj); if (name && atto) { /* get the current count */ @@ -1799,7 +1827,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) timeline_request(snac, &object, &wrk, 0); if (valid_status(object_get(object, &a_msg))) { - const char *who = xs_dict_get(a_msg, "attributedTo"); + const char *who = get_atto(a_msg); if (who && !is_muted(snac, who)) { /* bring the actor */ diff --git a/data.c b/data.c index c8292ef..d9816a0 100644 --- a/data.c +++ b/data.c @@ -2345,7 +2345,8 @@ int was_question_voted(snac *user, const char *id) xs *obj = NULL; if (valid_status(object_get_by_md5(md5, &obj))) { - if (strcmp(xs_dict_get(obj, "attributedTo"), user->actor) == 0 && + char *atto = get_atto(obj); + if (atto && strcmp(atto, user->actor) == 0 && !xs_is_null(xs_dict_get(obj, "name"))) { voted = 1; break; diff --git a/html.c b/html.c index 1bc28b7..c08cb11 100644 --- a/html.c +++ b/html.c @@ -1275,35 +1275,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int local, if (strcmp(type, "Note") == 0 && !xs_is_null(xs_dict_get(msg, "name"))) return NULL; - /* bring the main actor */ - if ((actor = xs_dict_get(msg, "attributedTo")) == NULL) + /* get the attributedTo */ + if ((actor = get_atto(msg)) == NULL) return NULL; - /* if the actor is a list (like on Peertube videos), pick the Person */ - if (xs_type(actor) == XSTYPE_LIST) { - char *e_actor = NULL; - xs_list *p = actor; - - while (xs_list_iter(&p, &v)) { - if (xs_type(v) == XSTYPE_DICT) { - char *type = xs_dict_get(v, "type"); - if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Person") == 0) { - e_actor = xs_dict_get(v, "id"); - - if (xs_type(e_actor) == XSTYPE_STRING) - break; - else - e_actor = NULL; - } - } - } - - if (e_actor != NULL) - actor = e_actor; - else - return NULL; - } - /* ignore muted morons immediately */ if (user && is_muted(user, actor)) return NULL; @@ -1979,7 +1954,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int local, /* if it's an instance page, discard private users */ if (user == NULL && xs_startswith(xs_dict_get(msg, "id"), srv_baseurl)) { - const char *atto = xs_dict_get(msg, "attributedTo"); + const char *atto = get_atto(msg); xs *l = xs_split(atto, "/"); const char *uid = xs_list_get(l, -1); snac user; diff --git a/mastoapi.c b/mastoapi.c index a81e86e..a9e8aa8 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -701,7 +701,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) /* converts an ActivityPub note to a Mastodon status */ { xs *actor = NULL; - actor_get(xs_dict_get(msg, "attributedTo"), &actor); + actor_get(get_atto(msg), &actor); /* if the author is not here, discard */ if (actor == NULL) @@ -967,7 +967,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) st = xs_dict_set(st, "in_reply_to_id", irt_mid); char *at = NULL; - if (!xs_is_null(at = xs_dict_get(irto, "attributedTo"))) { + if (!xs_is_null(at = get_atto(irto))) { xs *at_md5 = xs_md5_hex(at, strlen(at)); st = xs_dict_set(st, "in_reply_to_account_id", at_md5); } @@ -1443,7 +1443,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, from = xs_dict_get(msg, "audience"); if (from == NULL) - from = xs_dict_get(msg, "attributedTo"); + from = get_atto(msg); if (from == NULL) continue; @@ -1525,7 +1525,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, /* discard private users */ { - const char *atto = xs_dict_get(msg, "attributedTo"); + const char *atto = get_atto(msg); xs *l = xs_split(atto, "/"); const char *uid = xs_list_get(l, -1); snac p_user; @@ -1825,7 +1825,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, if (valid_status(object_get_by_md5(id, &msg))) { if (op == NULL) { - if (!is_muted(&snac1, xs_dict_get(msg, "attributedTo"))) { + if (!is_muted(&snac1, get_atto(msg))) { /* return the status itself */ out = mastoapi_status(&snac1, msg); } @@ -2435,7 +2435,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, if (valid_status(timeline_get_by_md5(&snac, mid, &msg))) { const char *id = xs_dict_get(msg, "id"); - const char *atto = xs_dict_get(msg, "attributedTo"); + const char *atto = get_atto(msg); xs_list *opts = xs_dict_get(msg, "oneOf"); if (opts == NULL) diff --git a/snac.h b/snac.h index 5843d39..79d23b5 100644 --- a/snac.h +++ b/snac.h @@ -245,6 +245,8 @@ const char *default_avatar_base64(void); xs_str *process_tags(snac *snac, const char *content, xs_list **tag); +char *get_atto(const xs_dict *msg); + xs_dict *msg_admiration(snac *snac, char *object, char *type); xs_dict *msg_create(snac *snac, const xs_dict *object); xs_dict *msg_follow(snac *snac, const char *actor);