From 64f2d3d746d8536c460b88fc852fdca01c5c813c Mon Sep 17 00:00:00 2001 From: default Date: Tue, 7 Jan 2025 08:08:51 +0100 Subject: Minor semantic tweak. --- activitypub.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 1ae5ad9..0740d3d 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1423,8 +1423,9 @@ xs_dict *msg_follow(snac *snac, const char *q) xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, const xs_str *in_reply_to, const xs_list *attach, - int priv, const char *lang_str) + int scope, const char *lang_str) /* creates a 'Note' message */ +/* scope: 0, public; 1, private (mentioned only); 2, "quiet public"; 3, followers only */ { xs *ntid = tid(0); xs *id = xs_fmt("%s/p/%s", snac->actor, ntid); @@ -1440,6 +1441,9 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, xs_list *p; const xs_val *v; + /* FIXME: implement scopes 2 and 3 */ + int priv = scope == 1; + if (rcpts == NULL) to = xs_list_new(); else { -- cgit v1.2.3 From fc9140bf1a94ea927c10db9c6bfb70afe5438bef Mon Sep 17 00:00:00 2001 From: default Date: Tue, 7 Jan 2025 19:01:46 +0100 Subject: Added a tweak to follow LitePub (Pleroma-style, https://litepub.social/) relays. Usage: create a magic user named 'relay' and make it follow a relay actor (examples: https://relay.c.im/actor or https://relay.ie9.org/actor). Unfollowing returns a 400 status and posts keep arriving (at least with ie9.org), so this is a problem at this moment. --- activitypub.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 0740d3d..fe3fd41 100644 --- a/activitypub.c +++ b/activitypub.c @@ -675,7 +675,7 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) if (pub_msg) { /* a public message for someone we follow? (probably cc'ed) accept */ - if (following_check(snac, v)) + if (strcmp(v, public_address) != 0 && following_check(snac, v)) return 5; } else @@ -1242,6 +1242,10 @@ xs_dict *msg_actor(snac *snac) if (xs_type(xs_dict_get(snac->config, "bot")) == XSTYPE_TRUE) msg = xs_dict_set(msg, "type", "Service"); + /* if it's named "relay", then identify as an "Application" */ + if (strcmp(snac->uid, "relay") == 0) + msg = xs_dict_set(msg, "type", "Application"); + /* add the header image, if there is one defined */ const char *header = xs_dict_get(snac->config, "header"); if (!xs_is_null(header)) { @@ -2773,11 +2777,12 @@ void process_queue_item(xs_dict *q_item) snac user; if (user_open(&user, v)) { - if (is_msg_for_me(&user, msg)) { + int rsn = is_msg_for_me(&user, msg); + if (rsn) { xs *fn = xs_fmt("%s/queue/%s.json", user.basedir, ntid); snac_debug(&user, 1, - xs_fmt("enqueue_input (from shared inbox) %s", xs_dict_get(msg, "id"))); + xs_fmt("enqueue_input (from shared inbox) %s [%d]", xs_dict_get(msg, "id"), rsn)); if (link(tmpfn, fn) < 0) srv_log(xs_fmt("link(%s, %s) error", tmpfn, fn)); -- cgit v1.2.3 From 932227bbac7fe740bff1e38bf92b58edef19e32f Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 Jan 2025 16:59:14 +0100 Subject: Bumped copyright year. --- activitypub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index fe3fd41..24954e6 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #include "xs.h" #include "xs_json.h" -- cgit v1.2.3 From 25b22d8a94ddfd3f281e0b0c3405bf7dd6e6feac Mon Sep 17 00:00:00 2001 From: default Date: Thu, 9 Jan 2025 09:10:21 +0100 Subject: Some fixes to receive and update 'Event' objects correctly. --- activitypub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 24954e6..944dd69 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2126,14 +2126,14 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id)); } else - if (strcmp(utype, "Video") == 0) { /** **/ + if (xs_match(utype, "Audio|Video|Event")) { /** **/ const char *id = xs_dict_get(object, "id"); if (xs_is_null(id)) snac_log(snac, xs_fmt("malformed message: no 'id' field")); else if (timeline_add(snac, id, object)) - snac_log(snac, xs_fmt("new 'Video' %s %s", actor, id)); + snac_log(snac, xs_fmt("new '%s' %s %s", utype, actor, id)); } else snac_debug(snac, 1, xs_fmt("ignored 'Create' for object type '%s'", utype)); @@ -2241,7 +2241,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) snac_log(snac, xs_fmt("updated actor %s", actor)); } else - if (xs_match(utype, "Note|Page|Article|Video")) { /** **/ + if (xs_match(utype, "Note|Page|Article|Video|Audio|Event")) { /** **/ const char *id = xs_dict_get(object, "id"); if (xs_is_null(id)) -- cgit v1.2.3 From c25360468c56286a50f52128f548bfd9e8cb7b6b Mon Sep 17 00:00:00 2001 From: default Date: Thu, 9 Jan 2025 18:37:09 +0100 Subject: Added a way to archive ignored messages. --- activitypub.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 24954e6..9f7e9a6 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1853,6 +1853,17 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) /* reject uninteresting messages right now */ if (xs_match(type, "Add|View|Reject|Read|Remove")) { srv_debug(0, xs_fmt("Ignored message of type '%s'", type)); + + /* archive the ignored activity */ + xs *ntid = tid(0); + xs *fn = xs_fmt("%s/ignored/%s.json", srv_basedir, ntid); + FILE *f; + + if ((f = fopen(fn, "w")) != NULL) { + xs_json_dump(msg, 4, f); + fclose(f); + } + return -1; } -- cgit v1.2.3 From 41cb63c936e1520def842f381334397a572bc1cd Mon Sep 17 00:00:00 2001 From: default Date: Thu, 9 Jan 2025 19:21:06 +0100 Subject: Added some actor object caching. --- activitypub.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 81f7708..6f3aefb 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1194,10 +1194,20 @@ xs_dict *msg_actor(snac *snac) xs *avtr = NULL; xs *kid = NULL; xs *f_bio = NULL; - xs_dict *msg = msg_base(snac, "Person", snac->actor, NULL, NULL, NULL); + xs_dict *msg = NULL; const char *p; int n; + /* everybody loves some caching */ + if (time(NULL) - object_mtime(snac->actor) < 6 * 3600 && + valid_status(object_get(snac->actor, &msg))) { + snac_debug(snac, 1, xs_fmt("Returning cached actor %s", snac->actor)); + + return msg; + } + + msg = msg_base(snac, "Person", snac->actor, NULL, NULL, NULL); + /* change the @context (is this really necessary?) */ ctxt = xs_list_append(ctxt, "https:/" "/www.w3.org/ns/activitystreams"); ctxt = xs_list_append(ctxt, "https:/" "/w3id.org/security/v1"); @@ -1330,6 +1340,10 @@ xs_dict *msg_actor(snac *snac) msg = xs_dict_set(msg, "manuallyApprovesFollowers", xs_stock(xs_is_true(manually) ? XSTYPE_TRUE : XSTYPE_FALSE)); + /* cache it */ + snac_debug(snac, 1, xs_fmt("Caching actor %s", snac->actor)); + object_add_ow(snac->actor, msg); + return msg; } -- cgit v1.2.3 From f97fbe374429833319cea78b1f149a3111cea633 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 9 Jan 2025 19:32:40 +0100 Subject: Bumped debug level of actor cache hits. --- activitypub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 6f3aefb..d31a888 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1201,7 +1201,7 @@ xs_dict *msg_actor(snac *snac) /* everybody loves some caching */ if (time(NULL) - object_mtime(snac->actor) < 6 * 3600 && valid_status(object_get(snac->actor, &msg))) { - snac_debug(snac, 1, xs_fmt("Returning cached actor %s", snac->actor)); + snac_debug(snac, 2, xs_fmt("Returning cached actor %s", snac->actor)); return msg; } -- cgit v1.2.3 From 131fbc105a9b82988869fe84c03f2e0b0135e168 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 06:45:44 +0100 Subject: Always return a shared inbox for the 'relay' user. --- activitypub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index d31a888..77d8e34 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1321,7 +1321,7 @@ xs_dict *msg_actor(snac *snac) } /* use shared inboxes? */ - if (xs_type(xs_dict_get(srv_config, "shared_inboxes")) == XSTYPE_TRUE) { + if (xs_is_true(xs_dict_get(srv_config, "shared_inboxes")) || strcmp(snac->uid, "relay") == 0) { xs *d = xs_dict_new(); xs *si = xs_fmt("%s/shared-inbox", srv_baseurl); d = xs_dict_append(d, "sharedInbox", si); -- cgit v1.2.3 From aab32743c150a62648cd620da05d4388747c6253 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 06:47:58 +0100 Subject: Actor caching lowered to 3 hours. --- activitypub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 77d8e34..ecc0533 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1199,7 +1199,7 @@ xs_dict *msg_actor(snac *snac) int n; /* everybody loves some caching */ - if (time(NULL) - object_mtime(snac->actor) < 6 * 3600 && + if (time(NULL) - object_mtime(snac->actor) < 3 * 3600 && valid_status(object_get(snac->actor, &msg))) { snac_debug(snac, 2, xs_fmt("Returning cached actor %s", snac->actor)); -- cgit v1.2.3 From 538f6970f86323dca734436861fe19193fae87e5 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 08:29:57 +0100 Subject: If a location is defined, user actors include a 'Place' object. --- activitypub.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index ecc0533..3bd6220 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1184,6 +1184,28 @@ xs_dict *msg_repulsion(snac *user, const char *id, const char *type) } +xs_dict *msg_place(snac *user, const char *label) +/* creates a Place object, if the user has a location defined */ +{ + xs *place = NULL; + const char *latitude = xs_dict_get_def(user->config, "latitude", ""); + const char *longitude = xs_dict_get_def(user->config, "longitude", ""); + + if (*latitude && *longitude) { + xs *d_la = xs_number_new(atof(latitude)); + xs *d_lo = xs_number_new(atof(longitude)); + + place = msg_base(user, "Place", NULL, user->actor, NULL, NULL); + + place = xs_dict_set(place, "name", label); + place = xs_dict_set(place, "latitude", d_la); + place = xs_dict_set(place, "longitude", d_lo); + } + + return place; +} + + xs_dict *msg_actor(snac *snac) /* create a Person message for this actor */ { @@ -1340,6 +1362,11 @@ xs_dict *msg_actor(snac *snac) msg = xs_dict_set(msg, "manuallyApprovesFollowers", xs_stock(xs_is_true(manually) ? XSTYPE_TRUE : XSTYPE_FALSE)); + /* if there are location coords, create a Place object */ + xs *location = msg_place(snac, "Home"); + if (xs_type(location) == XSTYPE_DICT) + msg = xs_dict_set(msg, "location", location); + /* cache it */ snac_debug(snac, 1, xs_fmt("Caching actor %s", snac->actor)); object_add_ow(snac->actor, msg); -- cgit v1.2.3 From ef7c257c5c2fb8e696ea3bcdd279d46e09e5b20d Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 08:34:48 +0100 Subject: Fixed crash in msg_place() because I'm a moron. --- activitypub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 3bd6220..4966482 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1187,7 +1187,7 @@ xs_dict *msg_repulsion(snac *user, const char *id, const char *type) xs_dict *msg_place(snac *user, const char *label) /* creates a Place object, if the user has a location defined */ { - xs *place = NULL; + xs_dict *place = NULL; const char *latitude = xs_dict_get_def(user->config, "latitude", ""); const char *longitude = xs_dict_get_def(user->config, "longitude", ""); -- cgit v1.2.3 From ff44142b30ceded6ed7db24d033296b0966edb27 Mon Sep 17 00:00:00 2001 From: default Date: Sat, 11 Jan 2025 01:39:37 +0100 Subject: Moved creation of "quiet public" posts to msg_note(), where it belongs. --- activitypub.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 4966482..369423d 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1486,7 +1486,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, xs_list *p; const xs_val *v; - /* FIXME: implement scopes 2 and 3 */ + /* FIXME: implement scope 3 */ int priv = scope == 1; if (rcpts == NULL) @@ -1606,6 +1606,12 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, } } + if (scope == 2) { + /* Mastodon's "quiet public": add public address to cc */ + if (xs_list_in(cc, public_address) == -1) + cc = xs_list_append(cc, public_address); + } + else /* no recipients? must be for everybody */ if (!priv && xs_list_len(to) == 0) to = xs_list_append(to, public_address); -- cgit v1.2.3 From 1ac3f65e0a0ef2aebf2b88dacfd202b4b649ac65 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 12 Jan 2025 05:29:09 +0100 Subject: Renamed msg_place() to msg_actor_place(). --- activitypub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 369423d..862f943 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1184,7 +1184,7 @@ xs_dict *msg_repulsion(snac *user, const char *id, const char *type) } -xs_dict *msg_place(snac *user, const char *label) +xs_dict *msg_actor_place(snac *user, const char *label) /* creates a Place object, if the user has a location defined */ { xs_dict *place = NULL; @@ -1363,7 +1363,7 @@ xs_dict *msg_actor(snac *snac) xs_stock(xs_is_true(manually) ? XSTYPE_TRUE : XSTYPE_FALSE)); /* if there are location coords, create a Place object */ - xs *location = msg_place(snac, "Home"); + xs *location = msg_actor_place(snac, "Home"); if (xs_type(location) == XSTYPE_DICT) msg = xs_dict_set(msg, "location", location); -- cgit v1.2.3 From a016045a8fb80e4accad618c60b987bad708f45e Mon Sep 17 00:00:00 2001 From: default Date: Mon, 13 Jan 2025 06:17:30 +0100 Subject: Don't describe as 'fatal' what are just non-retriable connection errors. --- activitypub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 862f943..f0d9336 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2706,7 +2706,7 @@ void process_queue_item(xs_dict *q_item) || status == HTTP_STATUS_UNPROCESSABLE_CONTENT || status < 0) /* explicit error: discard */ - srv_log(xs_fmt("output message: fatal error %s %d", inbox, status)); + srv_log(xs_fmt("output message: error %s %d", inbox, status)); else if (retries > queue_retry_max) srv_log(xs_fmt("output message: giving up %s %d", inbox, status)); -- cgit v1.2.3 From 4127ec4100ee6f87f42afacba185486ade670966 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 19 Jan 2025 18:20:27 +0100 Subject: Also relay notes to the relays that follow us. --- activitypub.c | 58 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index f0d9336..18b3c86 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2485,7 +2485,7 @@ int send_email(const char *msg) } -void process_user_queue_item(snac *snac, xs_dict *q_item) +void process_user_queue_item(snac *user, xs_dict *q_item) /* processes an item from the user queue */ { const char *type; @@ -2496,7 +2496,7 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) if (strcmp(type, "message") == 0) { const xs_dict *msg = xs_dict_get(q_item, "message"); - xs *rcpts = recipient_list(snac, msg, 1); + xs *rcpts = recipient_list(user, msg, 1); xs_set inboxes; const xs_str *actor; @@ -2505,7 +2505,7 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) /* add this shared inbox first */ xs *this_shared_inbox = xs_fmt("%s/shared-inbox", srv_baseurl); xs_set_add(&inboxes, this_shared_inbox); - enqueue_output(snac, msg, this_shared_inbox, 0, 0); + enqueue_output(user, msg, this_shared_inbox, 0, 0); /* iterate the recipients */ xs_list_foreach(rcpts, actor) { @@ -2516,10 +2516,10 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) if (inbox != NULL) { /* add to the set and, if it's not there, send message */ if (xs_set_add(&inboxes, inbox) == 1) - enqueue_output(snac, msg, inbox, 0, 0); + enqueue_output(user, msg, inbox, 0, 0); } else - snac_log(snac, xs_fmt("cannot find inbox for %s", actor)); + snac_log(user, xs_fmt("cannot find inbox for %s", actor)); } } @@ -2531,12 +2531,36 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) xs_list_foreach(shibx, inbox) { if (xs_set_add(&inboxes, inbox) == 1) - enqueue_output(snac, msg, inbox, 0, 0); + enqueue_output(user, msg, inbox, 0, 0); } } } xs_set_free(&inboxes); + + /* relay this note */ + if (strcmp(user->uid, "relay") != 0) { /* avoid loops */ + snac relay; + if (user_open(&relay, "relay")) { + /* a 'relay' user exists */ + const char *type = xs_dict_get(msg, "type"); + + if (xs_is_string(type) && strcmp(type, "Create") == 0) { + const xs_val *object = xs_dict_get(msg, "object"); + + if (xs_is_dict(object)) { + object = xs_dict_get(object, "id"); + + snac_debug(&relay, 1, xs_fmt("relaying message %s", object)); + + xs *boost = msg_admiration(&relay, object, "Announce"); + enqueue_message(&relay, boost); + } + } + + user_free(&relay); + } + } } else if (strcmp(type, "input") == 0) { @@ -2548,13 +2572,13 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) if (xs_is_null(msg)) return; - if (!process_input_message(snac, msg, req)) { + if (!process_input_message(user, msg, req)) { if (retries > queue_retry_max) - snac_log(snac, xs_fmt("input giving up")); + snac_log(user, xs_fmt("input giving up")); else { /* reenqueue */ - enqueue_input(snac, msg, req, retries + 1); - snac_log(snac, xs_fmt("input requeue #%d", retries + 1)); + enqueue_input(user, msg, req, retries + 1); + snac_log(user, xs_fmt("input requeue #%d", retries + 1)); } } } @@ -2564,7 +2588,7 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) const char *id = xs_dict_get(q_item, "message"); if (!xs_is_null(id)) - update_question(snac, id); + update_question(user, id); } else if (strcmp(type, "object_request") == 0) { @@ -2574,17 +2598,17 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) int status; xs *data = NULL; - status = activitypub_request(snac, id, &data); + status = activitypub_request(user, id, &data); if (valid_status(status)) object_add_ow(id, data); - snac_debug(snac, 1, xs_fmt("object_request %s %d", id, status)); + snac_debug(user, 1, xs_fmt("object_request %s %d", id, status)); } } else if (strcmp(type, "verify_links") == 0) { - verify_links(snac); + verify_links(user); } else if (strcmp(type, "actor_refresh") == 0) { @@ -2596,16 +2620,16 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) xs *actor_o = NULL; int status; - if (valid_status((status = activitypub_request(snac, actor, &actor_o)))) + if (valid_status((status = activitypub_request(user, actor, &actor_o)))) actor_add(actor, actor_o); else object_touch(actor); - snac_log(snac, xs_fmt("actor_refresh %s %d", actor, status)); + snac_log(user, xs_fmt("actor_refresh %s %d", actor, status)); } } else - snac_log(snac, xs_fmt("unexpected user q_item type '%s'", type)); + snac_log(user, xs_fmt("unexpected user q_item type '%s'", type)); } -- cgit v1.2.3 From 5b7279b6f7b0bff59aba029b12b05c989a3b0059 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 19 Jan 2025 18:39:29 +0100 Subject: Only relay public posts. --- activitypub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 18b3c86..73145d3 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2539,7 +2539,7 @@ void process_user_queue_item(snac *user, xs_dict *q_item) xs_set_free(&inboxes); /* relay this note */ - if (strcmp(user->uid, "relay") != 0) { /* avoid loops */ + if (is_msg_public(msg) && strcmp(user->uid, "relay") != 0) { /* avoid loops */ snac relay; if (user_open(&relay, "relay")) { /* a 'relay' user exists */ -- cgit v1.2.3 From f7ae2521ba76dfa403b182221001c38bf383d0e3 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 19 Jan 2025 18:54:02 +0100 Subject: Don't notify us for our own posts from the relay. --- activitypub.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 73145d3..8b44dc8 100644 --- a/activitypub.c +++ b/activitypub.c @@ -889,6 +889,11 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor, /* if it's not an admiration about something by us, done */ if (xs_is_null(objid) || !xs_startswith(objid, snac->actor)) return; + + /* if it's an announce by our own relay, done */ + xs *relay_id = xs_fmt("%s/relay", srv_baseurl); + if (xs_startswith(id, relay_id)) + return; } /* updated poll? */ -- cgit v1.2.3 From 7cd62dd25b92780ef4e1ad42c1d2e9ba69c931e9 Mon Sep 17 00:00:00 2001 From: default Date: Wed, 22 Jan 2025 05:29:25 +0100 Subject: Don't account as such announces by our own relay. --- activitypub.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 8b44dc8..5517bf4 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2274,11 +2274,16 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) xs *who_o = NULL; if (valid_status(actor_request(snac, who, &who_o))) { - if (timeline_admire(snac, object, actor, 0) == HTTP_STATUS_CREATED) - snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); - else - snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", - actor, object)); + /* don't account as such announces by our own relay */ + xs *this_relay = xs_fmt("%s/relay", srv_baseurl); + + if (strcmp(actor, this_relay) != 0) { + if (timeline_admire(snac, object, actor, 0) == HTTP_STATUS_CREATED) + snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); + else + snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", + actor, object)); + } /* distribute the post with the actor as 'proxy' */ list_distribute(snac, actor, a_msg); -- cgit v1.2.3 From 070a9db3d72e0961dca45c7e65aa9fc4532aba73 Mon Sep 17 00:00:00 2001 From: default Date: Wed, 22 Jan 2025 05:59:15 +0100 Subject: Also accept 'Update' activities for 'Application' objects. --- activitypub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 5517bf4..8fa29c9 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2302,7 +2302,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) } else if (strcmp(type, "Update") == 0) { /** **/ - if (xs_match(utype, "Person|Service")) { /** **/ + if (xs_match(utype, "Person|Service|Application")) { /** **/ actor_add(actor, xs_dict_get(msg, "object")); timeline_touch(snac); -- cgit v1.2.3 From ac663a6b4dd5eee1fb3c676524b8e141eb2529ed Mon Sep 17 00:00:00 2001 From: default Date: Wed, 22 Jan 2025 10:07:39 +0100 Subject: Moved followed hashtag check to its own function. --- activitypub.c | 60 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 8fa29c9..b505fbb 100644 --- a/activitypub.c +++ b/activitypub.c @@ -587,6 +587,40 @@ int is_msg_from_private_user(const xs_dict *msg) } +int followed_hashtag_check(snac *user, const xs_dict *msg) +/* returns true if this message contains a hashtag followed by me */ +{ + const xs_list *fw_tags = xs_dict_get(user->config, "followed_hashtags"); + + if (xs_is_list(fw_tags)) { + const xs_list *tags_in_msg = xs_dict_get(msg, "tag"); + + if (xs_is_list(tags_in_msg)) { + const xs_dict *te; + + /* iterate the tags in the message */ + xs_list_foreach(tags_in_msg, te) { + if (xs_is_dict(te)) { + const char *type = xs_dict_get(te, "type"); + const char *name = xs_dict_get(te, "name"); + + if (xs_is_string(type) && xs_is_string(name)) { + if (strcmp(type, "Hashtag") == 0) { + xs *lc_name = xs_utf8_to_lower(name); + + if (xs_list_in(fw_tags, lc_name) != -1) + return 1; + } + } + } + } + } + } + + return 0; +} + + int is_msg_for_me(snac *snac, const xs_dict *c_msg) /* checks if this message is for me */ { @@ -708,30 +742,8 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) } /* does this message contain a tag we are following? */ - const xs_list *fw_tags = xs_dict_get(snac->config, "followed_hashtags"); - if (pub_msg && xs_type(fw_tags) == XSTYPE_LIST) { - const xs_list *tags_in_msg = xs_dict_get(msg, "tag"); - if (xs_type(tags_in_msg) == XSTYPE_LIST) { - const xs_dict *te; - - /* iterate the tags in the message */ - xs_list_foreach(tags_in_msg, te) { - if (xs_type(te) == XSTYPE_DICT) { - const char *type = xs_dict_get(te, "type"); - const char *name = xs_dict_get(te, "name"); - - if (xs_type(type) == XSTYPE_STRING && xs_type(name) == XSTYPE_STRING) { - if (strcmp(type, "Hashtag") == 0) { - xs *lc_name = xs_utf8_to_lower(name); - - if (xs_list_in(fw_tags, lc_name) != -1) - return 7; - } - } - } - } - } - } + if (pub_msg && followed_hashtag_check(snac, msg)) + return 7; return 0; } -- cgit v1.2.3 From a51c996efe0e41334523602271740b6e6b2501c0 Mon Sep 17 00:00:00 2001 From: default Date: Wed, 22 Jan 2025 10:38:01 +0100 Subject: More tweaks to hashtag following code. --- activitypub.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index b505fbb..86599ee 100644 --- a/activitypub.c +++ b/activitypub.c @@ -636,19 +636,32 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) if (xs_match(type, "Like|Announce|EmojiReact")) { const char *object = xs_dict_get(c_msg, "object"); - if (xs_type(object) == XSTYPE_DICT) + if (xs_is_dict(object)) object = xs_dict_get(object, "id"); /* bad object id? reject */ - if (xs_type(object) != XSTYPE_STRING) + if (!xs_is_string(object)) return 0; /* if it's about one of our posts, accept it */ if (xs_startswith(object, snac->actor)) return 2; - /* if it's by someone we don't follow, reject */ - return following_check(snac, actor); + /* if it's by someone we follow, accept it */ + if (following_check(snac, actor)) + return 1; + + /* do we follow any hashtag? */ + if (xs_is_list(xs_dict_get(snac->config, "followed_hashtags"))) { + xs *obj = NULL; + + /* if the admired object contains any followed hashtag, accept it */ + if (valid_status(object_get(object, &obj)) && + followed_hashtag_check(snac, obj)) + return 7; + } + + return 0; } /* if it's an Undo, it must be from someone related to us */ -- cgit v1.2.3 From fda3057dc86d859a0935d2f5fce890d114db5861 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 23 Jan 2025 14:39:59 +0100 Subject: More hashtag following tweaks. --- activitypub.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 86599ee..cade0d9 100644 --- a/activitypub.c +++ b/activitypub.c @@ -621,6 +621,36 @@ int followed_hashtag_check(snac *user, const xs_dict *msg) } +void followed_hashtag_distribute(const xs_dict *msg) +/* distribute this post to all users following the included hashtags */ +{ + const char *id = xs_dict_get(msg, "id"); + const xs_list *tags_in_msg = xs_dict_get(msg, "tag"); + + if (!xs_is_string(id) || !xs_is_list(tags_in_msg) || xs_list_len(tags_in_msg) == 0) + return; + + srv_debug(1, xs_fmt("followed_hashtag_distribute check for %s", id)); + + xs *users = user_list(); + const char *uid; + + xs_list_foreach(users, uid) { + snac user; + + if (user_open(&user, uid)) { + if (followed_hashtag_check(&user, msg)) { + timeline_add(&user, id, msg); + + snac_log(&user, xs_fmt("followed hashtag in %s", id)); + } + + user_free(&user); + } + } +} + + int is_msg_for_me(snac *snac, const xs_dict *c_msg) /* checks if this message is for me */ { @@ -2313,6 +2343,9 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) /* distribute the post with the actor as 'proxy' */ list_distribute(snac, actor, a_msg); + /* distribute the post to users following these hashtags */ + followed_hashtag_distribute(a_msg); + do_notify = 1; } else -- cgit v1.2.3