aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrunfink <grunfink@comam.es>2025-08-16 16:42:50 +0200
committergrunfink <grunfink@comam.es>2025-08-16 16:42:50 +0200
commit86de22fe92560db8d0661a6f4ee9be07a84043a3 (patch)
tree4a4c5d5aedde7faae4909990911a8b681589d363
parent9558136f4153f75bf5b5dfe789f841489796b9eb (diff)
New function collect_replies().
-rw-r--r--activitypub.c88
-rw-r--r--main.c6
-rw-r--r--snac.h2
3 files changed, 96 insertions, 0 deletions
diff --git a/activitypub.c b/activitypub.c
index 634e243..a375584 100644
--- a/activitypub.c
+++ b/activitypub.c
@@ -936,6 +936,94 @@ xs_str *process_tags(snac *snac, const char *content, xs_list **tag)
}
+void collect_replies(snac *user, const char *id)
+/* collects all replies for a post */
+{
+ xs *obj = NULL;
+
+ if (!valid_status(object_get(id, &obj))) {
+ snac_debug(user, 1, xs_fmt("collect_replies: object '%s' is not here", id));
+ return;
+ }
+
+ const char *next = xs_dict_get_path(obj, "replies.first.next");
+ if (!xs_is_string(next)) {
+ snac_debug(user, 1, xs_fmt("collect_replies: object '%s' does not have a replies.first.next URL", id));
+ return;
+ }
+
+ /* pick the first level replies (may be empty) */
+ const xs_list *level0_replies = xs_dict_get_path(obj, "replies.first.items");
+
+ xs *reply_obj = NULL;
+
+ if (!valid_status(object_get(next, &reply_obj))) {
+ if (!valid_status(activitypub_request(user, next, &reply_obj))) {
+ snac_debug(user, 1, xs_fmt("collect_replies: cannot get replies object '%s'", next));
+ return;
+ }
+ }
+
+ const xs_list *level1_replies = xs_dict_get(reply_obj, "items");
+ if (!xs_is_list(level1_replies)) {
+ snac_debug(user, 1, xs_fmt("collect_replies: cannot get reply items from object '%s'", next));
+ return;
+ }
+
+ xs *items = NULL;
+
+ if (xs_is_list(level0_replies))
+ items = xs_list_cat(xs_dup(level0_replies), level1_replies);
+ else
+ items = xs_dup(level1_replies);
+
+ const xs_val *v;
+
+ xs_list_foreach(items, v) {
+ xs *reply = NULL;
+
+ if (xs_is_string(v)) {
+ /* request the object */
+ if (!valid_status(object_get(v, &reply))) {
+ if (!valid_status(activitypub_request(user, v, &reply))) {
+ snac_debug(user, 1, xs_fmt("collect_replies: error requesting object '%s'", v));
+ continue;
+ }
+ }
+ }
+ else
+ if (xs_is_dict(v)) {
+ /* actually the post object */
+ reply = xs_dup(v);
+ }
+
+ if (!xs_is_dict(reply))
+ continue;
+
+ const char *id = xs_dict_get(reply, "id");
+ const char *type = xs_dict_get(reply, "type");
+ const char *attr_to = get_atto(reply);
+
+ if (!xs_is_string(id) || !xs_is_string(type) || !xs_is_string(attr_to))
+ continue;
+
+ if (!xs_match(type, POSTLIKE_OBJECT_TYPE))
+ continue;
+
+ if (timeline_here(user, id)) {
+ snac_debug(user, 1, xs_fmt("collect_replies: item already in timeline %s", id));
+ continue;
+ }
+
+ enqueue_actor_refresh(user, attr_to, 0);
+
+ timeline_add(user, id, reply);
+
+ snac_log(user, xs_fmt("new '%s' (collect_replies) %s %s", type, attr_to, id));
+ }
+}
+
+
void notify(snac *snac, const char *type, const char *utype, const char *actor, const xs_dict *msg)
/* notifies the user of relevant events */
{
diff --git a/main.c b/main.c
index c4c298f..1e27302 100644
--- a/main.c
+++ b/main.c
@@ -730,6 +730,12 @@ int main(int argc, char *argv[])
return 0;
}
+ if (strcmp(cmd, "collect_replies") == 0) { /** **/
+ collect_replies(&snac, url);
+
+ return 0;
+ }
+
if (strcmp(cmd, "insert") == 0) { /** **/
int status;
xs *data = NULL;
diff --git a/snac.h b/snac.h
index c060363..82c4a98 100644
--- a/snac.h
+++ b/snac.h
@@ -334,6 +334,8 @@ const char *default_avatar_base64(void);
xs_str *process_tags(snac *snac, const char *content, xs_list **tag);
+void collect_replies(snac *user, const char *id);
+
const char *get_atto(const xs_dict *msg);
const char *get_in_reply_to(const xs_dict *msg);
xs_list *get_attachments(const xs_dict *msg);