diff options
Diffstat (limited to 'activitypub.c')
-rw-r--r-- | activitypub.c | 146 |
1 files changed, 119 insertions, 27 deletions
diff --git a/activitypub.c b/activitypub.c index 73fbbc6..53f102e 100644 --- a/activitypub.c +++ b/activitypub.c @@ -125,10 +125,10 @@ int actor_request(snac *user, const char *actor, xs_dict **data) *data = NULL; /* get from disk first */ - status = actor_get(actor, data); + status = actor_get_refresh(user, actor, data); - if (status != 200) { - /* actor data non-existent or stale: get from the net */ + if (!valid_status(status)) { + /* actor data non-existent: get from the net */ status = activitypub_request(user, actor, &payload); if (valid_status(status)) { @@ -149,8 +149,6 @@ int actor_request(snac *user, const char *actor, xs_dict **data) if (valid_status(status) && data && *data) inbox_add_by_actor(*data); } - else - srv_debug(2, xs_fmt("NOT collected")); return status; } @@ -313,6 +311,12 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level) if (level < MAX_CONVERSATION_LEVELS && !xs_is_null(*id)) { xs *msg = NULL; + /* from a blocked instance? discard and break */ + if (is_instance_blocked(*id)) { + snac_debug(snac, 1, xs_fmt("timeline_request blocked instance %s", *id)); + return status; + } + /* is the object already there? */ if (!valid_status(object_get(*id, &msg))) { /* no; download it */ @@ -354,18 +358,22 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level) if (xs_match(type, "Note|Page|Article|Video")) { const char *actor = get_atto(object); - /* request (and drop) the actor for this entry */ - if (!xs_is_null(actor)) - actor_request(snac, actor, NULL); + if (content_check("filter_reject.txt", object)) + snac_log(snac, xs_fmt("timeline_request rejected by content %s", nid)); + else { + /* request (and drop) the actor for this entry */ + if (!xs_is_null(actor)) + actor_request(snac, actor, NULL); - /* does it have an ancestor? */ - char *in_reply_to = xs_dict_get(object, "inReplyTo"); + /* does it have an ancestor? */ + char *in_reply_to = xs_dict_get(object, "inReplyTo"); - /* store */ - timeline_add(snac, nid, object); + /* store */ + timeline_add(snac, nid, object); - /* recurse! */ - timeline_request(snac, &in_reply_to, NULL, level + 1); + /* recurse! */ + timeline_request(snac, &in_reply_to, NULL, level + 1); + } } } } @@ -623,6 +631,12 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) const char *type = xs_dict_get(c_msg, "type"); const char *actor = xs_dict_get(c_msg, "actor"); + if (strcmp(actor, snac->actor) == 0) { + /* message by myself? (most probably via the shared-inbox) reject */ + snac_debug(snac, 1, xs_fmt("ignoring message by myself")); + return 0; + } + if (xs_match(type, "Like|Announce")) { const char *object = xs_dict_get(c_msg, "object"); @@ -657,6 +671,12 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) return !xs_is_null(object) && strcmp(snac->actor, object) == 0; } + /* only accept Ping directed to us */ + if (xs_match(type, "Ping")) { + char *dest = xs_dict_get(c_msg, "to"); + return !xs_is_null(dest) && strcmp(snac->actor, dest) == 0; + } + /* if it's not a Create or Update, allow as is */ if (!xs_match(type, "Create|Update")) { return 1; @@ -1072,7 +1092,7 @@ xs_dict *msg_collection(snac *snac, char *id) msg = xs_dict_append(msg, "attributedTo", snac->actor); msg = xs_dict_append(msg, "orderedItems", ol); - msg = xs_dict_append(msg, "totalItems", xs_stock_0); + msg = xs_dict_append(msg, "totalItems", xs_stock(0)); return msg; } @@ -1129,8 +1149,10 @@ xs_dict *msg_admiration(snac *snac, char *object, char *type) if (valid_status(object_get(object, &a_msg))) { xs *rcpts = xs_list_new(); + xs *o_md5 = xs_md5_hex(object, strlen(object)); + xs *id = xs_fmt("%s/%s/%s", snac->actor, *type == 'L' ? "l" : "a", o_md5); - msg = msg_base(snac, type, "@dummy", snac->actor, "@now", object); + msg = msg_base(snac, type, id, snac->actor, "@now", object); if (is_msg_public(a_msg)) rcpts = xs_list_append(rcpts, public_address); @@ -1146,6 +1168,33 @@ xs_dict *msg_admiration(snac *snac, char *object, char *type) } +xs_dict *msg_repulsion(snac *user, char *id, char *type) +/* creates an Undo + admiration message */ +{ + xs *a_msg = NULL; + xs_dict *msg = NULL; + + if (valid_status(object_get(id, &a_msg))) { + /* create a clone of the original admiration message */ + xs *object = msg_admiration(user, id, type); + + /* delete the published date */ + object = xs_dict_del(object, "published"); + + /* create an undo message for this object */ + msg = msg_undo(user, object); + + /* copy the 'to' field */ + msg = xs_dict_set(msg, "to", xs_dict_get(object, "to")); + } + + /* now we despise this */ + object_unadmire(id, user->actor, *type == 'L' ? 1 : 0); + + return msg; +} + + xs_dict *msg_actor(snac *snac) /* create a Person message for this actor */ { @@ -1170,7 +1219,7 @@ xs_dict *msg_actor(snac *snac) msg = xs_dict_set(msg, "preferredUsername", snac->uid); msg = xs_dict_set(msg, "published", xs_dict_get(snac->config, "published")); - xs *f_bio_2 = not_really_markdown(xs_dict_get(snac->config, "bio"), NULL); + xs *f_bio_2 = not_really_markdown(xs_dict_get(snac->config, "bio"), NULL, NULL); f_bio = process_tags(snac, f_bio_2, &tags); msg = xs_dict_set(msg, "summary", f_bio); msg = xs_dict_set(msg, "tag", tags); @@ -1378,7 +1427,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, } /* format the content */ - fc2 = not_really_markdown(content, &atls); + fc2 = not_really_markdown(content, &atls, &tag); if (in_reply_to != NULL && *in_reply_to) { xs *p_msg = NULL; @@ -1556,6 +1605,7 @@ xs_dict *msg_question(snac *user, const char *content, xs_list *attach, } if (xs_set_add(&seen, v2) == 1) { + d = xs_dict_append(d, "type", "Note"); d = xs_dict_append(d, "name", v2); d = xs_dict_append(d, "replies", replies); o = xs_list_append(o, d); @@ -1608,7 +1658,7 @@ int update_question(snac *user, const char *id) const char *name = xs_dict_get(v, "name"); if (name) { lopts = xs_list_append(lopts, name); - rcnt = xs_dict_set(rcnt, name, xs_stock_0); + rcnt = xs_dict_set(rcnt, name, xs_stock(0)); } } @@ -1891,6 +1941,8 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) } else if (strcmp(type, "Undo") == 0) { /** **/ + char *id = xs_dict_get(object, "object"); + if (xs_type(object) != XSTYPE_DICT) utype = "Follow"; @@ -1903,6 +1955,23 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) snac_log(snac, xs_fmt("error deleting follower %s", actor)); } else + if (strcmp(utype, "Like") == 0) { /** **/ + int status = object_unadmire(id, actor, 1); + + snac_log(snac, xs_fmt("Unlike for %s %d", id, status)); + } + else + if (strcmp(utype, "Announce") == 0) { /** **/ + int status = 200; + + /* commented out: if a followed user boosts something that + is requested and then unboosts, the post remains here, + but with no apparent reason, and that is confusing */ + //status = object_unadmire(id, actor, 0); + + snac_log(snac, xs_fmt("Unboost for %s %d", id, status)); + } + else snac_debug(snac, 1, xs_fmt("ignored 'Undo' for object type '%s'", utype)); } else @@ -1912,7 +1981,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) return 1; } - if (strcmp(utype, "Note") == 0) { /** **/ + if (xs_match(utype, "Note|Article")) { /** **/ char *id = xs_dict_get(object, "id"); char *in_reply_to = xs_dict_get(object, "inReplyTo"); xs *wrk = NULL; @@ -1921,10 +1990,15 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) snac_debug(snac, 0, xs_fmt("dropped reply %s to hidden post %s", id, in_reply_to)); } else { + if (content_check("filter_reject.txt", object)) { + snac_log(snac, xs_fmt("rejected by content %s", id)); + return 1; + } + timeline_request(snac, &in_reply_to, &wrk, 0); if (timeline_add(snac, id, object)) { - snac_log(snac, xs_fmt("new 'Note' %s %s", actor, id)); + snac_log(snac, xs_fmt("new '%s' %s %s", utype, actor, id)); do_notify = 1; } @@ -1988,12 +2062,12 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) if (xs_type(object) == XSTYPE_DICT) object = xs_dict_get(object, "id"); - if (timeline_admire(snac, object, actor, 1) == 201) { + if (timeline_admire(snac, object, actor, 1) == 201) snac_log(snac, xs_fmt("new 'Like' %s %s", actor, object)); - do_notify = 1; - } else snac_log(snac, xs_fmt("repeated 'Like' from %s to %s", actor, object)); + + do_notify = 1; } else if (strcmp(type, "Announce") == 0) { /** **/ @@ -2019,13 +2093,13 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) xs *who_o = NULL; if (valid_status(actor_request(snac, who, &who_o))) { - if (timeline_admire(snac, object, actor, 0) == 201) { + if (timeline_admire(snac, object, actor, 0) == 201) snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); - do_notify = 1; - } else snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", actor, object)); + + do_notify = 1; } else snac_debug(snac, 1, xs_fmt("dropped 'Announce' on actor request error %s", who)); @@ -2236,6 +2310,24 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) verify_links(snac); } else + if (strcmp(type, "actor_refresh") == 0) { + const char *actor = xs_dict_get(q_item, "actor"); + double mtime = object_mtime(actor); + + /* only refresh if it was refreshed more than an hour ago */ + if (mtime + 3600.0 < (double) time(NULL)) { + xs *actor_o = NULL; + int status; + + if (valid_status((status = activitypub_request(snac, actor, &actor_o)))) + actor_add(actor, actor_o); + else + object_touch(actor); + + snac_log(snac, xs_fmt("actor_refresh %s %d", actor, status)); + } + } + else snac_log(snac, xs_fmt("unexpected user q_item type '%s'", type)); } |