summaryrefslogtreecommitdiff
path: root/activitypub.c
diff options
context:
space:
mode:
authorGravatar shtrophic2025-01-24 20:38:26 +0100
committerGravatar shtrophic2025-01-24 20:38:26 +0100
commit85be7f36e12507cff7607df22ca14f8bfc00f6e2 (patch)
treee41bedab3e3b011c16d2ea6180926470cc8586aa /activitypub.c
parentfix memory leak (diff)
parentVersion 2.69 RELEASED. (diff)
downloadsnac2-85be7f36e12507cff7607df22ca14f8bfc00f6e2.tar.gz
snac2-85be7f36e12507cff7607df22ca14f8bfc00f6e2.tar.xz
snac2-85be7f36e12507cff7607df22ca14f8bfc00f6e2.zip
Merge remote-tracking branch 'upstream/master' into curl-smtp
Diffstat (limited to 'activitypub.c')
-rw-r--r--activitypub.c131
1 files changed, 97 insertions, 34 deletions
diff --git a/activitypub.c b/activitypub.c
index 2b10435..4cb779a 100644
--- a/activitypub.c
+++ b/activitypub.c
@@ -587,6 +587,70 @@ int is_msg_from_private_user(const xs_dict *msg)
587} 587}
588 588
589 589
590int followed_hashtag_check(snac *user, const xs_dict *msg)
591/* returns true if this message contains a hashtag followed by me */
592{
593 const xs_list *fw_tags = xs_dict_get(user->config, "followed_hashtags");
594
595 if (xs_is_list(fw_tags)) {
596 const xs_list *tags_in_msg = xs_dict_get(msg, "tag");
597
598 if (xs_is_list(tags_in_msg)) {
599 const xs_dict *te;
600
601 /* iterate the tags in the message */
602 xs_list_foreach(tags_in_msg, te) {
603 if (xs_is_dict(te)) {
604 const char *type = xs_dict_get(te, "type");
605 const char *name = xs_dict_get(te, "name");
606
607 if (xs_is_string(type) && xs_is_string(name)) {
608 if (strcmp(type, "Hashtag") == 0) {
609 xs *lc_name = xs_utf8_to_lower(name);
610
611 if (xs_list_in(fw_tags, lc_name) != -1)
612 return 1;
613 }
614 }
615 }
616 }
617 }
618 }
619
620 return 0;
621}
622
623
624void followed_hashtag_distribute(const xs_dict *msg)
625/* distribute this post to all users following the included hashtags */
626{
627 const char *id = xs_dict_get(msg, "id");
628 const xs_list *tags_in_msg = xs_dict_get(msg, "tag");
629
630 if (!xs_is_string(id) || !xs_is_list(tags_in_msg) || xs_list_len(tags_in_msg) == 0)
631 return;
632
633 srv_debug(1, xs_fmt("followed_hashtag_distribute check for %s", id));
634
635 xs *users = user_list();
636 const char *uid;
637
638 xs_list_foreach(users, uid) {
639 snac user;
640
641 if (user_open(&user, uid)) {
642 if (followed_hashtag_check(&user, msg)) {
643 timeline_add(&user, id, msg);
644
645 snac_log(&user, xs_fmt("followed hashtag in %s", id));
646 }
647
648 user_free(&user);
649 }
650 }
651}
652
653
590int is_msg_for_me(snac *snac, const xs_dict *c_msg) 654int is_msg_for_me(snac *snac, const xs_dict *c_msg)
591/* checks if this message is for me */ 655/* checks if this message is for me */
592{ 656{
@@ -602,19 +666,32 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
602 if (xs_match(type, "Like|Announce|EmojiReact")) { 666 if (xs_match(type, "Like|Announce|EmojiReact")) {
603 const char *object = xs_dict_get(c_msg, "object"); 667 const char *object = xs_dict_get(c_msg, "object");
604 668
605 if (xs_type(object) == XSTYPE_DICT) 669 if (xs_is_dict(object))
606 object = xs_dict_get(object, "id"); 670 object = xs_dict_get(object, "id");
607 671
608 /* bad object id? reject */ 672 /* bad object id? reject */
609 if (xs_type(object) != XSTYPE_STRING) 673 if (!xs_is_string(object))
610 return 0; 674 return 0;
611 675
612 /* if it's about one of our posts, accept it */ 676 /* if it's about one of our posts, accept it */
613 if (xs_startswith(object, snac->actor)) 677 if (xs_startswith(object, snac->actor))
614 return 2; 678 return 2;
615 679
616 /* if it's by someone we don't follow, reject */ 680 /* if it's by someone we follow, accept it */
617 return following_check(snac, actor); 681 if (following_check(snac, actor))
682 return 1;
683
684 /* do we follow any hashtag? */
685 if (xs_is_list(xs_dict_get(snac->config, "followed_hashtags"))) {
686 xs *obj = NULL;
687
688 /* if the admired object contains any followed hashtag, accept it */
689 if (valid_status(object_get(object, &obj)) &&
690 followed_hashtag_check(snac, obj))
691 return 7;
692 }
693
694 return 0;
618 } 695 }
619 696
620 /* if it's an Undo, it must be from someone related to us */ 697 /* if it's an Undo, it must be from someone related to us */
@@ -708,30 +785,8 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
708 } 785 }
709 786
710 /* does this message contain a tag we are following? */ 787 /* does this message contain a tag we are following? */
711 const xs_list *fw_tags = xs_dict_get(snac->config, "followed_hashtags"); 788 if (pub_msg && followed_hashtag_check(snac, msg))
712 if (pub_msg && xs_type(fw_tags) == XSTYPE_LIST) { 789 return 7;
713 const xs_list *tags_in_msg = xs_dict_get(msg, "tag");
714 if (xs_type(tags_in_msg) == XSTYPE_LIST) {
715 const xs_dict *te;
716
717 /* iterate the tags in the message */
718 xs_list_foreach(tags_in_msg, te) {
719 if (xs_type(te) == XSTYPE_DICT) {
720 const char *type = xs_dict_get(te, "type");
721 const char *name = xs_dict_get(te, "name");
722
723 if (xs_type(type) == XSTYPE_STRING && xs_type(name) == XSTYPE_STRING) {
724 if (strcmp(type, "Hashtag") == 0) {
725 xs *lc_name = xs_utf8_to_lower(name);
726
727 if (xs_list_in(fw_tags, lc_name) != -1)
728 return 7;
729 }
730 }
731 }
732 }
733 }
734 }
735 790
736 return 0; 791 return 0;
737} 792}
@@ -2277,15 +2332,23 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
2277 xs *who_o = NULL; 2332 xs *who_o = NULL;
2278 2333
2279 if (valid_status(actor_request(snac, who, &who_o))) { 2334 if (valid_status(actor_request(snac, who, &who_o))) {
2280 if (timeline_admire(snac, object, actor, 0) == HTTP_STATUS_CREATED) 2335 /* don't account as such announces by our own relay */
2281 snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); 2336 xs *this_relay = xs_fmt("%s/relay", srv_baseurl);
2282 else 2337
2283 snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", 2338 if (strcmp(actor, this_relay) != 0) {
2284 actor, object)); 2339 if (timeline_admire(snac, object, actor, 0) == HTTP_STATUS_CREATED)
2340 snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object));
2341 else
2342 snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s",
2343 actor, object));
2344 }
2285 2345
2286 /* distribute the post with the actor as 'proxy' */ 2346 /* distribute the post with the actor as 'proxy' */
2287 list_distribute(snac, actor, a_msg); 2347 list_distribute(snac, actor, a_msg);
2288 2348
2349 /* distribute the post to users following these hashtags */
2350 followed_hashtag_distribute(a_msg);
2351
2289 do_notify = 1; 2352 do_notify = 1;
2290 } 2353 }
2291 else 2354 else
@@ -2300,7 +2363,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
2300 } 2363 }
2301 else 2364 else
2302 if (strcmp(type, "Update") == 0) { /** **/ 2365 if (strcmp(type, "Update") == 0) { /** **/
2303 if (xs_match(utype, "Person|Service")) { /** **/ 2366 if (xs_match(utype, "Person|Service|Application")) { /** **/
2304 actor_add(actor, xs_dict_get(msg, "object")); 2367 actor_add(actor, xs_dict_get(msg, "object"));
2305 timeline_touch(snac); 2368 timeline_touch(snac);
2306 2369