From 771e987958fca3ad8cf310771256596dc38f4904 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 27 Feb 2025 14:43:29 +0100 Subject: New function hashtag_in_msg(). --- activitypub.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 104110d..2813beb 100644 --- a/activitypub.c +++ b/activitypub.c @@ -587,12 +587,10 @@ 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 */ +int hashtag_in_msg(const xs_list *hashtags, const xs_dict *msg) +/* returns 1 if the message contains any of the list of hashtags */ { - const xs_list *fw_tags = xs_dict_get(user->config, "followed_hashtags"); - - if (xs_is_list(fw_tags)) { + if (xs_is_list(hashtags)) { const xs_list *tags_in_msg = xs_dict_get(msg, "tag"); if (xs_is_list(tags_in_msg)) { @@ -608,7 +606,7 @@ int followed_hashtag_check(snac *user, const xs_dict *msg) if (strcmp(type, "Hashtag") == 0) { xs *lc_name = xs_utf8_to_lower(name); - if (xs_list_in(fw_tags, lc_name) != -1) + if (xs_list_in(hashtags, lc_name) != -1) return 1; } } @@ -621,6 +619,13 @@ int followed_hashtag_check(snac *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 */ +{ + return hashtag_in_msg(xs_dict_get(user->config, "followed_hashtags"), msg); +} + + void followed_hashtag_distribute(const xs_dict *msg) /* distribute this post to all users following the included hashtags */ { -- cgit v1.2.3 From 190d1d68db733fa71edc5e4ac4e1d23caaae5963 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 27 Feb 2025 15:09:00 +0100 Subject: New function blocked_hashtag_check(). --- activitypub.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 2813beb..a7b6c0b 100644 --- a/activitypub.c +++ b/activitypub.c @@ -590,7 +590,7 @@ int is_msg_from_private_user(const xs_dict *msg) int hashtag_in_msg(const xs_list *hashtags, const xs_dict *msg) /* returns 1 if the message contains any of the list of hashtags */ { - if (xs_is_list(hashtags)) { + if (xs_is_list(hashtags) && xs_is_dict(msg)) { const xs_list *tags_in_msg = xs_dict_get(msg, "tag"); if (xs_is_list(tags_in_msg)) { @@ -620,7 +620,7 @@ int hashtag_in_msg(const xs_list *hashtags, 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 */ +/* returns 1 if this message contains a hashtag followed by me */ { return hashtag_in_msg(xs_dict_get(user->config, "followed_hashtags"), msg); } @@ -656,6 +656,13 @@ void followed_hashtag_distribute(const xs_dict *msg) } +int blocked_hashtag_check(snac *user, const xs_dict *msg) +/* returns 1 if this message contains a hashtag blocked by me */ +{ + return hashtag_in_msg(xs_dict_get(user->config, "blocked_hashtags"), msg); +} + + int is_msg_for_me(snac *snac, const xs_dict *c_msg) /* checks if this message is for me */ { @@ -678,23 +685,25 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) if (!xs_is_string(object)) return 0; + xs *obj = NULL; + if (!valid_status(object_get(object, &obj))) + return 0; + /* if it's about one of our posts, accept it */ if (xs_startswith(object, snac->actor)) return 2; + /* blocked by hashtag? */ + if (blocked_hashtag_check(snac, obj)) + return 0; + /* 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; - } + if (followed_hashtag_check(snac, obj)) + return 7; return 0; } @@ -726,13 +735,20 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) return 1; } + const xs_dict *msg = xs_dict_get(c_msg, "object"); + + /* any blocked hashtag? reject */ + if (blocked_hashtag_check(snac, msg)) { + snac_debug(snac, 1, xs_fmt("blocked by hashtag %s", xs_dict_get(msg, "id"))); + return 0; + } + int pub_msg = is_msg_public(c_msg); /* if this message is public and we follow the actor of this post, allow */ if (pub_msg && following_check(snac, actor)) return 1; - const xs_dict *msg = xs_dict_get(c_msg, "object"); xs *rcpts = recipient_list(snac, msg, 0); xs_list *p = rcpts; const xs_str *v; -- cgit v1.2.3 From 995ea87a8f60f160c4846e4fbfce4e9ae60273de Mon Sep 17 00:00:00 2001 From: default Date: Thu, 27 Feb 2025 17:27:37 +0100 Subject: More hashtag block tweaks. --- activitypub.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index a7b6c0b..5d79593 100644 --- a/activitypub.c +++ b/activitypub.c @@ -677,17 +677,20 @@ 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"); + xs *obj = NULL; - if (xs_is_dict(object)) + if (xs_is_dict(object)) { + obj = xs_dup(object); object = xs_dict_get(object, "id"); + } /* bad object id? reject */ if (!xs_is_string(object)) return 0; - xs *obj = NULL; - if (!valid_status(object_get(object, &obj))) - return 0; + /* try to get the object */ + if (!xs_is_dict(obj)) + object_get(object, &obj); /* if it's about one of our posts, accept it */ if (xs_startswith(object, snac->actor)) -- cgit v1.2.3 From 7cc984c8d49ea5ae6e1902d91fafed9880384f2a Mon Sep 17 00:00:00 2001 From: default Date: Thu, 27 Feb 2025 17:47:06 +0100 Subject: More hashtag block tweaks. --- activitypub.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 5d79593..960a2a1 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2352,6 +2352,9 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) /* bring the actor */ xs *who_o = NULL; + if (blocked_hashtag_check(snac, a_msg)) + snac_debug(snac, 1, xs_fmt("blocked by hashtag %s", object)); + else if (valid_status(actor_request(snac, who, &who_o))) { /* don't account as such announces by our own relay */ xs *this_relay = xs_fmt("%s/relay", srv_baseurl); -- cgit v1.2.3 From 1cce6d86fa6b6828d395305c85b7d252ae53469f Mon Sep 17 00:00:00 2001 From: default Date: Thu, 27 Feb 2025 18:01:34 +0100 Subject: Also check for blocked hashtags in timeline_request(). --- activitypub.c | 98 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 49 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 960a2a1..1dedd17 100644 --- a/activitypub.c +++ b/activitypub.c @@ -329,6 +329,52 @@ xs_list *get_attachments(const xs_dict *msg) } +int hashtag_in_msg(const xs_list *hashtags, const xs_dict *msg) +/* returns 1 if the message contains any of the list of hashtags */ +{ + if (xs_is_list(hashtags) && xs_is_dict(msg)) { + 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(hashtags, lc_name) != -1) + return 1; + } + } + } + } + } + } + + return 0; +} + + +int followed_hashtag_check(snac *user, const xs_dict *msg) +/* returns 1 if this message contains a hashtag followed by me */ +{ + return hashtag_in_msg(xs_dict_get(user->config, "followed_hashtags"), msg); +} + + +int blocked_hashtag_check(snac *user, const xs_dict *msg) +/* returns 1 if this message contains a hashtag blocked by me */ +{ + return hashtag_in_msg(xs_dict_get(user->config, "blocked_hashtags"), msg); +} + + int timeline_request(snac *snac, const char **id, xs_str **wrk, int level) /* ensures that an entry and its ancestors are in the timeline */ { @@ -384,6 +430,9 @@ int timeline_request(snac *snac, const char **id, xs_str **wrk, int level) if (xs_match(type, POSTLIKE_OBJECT_TYPE)) { if (content_match("filter_reject.txt", object)) snac_log(snac, xs_fmt("timeline_request rejected by content %s", nid)); + else + if (blocked_hashtag_check(snac, object)) + snac_log(snac, xs_fmt("timeline_request rejected by hashtag %s", nid)); else { const char *actor = get_atto(object); @@ -587,45 +636,6 @@ int is_msg_from_private_user(const xs_dict *msg) } -int hashtag_in_msg(const xs_list *hashtags, const xs_dict *msg) -/* returns 1 if the message contains any of the list of hashtags */ -{ - if (xs_is_list(hashtags) && xs_is_dict(msg)) { - 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(hashtags, lc_name) != -1) - return 1; - } - } - } - } - } - } - - return 0; -} - - -int followed_hashtag_check(snac *user, const xs_dict *msg) -/* returns 1 if this message contains a hashtag followed by me */ -{ - return hashtag_in_msg(xs_dict_get(user->config, "followed_hashtags"), msg); -} - - void followed_hashtag_distribute(const xs_dict *msg) /* distribute this post to all users following the included hashtags */ { @@ -656,13 +666,6 @@ void followed_hashtag_distribute(const xs_dict *msg) } -int blocked_hashtag_check(snac *user, const xs_dict *msg) -/* returns 1 if this message contains a hashtag blocked by me */ -{ - return hashtag_in_msg(xs_dict_get(user->config, "blocked_hashtags"), msg); -} - - int is_msg_for_me(snac *snac, const xs_dict *c_msg) /* checks if this message is for me */ { @@ -2352,9 +2355,6 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) /* bring the actor */ xs *who_o = NULL; - if (blocked_hashtag_check(snac, a_msg)) - snac_debug(snac, 1, xs_fmt("blocked by hashtag %s", object)); - else if (valid_status(actor_request(snac, who, &who_o))) { /* don't account as such announces by our own relay */ xs *this_relay = xs_fmt("%s/relay", srv_baseurl); -- cgit v1.2.3 From 6776a73712047185c41d9cd9c1316f621c47ed4f Mon Sep 17 00:00:00 2001 From: default Date: Thu, 27 Feb 2025 19:03:01 +0100 Subject: Some tweaks to timeline_request(). --- activitypub.c | 100 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 1dedd17..5e1dd55 100644 --- a/activitypub.c +++ b/activitypub.c @@ -390,71 +390,71 @@ int timeline_request(snac *snac, const char **id, xs_str **wrk, int level) } /* is the object already there? */ - if (!valid_status(object_get(*id, &msg))) { + if (!valid_status((status = object_get(*id, &msg)))) { /* no; download it */ status = activitypub_request(snac, *id, &msg); + } - if (valid_status(status)) { - const xs_dict *object = msg; - const char *type = xs_dict_get(object, "type"); + if (valid_status(status)) { + const xs_dict *object = msg; + const char *type = xs_dict_get(object, "type"); - /* get the id again from the object, as it may be different */ - const char *nid = xs_dict_get(object, "id"); + /* get the id again from the object, as it may be different */ + const char *nid = xs_dict_get(object, "id"); - if (xs_type(nid) != XSTYPE_STRING) - return 0; + if (xs_type(nid) != XSTYPE_STRING) + return 0; - if (wrk && strcmp(nid, *id) != 0) { - snac_debug(snac, 1, - xs_fmt("timeline_request canonical id for %s is %s", *id, nid)); + if (wrk && strcmp(nid, *id) != 0) { + snac_debug(snac, 1, + xs_fmt("timeline_request canonical id for %s is %s", *id, nid)); - *wrk = xs_dup(nid); - *id = *wrk; - } + *wrk = xs_dup(nid); + *id = *wrk; + } - if (xs_is_null(type)) - type = "(null)"; + if (xs_is_null(type)) + type = "(null)"; - srv_debug(2, xs_fmt("timeline_request type %s '%s'", nid, type)); + srv_debug(2, xs_fmt("timeline_request type %s '%s'", nid, type)); - if (strcmp(type, "Create") == 0) { - /* some software like lemmy nest Announce + Create + Note */ - if (!xs_is_null(object = xs_dict_get(object, "object"))) { - type = xs_dict_get(object, "type"); - nid = xs_dict_get(object, "id"); - } - else - type = "(null)"; + if (strcmp(type, "Create") == 0) { + /* some software like lemmy nest Announce + Create + Note */ + if (!xs_is_null(object = xs_dict_get(object, "object"))) { + type = xs_dict_get(object, "type"); + nid = xs_dict_get(object, "id"); } + else + type = "(null)"; + } - if (xs_match(type, POSTLIKE_OBJECT_TYPE)) { - if (content_match("filter_reject.txt", object)) - snac_log(snac, xs_fmt("timeline_request rejected by content %s", nid)); - else - if (blocked_hashtag_check(snac, object)) - snac_log(snac, xs_fmt("timeline_request rejected by hashtag %s", nid)); - else { - const char *actor = get_atto(object); - - if (!xs_is_null(actor)) { - /* request (and drop) the actor for this entry */ - if (!valid_status(actor_request(snac, actor, NULL))) { - /* failed? retry later */ - enqueue_actor_refresh(snac, actor, 60); - } + if (xs_match(type, POSTLIKE_OBJECT_TYPE)) { + if (content_match("filter_reject.txt", object)) + snac_log(snac, xs_fmt("timeline_request rejected by content %s", nid)); + else + if (blocked_hashtag_check(snac, object)) + snac_log(snac, xs_fmt("timeline_request rejected by hashtag %s", nid)); + else { + const char *actor = get_atto(object); + + if (!xs_is_null(actor)) { + /* request (and drop) the actor for this entry */ + if (!valid_status(actor_request(snac, actor, NULL))) { + /* failed? retry later */ + enqueue_actor_refresh(snac, actor, 60); + } - /* does it have an ancestor? */ - const char *in_reply_to = get_in_reply_to(object); + /* does it have an ancestor? */ + const char *in_reply_to = get_in_reply_to(object); - /* store */ - timeline_add(snac, nid, object); + /* store */ + timeline_add(snac, nid, object); - /* redistribute to lists for this user */ - list_distribute(snac, actor, object); + /* redistribute to lists for this user */ + list_distribute(snac, actor, object); - /* recurse! */ - timeline_request(snac, &in_reply_to, NULL, level + 1); - } + /* recurse! */ + timeline_request(snac, &in_reply_to, NULL, level + 1); } } } @@ -2360,7 +2360,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) 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) + if (valid_status(timeline_admire(snac, object, actor, 0))) snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); else snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", -- cgit v1.2.3 From 8bd364bd49116b8b335272300ca05f25e1267df7 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 2 Mar 2025 06:04:52 +0100 Subject: msg_note() accepts a nullable post date. --- activitypub.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'activitypub.c') diff --git a/activitypub.c b/activitypub.c index 5e1dd55..c9f700f 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1555,7 +1555,7 @@ 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 scope, const char *lang_str) + int scope, const char *lang_str, const char *msg_date) /* creates a 'Note' message */ /* scope: 0, public; 1, private (mentioned only); 2, "quiet public"; 3, followers only */ { @@ -1569,7 +1569,12 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, xs *irt = NULL; xs *tag = xs_list_new(); xs *atls = xs_list_new(); - xs_dict *msg = msg_base(snac, "Note", id, NULL, "@now", NULL); + + /* discard non-parseable dates */ + if (!xs_is_string(msg_date) || xs_parse_iso_date(msg_date, 0) == 0) + msg_date = NULL; + + xs_dict *msg = msg_base(snac, "Note", id, NULL, xs_or(msg_date, "@now"), NULL); xs_list *p; const xs_val *v; @@ -1782,7 +1787,7 @@ xs_dict *msg_question(snac *user, const char *content, xs_list *attach, const xs_list *opts, int multiple, int end_secs) /* creates a Question message */ { - xs_dict *msg = msg_note(user, content, NULL, NULL, attach, 0, NULL); + xs_dict *msg = msg_note(user, content, NULL, NULL, attach, 0, NULL, NULL); int max = 8; xs_set seen; -- cgit v1.2.3