commit 59f3b54
grunfink
·
2025-09-03 04:08:13 +0000 UTC
parent d23fc31
New function collect_outbox().
3 files changed,
+107,
-0
+101,
-0
1@@ -1021,6 +1021,107 @@ void collect_replies(snac *user, const char *id)
2 }
3
4
5+void collect_outbox(snac *user, const char *actor_id)
6+/* gets an actor's outbox and inserts a bunch of posts in a user's timeline */
7+{
8+ int status;
9+ xs *actor = NULL;
10+
11+ if (!valid_status(status = actor_request(user, actor_id, &actor))) {
12+ snac_debug(user, 1, xs_fmt("collect_outbox: cannot get actor object '%s' %d", actor_id, status));
13+ return;
14+ }
15+
16+ xs *outbox = NULL;
17+ const char *outbox_url = xs_dict_get(actor, "outbox");
18+
19+ if (!xs_is_string(outbox_url))
20+ return;
21+
22+ if (!valid_status(status = activitypub_request(user, outbox_url, &outbox))) {
23+ snac_debug(user, 1, xs_fmt("collect_outbox: cannot get actor outbox '%s' %d", outbox_url, status));
24+ return;
25+ }
26+
27+ const xs_list *ordered_items = xs_dict_get(outbox, "orderedItems");
28+
29+ if (!xs_is_list(ordered_items)) {
30+ /* the list is not here; does it have a 'first'? */
31+ const char *first = xs_dict_get(outbox, "first");
32+
33+ if (xs_is_string(first)) {
34+ /* download this instead */
35+ xs *first2 = xs_dup(first);
36+ xs_free(outbox);
37+
38+ if (!valid_status(status = activitypub_request(user, first2, &outbox))) {
39+ snac_debug(user, 1, xs_fmt("collect_outbox: cannot get first page of outbox '%s' %d", first2, status));
40+ return;
41+ }
42+
43+ /* last chance */
44+ ordered_items = xs_dict_get(outbox, "orderedItems");
45+ }
46+ }
47+
48+ if (!xs_is_list(ordered_items)) {
49+ snac_debug(user, 1, xs_fmt("collect_outbox: cannot get list of posts for actor '%s' outbox", actor_id));
50+ return;
51+ }
52+
53+ /* well, ok, then */
54+ int max = 4;
55+ const xs_val *v;
56+
57+ xs_list_foreach(ordered_items, v) {
58+ if (max == 0)
59+ break;
60+
61+ xs *post = NULL;
62+
63+ if (xs_is_string(v)) {
64+ /* it's probably the post url */
65+ if (!valid_status(activitypub_request(user, v, &post)))
66+ continue;
67+ }
68+ else
69+ if (xs_is_dict(v))
70+ post = xs_dup(v);
71+
72+ if (post == NULL)
73+ continue;
74+
75+ const char *type = xs_dict_get(post, "type");
76+
77+ if (!xs_is_string(type) || strcmp(type, "Create")) {
78+ /* not a post */
79+ continue;
80+ }
81+
82+ const xs_dict *object = xs_dict_get(post, "object");
83+
84+ if (!xs_is_dict(object))
85+ continue;
86+
87+ type = xs_dict_get(object, "type");
88+ const char *id = xs_dict_get(object, "id");
89+ const char *attr_to = get_atto(object);
90+
91+ if (!xs_is_string(type) || !xs_is_string(id) || !xs_is_string(attr_to))
92+ continue;
93+
94+ if (!timeline_here(user, id)) {
95+ timeline_add(user, id, object);
96+ snac_log(user, xs_fmt("new '%s' (collect_outbox) %s %s", type, attr_to, id));
97+ }
98+ else
99+ snac_debug(user, 1, xs_fmt("collect_outbox: post '%s' already here", id));
100+
101+ max--;
102+ }
103+}
104+
105+
106 void notify(snac *snac, const char *type, const char *utype, const char *actor, const xs_dict *msg)
107 /* notifies the user of relevant events */
108 {
M
main.c
+5,
-0
1@@ -738,6 +738,11 @@ int main(int argc, char *argv[])
2 return 0;
3 }
4
5+ if (strcmp(cmd, "collect_outbox") == 0) { /** **/
6+ collect_outbox(&snac, url);
7+ return 0;
8+ }
9+
10 if (strcmp(cmd, "insert") == 0) { /** **/
11 int status;
12 xs *data = NULL;
M
snac.h
+1,
-0
1@@ -336,6 +336,7 @@ const char *default_avatar_base64(void);
2 xs_str *process_tags(snac *snac, const char *content, xs_list **tag);
3
4 void collect_replies(snac *user, const char *id);
5+void collect_outbox(snac *user, const char *actor_id);
6
7 const char *get_atto(const xs_dict *msg);
8 const char *get_in_reply_to(const xs_dict *msg);