aboutsummaryrefslogtreecommitdiff
path: root/neighborhood.c
diff options
context:
space:
mode:
Diffstat (limited to 'neighborhood.c')
-rw-r--r--neighborhood.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/neighborhood.c b/neighborhood.c
new file mode 100644
index 0000000..964a633
--- /dev/null
+++ b/neighborhood.c
@@ -0,0 +1,90 @@
+/* snac - A simple, minimalistic ActivityPub instance */
+/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */
+
+/* BEGIN neighborhood */
+/* neighborhood feed: feed of public posts from servers listed in server.json
+ under the "neighborhood" key. */
+
+#include "xs.h"
+#include "xs_set.h"
+
+#include "snac.h"
+
+xs_str *neighborhood_index_fn(void)
+/* returns the filename of the neighborhood index */
+{
+ return xs_fmt("%s/neighborhood.idx", srv_basedir);
+}
+
+
+int neighborhood_contains_actor(const char *actor)
+/* 1 if the actor's host is in srv_config["neighborhood"], 0 otherwise */
+{
+ if (!xs_is_string(actor) || *actor == '\0')
+ return 0;
+
+ const xs_list *neighborhoods = xs_dict_get(srv_config, "neighborhood");
+ if (xs_type(neighborhoods) != XSTYPE_LIST)
+ return 0;
+
+ /* extract host: third segment of "https://host/..." */
+ xs *parts = xs_split(actor, "/");
+ const char *raw_host = xs_list_get(parts, 2);
+ if (!xs_is_string(raw_host) || *raw_host == '\0')
+ return 0;
+
+ xs *host = xs_tolower_i(xs_dup(raw_host));
+
+ const xs_str *v;
+ int c = 0;
+ while (xs_list_next(neighborhoods, &v, &c)) {
+ if (!xs_is_string(v))
+ continue;
+ xs *candidate = xs_tolower_i(xs_dup(v));
+ if (strcmp(host, candidate) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+void neighborhood_update_indexes(const char *id, const xs_dict *msg)
+/* adds id to neighborhood.idx when the author's host is allowlisted and the post is public */
+{
+ if (!xs_is_string(id) || msg == NULL)
+ return;
+
+ if (xs_type(xs_dict_get(srv_config, "neighborhood")) != XSTYPE_LIST)
+ return;
+
+ if (get_msg_visibility(msg) != SCOPE_PUBLIC)
+ return;
+
+ const char *atto = get_atto(msg);
+ if (!neighborhood_contains_actor(atto))
+ return;
+
+ xs *fn = neighborhood_index_fn();
+ if (!index_in(fn, id))
+ index_add(fn, id);
+}
+
+
+xs_list *timeline_neighborhood_list(int skip, int show)
+/* returns the timeline for the neighborhood */
+{
+ xs *idx = neighborhood_index_fn();
+ xs *lst = index_list_desc(idx, skip, show);
+
+ /* make the list unique */
+ xs_set rep;
+ xs_set_init(&rep);
+ const char *md5;
+
+ xs_list_foreach(lst, md5)
+ xs_set_add(&rep, md5);
+
+ return xs_set_result(&rep);
+}
+/* END neighborhood */