From 085caa7747a3bbebbd2ec09b3264dc6fcc5a7624 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 19 Nov 2024 06:46:14 +0100 Subject: New function get_in_reply_to(). --- snac.h | 1 + 1 file changed, 1 insertion(+) (limited to 'snac.h') diff --git a/snac.h b/snac.h index ad2793e..8020978 100644 --- a/snac.h +++ b/snac.h @@ -296,6 +296,7 @@ const char *default_avatar_base64(void); xs_str *process_tags(snac *snac, const char *content, xs_list **tag); 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); xs_dict *msg_admiration(snac *snac, const char *object, const char *type); -- cgit From 775fb14706d92af9106b2ac0b87b4c4bd1f5b3ca Mon Sep 17 00:00:00 2001 From: default Date: Thu, 21 Nov 2024 15:12:22 +0100 Subject: Version 2.64 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'snac.h') diff --git a/snac.h b/snac.h index 8020978..0d62eb2 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ -#define VERSION "2.63" +#define VERSION "2.64" #define USER_AGENT "snac/" VERSION -- cgit From 7287776fd1f659619e211ee482ba0d6d64ddbf0b Mon Sep 17 00:00:00 2001 From: default Date: Sun, 24 Nov 2024 08:17:38 +0100 Subject: New function pending_add(). --- activitypub.c | 31 ++++++++++++++++++++----------- data.c | 22 ++++++++++++++++++++++ snac.h | 2 ++ 3 files changed, 44 insertions(+), 11 deletions(-) (limited to 'snac.h') diff --git a/activitypub.c b/activitypub.c index 649b1f2..3ab093f 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1927,22 +1927,31 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) object_add(actor, actor_obj); } - xs *f_msg = xs_dup(msg); - xs *reply = msg_accept(snac, f_msg, actor); + if (xs_is_true(xs_dict_get(snac->config, "approve_followers"))) { + pending_add(snac, actor, msg); - post_message(snac, actor, reply); - - if (xs_is_null(xs_dict_get(f_msg, "published"))) { - /* add a date if it doesn't include one (Mastodon) */ - xs *date = xs_str_utctime(0, ISO_DATE_SPEC); - f_msg = xs_dict_set(f_msg, "published", date); + snac_log(snac, xs_fmt("new pending follower approval %s", actor)); } + else { + /* automatic following */ + xs *f_msg = xs_dup(msg); + xs *reply = msg_accept(snac, f_msg, actor); - timeline_add(snac, id, f_msg); + post_message(snac, actor, reply); + + if (xs_is_null(xs_dict_get(f_msg, "published"))) { + /* add a date if it doesn't include one (Mastodon) */ + xs *date = xs_str_utctime(0, ISO_DATE_SPEC); + f_msg = xs_dict_set(f_msg, "published", date); + } - follower_add(snac, actor); + timeline_add(snac, id, f_msg); + + follower_add(snac, actor); + + snac_log(snac, xs_fmt("new follower %s", actor)); + } - snac_log(snac, xs_fmt("new follower %s", actor)); do_notify = 1; } else diff --git a/data.c b/data.c index bbebdb8..fa631e1 100644 --- a/data.c +++ b/data.c @@ -1202,6 +1202,28 @@ xs_list *follower_list(snac *snac) } +/** pending followers **/ + +int pending_add(snac *user, const char *actor, const xs_dict *msg) +/* stores the follow message for later confirmation */ +{ + xs *dir = xs_fmt("%s/pending", user->basedir); + xs *md5 = xs_md5_hex(actor, strlen(actor)); + xs *fn = xs_fmt("%s/%s.json", dir, md5); + FILE *f; + + mkdirx(dir); + + if ((f = fopen(fn, "w")) == NULL) + return -1; + + xs_json_dump(msg, 4, f); + fclose(f); + + return 0; +} + + /** timeline **/ double timeline_mtime(snac *snac) diff --git a/snac.h b/snac.h index 0d62eb2..bcddab4 100644 --- a/snac.h +++ b/snac.h @@ -141,6 +141,8 @@ int follower_del(snac *snac, const char *actor); int follower_check(snac *snac, const char *actor); xs_list *follower_list(snac *snac); +int pending_add(snac *user, const char *actor, const xs_dict *msg); + double timeline_mtime(snac *snac); int timeline_touch(snac *snac); int timeline_here(snac *snac, const char *md5); -- cgit From b91177cb464ffdb118d50569592be3f9789dbef6 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 24 Nov 2024 08:31:01 +0100 Subject: New function pending_get() and pending_list(). --- data.c | 38 ++++++++++++++++++++++++++++++++++++++ snac.h | 2 ++ 2 files changed, 40 insertions(+) (limited to 'snac.h') diff --git a/data.c b/data.c index fa631e1..79c7001 100644 --- a/data.c +++ b/data.c @@ -1224,6 +1224,44 @@ int pending_add(snac *user, const char *actor, const xs_dict *msg) } +xs_dict *pending_get(snac *user, const char *actor) +/* returns the pending follow confirmation for the actor */ +{ + xs *md5 = xs_md5_hex(actor, strlen(actor)); + xs *fn = xs_fmt("%s/pending/%s.json", user->basedir, md5); + xs_dict *msg = NULL; + FILE *f; + + if ((f = fopen(fn, "r")) != NULL) { + msg = xs_json_load(f); + fclose(f); + } + + return msg; +} + + +xs_list *pending_list(snac *user) +/* returns a list of pending follow confirmations */ +{ + xs *spec = xs_fmt("%s/pending/""*.json", user->basedir); + xs *l = xs_glob(spec, 0, 0); + xs_list *r = xs_list_new(); + const char *v; + + xs_list_foreach(l, v) { + const char *actor = xs_dict_get(v, "actor"); + + if (xs_type(actor) == XSTYPE_STRING) { + xs *md5 = xs_md5_hex(actor, strlen(actor)); + r = xs_list_append(r, md5); + } + } + + return r; +} + + /** timeline **/ double timeline_mtime(snac *snac) diff --git a/snac.h b/snac.h index bcddab4..25f7b74 100644 --- a/snac.h +++ b/snac.h @@ -142,6 +142,8 @@ int follower_check(snac *snac, const char *actor); xs_list *follower_list(snac *snac); int pending_add(snac *user, const char *actor, const xs_dict *msg); +xs_dict *pending_get(snac *user, const char *actor); +xs_list *pending_list(snac *user); double timeline_mtime(snac *snac); int timeline_touch(snac *snac); -- cgit From 129049edf4752495f768b247253cb7ffc848b0cc Mon Sep 17 00:00:00 2001 From: default Date: Sun, 24 Nov 2024 08:37:19 +0100 Subject: New function pending_check() and pending_del(). --- data.c | 20 ++++++++++++++++++++ snac.h | 2 ++ 2 files changed, 22 insertions(+) (limited to 'snac.h') diff --git a/data.c b/data.c index 79c7001..8bc35aa 100644 --- a/data.c +++ b/data.c @@ -1224,6 +1224,16 @@ int pending_add(snac *user, const char *actor, const xs_dict *msg) } +int pending_check(snac *user, const char *actor) +/* checks if there is a pending follow confirmation for the actor */ +{ + xs *md5 = xs_md5_hex(actor, strlen(actor)); + xs *fn = xs_fmt("%s/pending/%s.json", user->basedir, md5); + + return mtime(fn) != 0; +} + + xs_dict *pending_get(snac *user, const char *actor) /* returns the pending follow confirmation for the actor */ { @@ -1241,6 +1251,16 @@ xs_dict *pending_get(snac *user, const char *actor) } +void pending_del(snac *user, const char *actor) +/* deletes a pending follow confirmation for the actor */ +{ + xs *md5 = xs_md5_hex(actor, strlen(actor)); + xs *fn = xs_fmt("%s/pending/%s.json", user->basedir, md5); + + unlink(fn); +} + + xs_list *pending_list(snac *user) /* returns a list of pending follow confirmations */ { diff --git a/snac.h b/snac.h index 25f7b74..b4cb525 100644 --- a/snac.h +++ b/snac.h @@ -142,7 +142,9 @@ int follower_check(snac *snac, const char *actor); xs_list *follower_list(snac *snac); int pending_add(snac *user, const char *actor, const xs_dict *msg); +int pending_check(snac *user, const char *actor); xs_dict *pending_get(snac *user, const char *actor); +void pending_del(snac *user, const char *actor); xs_list *pending_list(snac *user); double timeline_mtime(snac *snac); -- cgit From 0db1cf05d1013f9b1e972ae79822f9eda4dede59 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 24 Nov 2024 09:14:59 +0100 Subject: New web actions "Approve" and "Discard". --- html.c | 28 ++++++++++++++++++++++++++++ snac.h | 1 + 2 files changed, 29 insertions(+) (limited to 'snac.h') diff --git a/html.c b/html.c index 990fb94..576d94f 100644 --- a/html.c +++ b/html.c @@ -3699,6 +3699,34 @@ int html_post_handler(const xs_dict *req, const char *q_path, unbookmark(&snac, id); timeline_touch(&snac); } + else + if (strcmp(action, L("Approve")) == 0) { /** **/ + xs *fwreq = pending_get(&snac, actor); + + if (fwreq != NULL) { + xs *reply = msg_accept(&snac, fwreq, actor); + + enqueue_message(&snac, reply); + + if (xs_is_null(xs_dict_get(fwreq, "published"))) { + /* add a date if it doesn't include one (Mastodon) */ + xs *date = xs_str_utctime(0, ISO_DATE_SPEC); + fwreq = xs_dict_set(fwreq, "published", date); + } + + timeline_add(&snac, xs_dict_get(fwreq, "id"), fwreq); + + follower_add(&snac, actor); + + pending_del(&snac, actor); + + snac_log(&snac, xs_fmt("new follower %s", actor)); + } + } + else + if (strcmp(action, L("Discard")) == 0) { /** **/ + pending_del(&snac, actor); + } else status = HTTP_STATUS_NOT_FOUND; diff --git a/snac.h b/snac.h index b4cb525..fc7a657 100644 --- a/snac.h +++ b/snac.h @@ -320,6 +320,7 @@ xs_dict *msg_update(snac *snac, const xs_dict *object); xs_dict *msg_ping(snac *user, const char *rcpt); xs_dict *msg_pong(snac *user, const char *rcpt, const char *object); xs_dict *msg_move(snac *user, const char *new_account); +xs_dict *msg_accept(snac *snac, const xs_val *object, const char *to); xs_dict *msg_question(snac *user, const char *content, xs_list *attach, const xs_list *opts, int multiple, int end_secs); -- cgit From 76654f1bfa76cef43fbb88d316b4c677fd8a89bb Mon Sep 17 00:00:00 2001 From: default Date: Sun, 24 Nov 2024 09:26:54 +0100 Subject: Bumped version. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'snac.h') diff --git a/snac.h b/snac.h index fc7a657..7a262a9 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ -#define VERSION "2.64" +#define VERSION "2.65-dev" #define USER_AGENT "snac/" VERSION -- cgit From 2eff3ffb664d372d68ab2d953466d7ba946c96c2 Mon Sep 17 00:00:00 2001 From: default Date: Mon, 25 Nov 2024 10:08:50 +0100 Subject: Most CSV import code has been moved to their own functions. --- snac.h | 4 ++++ utils.c | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'snac.h') diff --git a/snac.h b/snac.h index 7a262a9..9e00351 100644 --- a/snac.h +++ b/snac.h @@ -404,6 +404,10 @@ void verify_links(snac *user); void export_csv(snac *user); int migrate_account(snac *user); + +void import_blocked_accounts_csv(snac *user, const char *fn); +void import_following_accounts_csv(snac *user, const char *fn); +void import_list_csv(snac *user, const char *fn); void import_csv(snac *user); typedef enum { diff --git a/utils.c b/utils.c index 42200aa..b0d8193 100644 --- a/utils.c +++ b/utils.c @@ -670,13 +670,11 @@ void export_csv(snac *user) } -void import_csv(snac *user) -/* import CSV files from Mastodon */ +void import_blocked_accounts_csv(snac *user, const char *fn) +/* imports a Mastodon CSV file of blocked accounts */ { FILE *f; - const char *fn; - fn = "blocked_accounts.csv"; if ((f = fopen(fn, "r")) != NULL) { snac_log(user, xs_fmt("Importing from %s...", fn)); @@ -704,8 +702,14 @@ void import_csv(snac *user) } else snac_log(user, xs_fmt("Cannot open file %s", fn)); +} + + +void import_following_accounts_csv(snac *user, const char *fn) +/* imports a Mastodon CSV file of accounts to follow */ +{ + FILE *f; - fn = "following_accounts.csv"; if ((f = fopen(fn, "r")) != NULL) { snac_log(user, xs_fmt("Importing from %s...", fn)); @@ -757,8 +761,14 @@ void import_csv(snac *user) } else snac_log(user, xs_fmt("Cannot open file %s", fn)); +} + + +void import_list_csv(snac *user, const char *fn) +/* imports a Mastodon CSV file list */ +{ + FILE *f; - fn = "lists.csv"; if ((f = fopen(fn, "r")) != NULL) { snac_log(user, xs_fmt("Importing from %s...", fn)); @@ -808,6 +818,20 @@ void import_csv(snac *user) } else snac_log(user, xs_fmt("Cannot open file %s", fn)); +} + + +void import_csv(snac *user) +/* import CSV files from Mastodon */ +{ + FILE *f; + const char *fn; + + import_blocked_accounts_csv(user, "blocked_accounts.csv"); + + import_following_accounts_csv(user, "following_accounts.csv"); + + import_list_csv(user, "lists.csv"); fn = "bookmarks.csv"; if ((f = fopen(fn, "r")) != NULL) { -- cgit From 22d05cded1f1cb23b90ded9f9c1ad24b02718c2b Mon Sep 17 00:00:00 2001 From: default Date: Tue, 26 Nov 2024 17:15:54 +0100 Subject: Version 2.65 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'snac.h') diff --git a/snac.h b/snac.h index 9e00351..3f4fb81 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ -#define VERSION "2.65-dev" +#define VERSION "2.65" #define USER_AGENT "snac/" VERSION -- cgit From 203db3b09e3ebf8677f75e83e5470b99c74de470 Mon Sep 17 00:00:00 2001 From: default Date: Wed, 4 Dec 2024 05:51:17 +0100 Subject: Fixed bug in blocked instance rejection. --- html.c | 3 +++ mastoapi.c | 3 +++ snac.h | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'snac.h') diff --git a/html.c b/html.c index f8fb876..26831f5 100644 --- a/html.c +++ b/html.c @@ -1524,6 +1524,9 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if ((read_only || !user) && !is_msg_public(msg)) return NULL; + if (is_instance_blocked(id)) + return NULL; + if (user && level == 0 && xs_is_true(xs_dict_get(user->config, "collapse_threads"))) collapse_threads = 1; diff --git a/mastoapi.c b/mastoapi.c index a529990..0332629 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1349,6 +1349,9 @@ xs_list *mastoapi_timeline(snac *user, const xs_dict *args, const char *index_fn if (!xs_match(type, POSTLIKE_OBJECT_TYPE)) continue; + if (is_instance_blocked(id)) + continue; + const char *from = NULL; if (strcmp(type, "Page") == 0) from = xs_dict_get(msg, "audience"); diff --git a/snac.h b/snac.h index 3f4fb81..a3c055b 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ -#define VERSION "2.65" +#define VERSION "2.66-dev" #define USER_AGENT "snac/" VERSION -- cgit