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 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 From 932227bbac7fe740bff1e38bf92b58edef19e32f Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 Jan 2025 16:59:14 +0100 Subject: Bumped copyright year. --- LICENSE | 2 +- activitypub.c | 2 +- data.c | 2 +- format.c | 2 +- html.c | 2 +- http.c | 2 +- httpd.c | 2 +- main.c | 4 ++-- mastoapi.c | 2 +- snac.c | 2 +- snac.h | 2 +- upgrade.c | 2 +- utils.c | 2 +- webfinger.c | 2 +- xs.h | 2 +- xs_curl.h | 2 +- xs_fcgi.h | 2 +- xs_glob.h | 2 +- xs_hex.h | 2 +- xs_html.h | 2 +- xs_httpd.h | 2 +- xs_io.h | 2 +- xs_json.h | 2 +- xs_match.h | 2 +- xs_mime.h | 2 +- xs_openssl.h | 2 +- xs_random.h | 2 +- xs_regex.h | 2 +- xs_set.h | 2 +- xs_socket.h | 2 +- xs_time.h | 2 +- xs_unicode.h | 2 +- xs_unix_socket.h | 2 +- xs_url.h | 25 ++++++++++++++++++++++++- xs_version.h | 2 +- 35 files changed, 59 insertions(+), 36 deletions(-) (limited to 'activitypub.c') diff --git a/LICENSE b/LICENSE index cdb4e0b..702b487 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 - 2024 grunfink et al. (Fediverse: @grunfink@comam.es) +Copyright (c) 2022 - 2025 grunfink et al. (Fediverse: @grunfink@comam.es) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 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" diff --git a/data.c b/data.c index 0fd3528..576bc40 100644 --- a/data.c +++ b/data.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_hex.h" diff --git a/format.c b/format.c index 41e4162..52ed3ec 100644 --- a/format.c +++ b/format.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_regex.h" diff --git a/html.c b/html.c index d1844c2..5a62d16 100644 --- a/html.c +++ b/html.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_io.h" diff --git a/http.c b/http.c index b21f1dc..611de4f 100644 --- a/http.c +++ b/http.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_io.h" diff --git a/httpd.c b/httpd.c index 163f98a..dda40b9 100644 --- a/httpd.c +++ b/httpd.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_io.h" diff --git a/main.c b/main.c index 7d23c84..5b1dd61 100644 --- a/main.c +++ b/main.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_io.h" @@ -14,7 +14,7 @@ int usage(void) { printf("snac " VERSION " - A simple, minimalistic ActivityPub instance\n"); - printf("Copyright (c) 2022 - 2024 grunfink et al. / MIT license\n"); + printf("Copyright (c) 2022 - 2025 grunfink et al. / MIT license\n"); printf("\n"); printf("Commands:\n"); printf("\n"); diff --git a/mastoapi.c b/mastoapi.c index 62108ad..4b89d12 100644 --- a/mastoapi.c +++ b/mastoapi.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 */ #ifndef NO_MASTODON_API diff --git a/snac.c b/snac.c index 1ce563b..80c7349 100644 --- a/snac.c +++ b/snac.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 */ #define XS_IMPLEMENTATION diff --git a/snac.h b/snac.h index 5ee0390..23ec93a 100644 --- a/snac.h +++ b/snac.h @@ -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 */ #define VERSION "2.68" diff --git a/upgrade.c b/upgrade.c index 847c62e..87ddfc8 100644 --- a/upgrade.c +++ b/upgrade.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_io.h" diff --git a/utils.c b/utils.c index 0740d4d..336ae2d 100644 --- a/utils.c +++ b/utils.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_io.h" diff --git a/webfinger.c b/webfinger.c index 85123bc..5db9a97 100644 --- a/webfinger.c +++ b/webfinger.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" diff --git a/xs.h b/xs.h index 39b3b64..a6e40d5 100644 --- a/xs.h +++ b/xs.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_H diff --git a/xs_curl.h b/xs_curl.h index 9b4c229..f0cfd98 100644 --- a/xs_curl.h +++ b/xs_curl.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_CURL_H diff --git a/xs_fcgi.h b/xs_fcgi.h index c6ffe1f..870e3e8 100644 --- a/xs_fcgi.h +++ b/xs_fcgi.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ /* This is an intentionally-dead-simple FastCGI implementation; diff --git a/xs_glob.h b/xs_glob.h index 15cb49a..6d87ca1 100644 --- a/xs_glob.h +++ b/xs_glob.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_GLOB_H diff --git a/xs_hex.h b/xs_hex.h index 745ac93..2507d5d 100644 --- a/xs_hex.h +++ b/xs_hex.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_HEX_H diff --git a/xs_html.h b/xs_html.h index a95d45a..8331f93 100644 --- a/xs_html.h +++ b/xs_html.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_HTML_H diff --git a/xs_httpd.h b/xs_httpd.h index 860ae05..cf0d811 100644 --- a/xs_httpd.h +++ b/xs_httpd.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_HTTPD_H diff --git a/xs_io.h b/xs_io.h index f63ae5b..110b0eb 100644 --- a/xs_io.h +++ b/xs_io.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_IO_H diff --git a/xs_json.h b/xs_json.h index 69249b1..660c277 100644 --- a/xs_json.h +++ b/xs_json.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_JSON_H diff --git a/xs_match.h b/xs_match.h index 668429a..0b89ac8 100644 --- a/xs_match.h +++ b/xs_match.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_MATCH_H diff --git a/xs_mime.h b/xs_mime.h index 5c0a6fd..6f65382 100644 --- a/xs_mime.h +++ b/xs_mime.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_MIME_H diff --git a/xs_openssl.h b/xs_openssl.h index f339ac6..9388691 100644 --- a/xs_openssl.h +++ b/xs_openssl.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_OPENSSL_H diff --git a/xs_random.h b/xs_random.h index 78de32a..f936099 100644 --- a/xs_random.h +++ b/xs_random.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_RANDOM_H diff --git a/xs_regex.h b/xs_regex.h index 3ba504b..a4db447 100644 --- a/xs_regex.h +++ b/xs_regex.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_REGEX_H diff --git a/xs_set.h b/xs_set.h index f6b65aa..3eaefdf 100644 --- a/xs_set.h +++ b/xs_set.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_SET_H diff --git a/xs_socket.h b/xs_socket.h index fb67b9d..6e618ba 100644 --- a/xs_socket.h +++ b/xs_socket.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_SOCKET_H diff --git a/xs_time.h b/xs_time.h index 1df2fef..0e004dc 100644 --- a/xs_time.h +++ b/xs_time.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_TIME_H diff --git a/xs_unicode.h b/xs_unicode.h index cfcd8ff..ef18fea 100644 --- a/xs_unicode.h +++ b/xs_unicode.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_UNICODE_H diff --git a/xs_unix_socket.h b/xs_unix_socket.h index 3eb2307..462a5b3 100644 --- a/xs_unix_socket.h +++ b/xs_unix_socket.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_UNIX_SOCKET_H diff --git a/xs_url.h b/xs_url.h index ac43585..3c24736 100644 --- a/xs_url.h +++ b/xs_url.h @@ -1,10 +1,11 @@ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #ifndef _XS_URL_H #define _XS_URL_H xs_str *xs_url_dec(const char *str); +xs_str *xs_url_enc(const char *str); xs_dict *xs_url_vars(const char *str); xs_dict *xs_multipart_form_data(const char *payload, int p_size, const char *header); @@ -39,6 +40,28 @@ xs_str *xs_url_dec(const char *str) } +xs_str *xs_url_enc(const char *str) +/* URL-encodes a string (RFC 3986) */ +{ + xs_str *s = xs_str_new(NULL); + + while (*str) { + if (isalnum(*str) || strchr("-._~", *str)) { + s = xs_append_m(s, str, 1); + } + else { + char tmp[8]; + snprintf(tmp, sizeof(tmp), "%%%02X", (unsigned char)*str); + s = xs_append_m(s, tmp, 3); + } + + str++; + } + + return s; +} + + xs_dict *xs_url_vars(const char *str) /* parse url variables */ { diff --git a/xs_version.h b/xs_version.h index 770366a..fc3b755 100644 --- a/xs_version.h +++ b/xs_version.h @@ -1 +1 @@ -/* 297f71e198be7819213e9122e1e78c3b963111bc 2024-11-24T18:48:42+01:00 */ +/* 9e8f5cf300ffbf453031f2ec923cef0822a41b41 2025-01-08T16:57:26+01:00 */ -- cgit 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 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 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 +++++++++++++++- data.c | 4 ++++ snac.h | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) (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; } diff --git a/data.c b/data.c index 576bc40..3463727 100644 --- a/data.c +++ b/data.c @@ -336,6 +336,10 @@ int user_persist(snac *snac, int publish) if (!nw) publish = 0; + else { + /* uncache the actor object */ + object_del(snac->actor); + } } } } diff --git a/snac.h b/snac.h index 23ec93a..5729a22 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ -#define VERSION "2.68" +#define VERSION "2.69-dev" #define USER_AGENT "snac/" VERSION -- cgit 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 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 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 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 +++++++++++++++++++++++++++ html.c | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) (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); diff --git a/html.c b/html.c index eb4ab1f..3498b93 100644 --- a/html.c +++ b/html.c @@ -1311,7 +1311,7 @@ xs_html *html_top_controls(snac *snac) xs_html_attr("for", "show_contact_metrics"), xs_html_text(L("Publish follower and following metrics")))), xs_html_tag("p", - xs_html_text(L("Home location:")), + xs_html_text(L("Current location:")), xs_html_sctag("br", NULL), xs_html_sctag("input", xs_html_attr("type", "text"), -- cgit 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 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 +++++++- main.c | 11 ++--------- 2 files changed, 9 insertions(+), 10 deletions(-) (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); diff --git a/main.c b/main.c index 5b1dd61..83b73af 100644 --- a/main.c +++ b/main.c @@ -668,15 +668,8 @@ int main(int argc, char *argv[]) else content = xs_dup(url); - msg = msg_note(&snac, content, NULL, NULL, attl, 0, getenv("LANG")); - - if (strcmp(cmd, "note_unlisted") == 0) { - /* according to Mastodon, "unlisted" posts (now called "quiet public") - has the public address as a cc instead of to, so toggle it */ - xs *to = xs_dup(xs_dict_get(msg, "to")); - msg = xs_dict_set(msg, "cc", to); - msg = xs_dict_set(msg, "to", xs_stock(XSTYPE_LIST)); - } + msg = msg_note(&snac, content, NULL, NULL, attl, + strcmp(cmd, "note_unlisted") == 0 ? 2 : 0, getenv("LANG")); c_msg = msg_create(&snac, msg); -- cgit 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 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 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 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 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 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 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 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 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 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