aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhanchan <dev@hanchan.vip>2026-05-27 17:26:33 +0800
committerhanchan <dev@hanchan.vip>2026-05-27 17:26:33 +0800
commit5182a3384e80462e08713903c14b9cdecf56cdfb (patch)
tree7e1eba6b67fc3fcc71e6b91835cec247be8b2499
parent0bde1abe67aee7e7840338afef1022bcec3a1bd8 (diff)
add keep_replied_posts and keep_replied_me feathers, and auto-mention post author when reply to a post
-rw-r--r--data.c31
-rw-r--r--doc/snac.85
-rw-r--r--html.c21
-rw-r--r--utils.c4
4 files changed, 60 insertions, 1 deletions
diff --git a/data.c b/data.c
index 37c9325..3f7ba29 100644
--- a/data.c
+++ b/data.c
@@ -1562,6 +1562,37 @@ void timeline_update_indexes(snac *snac, const char *id)
else
/* also add it to public, it will be discarded later */
object_user_cache_add(snac, id, "public");
+
+ /* if `keep_replied_posts` is `true` and a local post is a reply to a remote post, add the parent remote post to the public */
+ if (xs_is_true(xs_dict_get(srv_config, "keep_replied_posts"))) {
+ const char *in_reply_to = get_in_reply_to(msg);
+
+ if (xs_is_string(in_reply_to) && *in_reply_to &&
+ !is_msg_mine(snac, in_reply_to)) {
+ if (object_user_cache_add(snac, in_reply_to, "public") >= 0) {
+ snac_debug(snac, 1,
+ xs_fmt("keep_replied_posts: added parent %s to public", in_reply_to));
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* if `keep_replied_me` is `true` and a remote post is a reply to one of local posts, add it to public */
+ if (xs_is_true(xs_dict_get(srv_config, "keep_replied_me"))) {
+ xs *msg = NULL;
+
+ if (valid_status(object_get(id, &msg))) {
+ const char *in_reply_to = get_in_reply_to(msg);
+
+ if (xs_is_string(in_reply_to) && *in_reply_to &&
+ is_msg_mine(snac, in_reply_to)) {
+ if (object_user_cache_add(snac, id, "public") >= 0) {
+ snac_debug(snac, 1,
+ xs_fmt("keep_replied_me: added reply %s to public", id));
+ }
+ }
+ }
}
}
}
diff --git a/doc/snac.8 b/doc/snac.8
index ef93d31..5698ce1 100644
--- a/doc/snac.8
+++ b/doc/snac.8
@@ -327,6 +327,11 @@ Overrides the default "mogrify" command name or path. Use this if the tool is no
Overrides the default "ffmpeg" command name or path. Use this if the tool is not in the system PATH or has a different name.
.It Ic purge_static
If set to true, user static directories are purged; any file stored in these subdirectories (usually images or other media) that is not attached to any post, not used as avatar, header or favicon, and not served as an emoji, is deleted from the filesystem. Don't enable this option if any of your users are serving other files (like, e.g., CSS assets) this way.
+.It Ic keep_replied_posts
+If set to true, when you reply to a remote post, the parent remote post will be added to local public timeline.
+.It Ic keep_replied_me
+If set to true, when a remote user replies to one of local posts, the
+remote reply will be added to local public timeline.
.El
.Pp
You must restart the server to make effective these changes.
diff --git a/html.c b/html.c
index ecd7fd7..a553d8c 100644
--- a/html.c
+++ b/html.c
@@ -2035,6 +2035,27 @@ xs_str *build_mentions(snac *user, const xs_dict *msg)
}
}
+ /* also add the author of this post as a mention */
+ const char *atto = get_atto(msg);
+
+ if (xs_is_string(atto) && *atto && strcmp(atto, user->actor) != 0) {
+ /* check if this author is already in the mentions string */
+ xs *l = xs_split(atto, "/");
+
+ if (xs_list_len(l) > 3) {
+ xs *actor_o = NULL;
+ if (valid_status(object_get(atto, &actor_o))) {
+ const char *uname = xs_dict_get(actor_o, "preferredUsername");
+ if (!xs_is_null(uname) && *uname) {
+ xs *handle = xs_fmt("@%s@%s ", uname, xs_list_get(l, 2));
+ if (xs_str_in(s, handle) == -1) {
+ s = xs_str_cat(s, handle);
+ }
+ }
+ }
+ }
+ }
+
if (*s) {
xs *s1 = s;
s = xs_fmt("\n\n\nCC: %s", s1);
diff --git a/utils.c b/utils.c
index c36587a..9475bd7 100644
--- a/utils.c
+++ b/utils.c
@@ -44,7 +44,9 @@ static const char * const default_srv_config = "{"
"\"protocol\": \"https\","
"\"fastcgi\": false,"
"\"disable_inbox_collection\": true,"
- "\"disable_history\": true"
+ "\"disable_history\": true,"
+ "\"keep_replied_posts\": false,"
+ "\"keep_replied_me\": false"
"}";
static const char * const default_css =