summaryrefslogtreecommitdiff
path: root/activitypub.c
diff options
context:
space:
mode:
Diffstat (limited to 'activitypub.c')
-rw-r--r--activitypub.c146
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));
}