From b2f5f95c7b8c8793f82d394009b0908888de5bdc Mon Sep 17 00:00:00 2001 From: default Date: Sat, 25 Jan 2025 23:06:08 +0100 Subject: Fixed repeated entries in the instance public timeline. --- data.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'data.c') diff --git a/data.c b/data.c index 33947ff..40382d2 100644 --- a/data.c +++ b/data.c @@ -1399,11 +1399,13 @@ void timeline_update_indexes(snac *snac, const char *id) if (valid_status(object_get(id, &msg))) { /* if its ours and is public, also store in public */ if (is_msg_public(msg)) { - object_user_cache_add(snac, id, "public"); - - /* also add it to the instance public timeline */ - xs *ipt = xs_fmt("%s/public.idx", srv_basedir); - index_add(ipt, id); + if (object_user_cache_add(snac, id, "public") >= 0) { + /* also add it to the instance public timeline */ + xs *ipt = xs_fmt("%s/public.idx", srv_basedir); + index_add(ipt, id); + } + else + srv_debug(1, xs_fmt("Not added to public instance index %s", id)); } } } @@ -1524,8 +1526,17 @@ xs_list *timeline_instance_list(int skip, int show) /* returns the timeline for the full instance */ { xs *idx = instance_index_fn(); + xs *lst = index_list_desc(idx, skip, show); - return 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); } -- cgit From 82bcc4b465f73a5d1f2eebcf3813452bc1c37fbd Mon Sep 17 00:00:00 2001 From: default Date: Mon, 27 Jan 2025 16:59:08 +0100 Subject: Minor optimization in timeline retrieving. Functions now receive an optional int *more, set to 1 if there are more than the 'show' requested. --- activitypub.c | 2 +- data.c | 24 ++++++++++++++++++------ html.c | 25 +++++++++++-------------- mastoapi.c | 2 +- snac.h | 4 ++-- 5 files changed, 33 insertions(+), 24 deletions(-) (limited to 'data.c') diff --git a/activitypub.c b/activitypub.c index cade0d9..bcb733a 100644 --- a/activitypub.c +++ b/activitypub.c @@ -3081,7 +3081,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path, int cnt = xs_number_get(xs_dict_get_def(srv_config, "max_public_entries", "20")); /* get the public outbox or the pinned list */ - xs *elems = *p_path == 'o' ? timeline_simple_list(&snac, "public", 0, cnt) : pinned_list(&snac); + xs *elems = *p_path == 'o' ? timeline_simple_list(&snac, "public", 0, cnt, NULL) : pinned_list(&snac); xs_list_foreach(elems, v) { xs *i = NULL; diff --git a/data.c b/data.c index 40382d2..550f7cf 100644 --- a/data.c +++ b/data.c @@ -1489,16 +1489,28 @@ xs_str *user_index_fn(snac *user, const char *idx_name) } -xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show) +xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show, int *more) /* returns a timeline (with all entries) */ { xs *idx = user_index_fn(user, idx_name); - return index_list_desc(idx, skip, show); + /* if a more flag is sent, request one more */ + xs_list *lst = index_list_desc(idx, skip, show + (more != NULL ? 1 : 0)); + + if (more != NULL) { + if (xs_list_len(lst) > show) { + *more = 1; + lst = xs_list_del(lst, -1); + } + else + *more = 0; + } + + return lst; } -xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show) +xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show, int *more) /* returns a timeline (only top level entries) */ { int c_max; @@ -1510,7 +1522,7 @@ xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show) if (show > c_max) show = c_max; - xs *list = timeline_simple_list(snac, idx_name, skip, show); + xs *list = timeline_simple_list(snac, idx_name, skip, show, more); return timeline_top_level(snac, list); } @@ -2709,9 +2721,9 @@ xs_list *content_search(snac *user, const char *regex, const char *md5s[3] = {0}; int c[3] = {0}; - tls[0] = timeline_simple_list(user, "public", 0, XS_ALL); /* public */ + tls[0] = timeline_simple_list(user, "public", 0, XS_ALL, NULL); /* public */ tls[1] = timeline_instance_list(0, XS_ALL); /* instance */ - tls[2] = priv ? timeline_simple_list(user, "private", 0, XS_ALL) : xs_list_new(); /* private or none */ + tls[2] = priv ? timeline_simple_list(user, "private", 0, XS_ALL, NULL) : xs_list_new(); /* private or none */ /* first positioning */ for (int n = 0; n < 3; n++) diff --git a/html.c b/html.c index 3b63cfc..bd94e9f 100644 --- a/html.c +++ b/html.c @@ -3314,21 +3314,17 @@ int html_get_handler(const xs_dict *req, const char *q_path, } else { xs *list = NULL; - xs *next = NULL; + int more = 0; - if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines"))) { - list = timeline_simple_list(&snac, "public", skip, show); - next = timeline_simple_list(&snac, "public", skip + show, 1); - } - else { - list = timeline_list(&snac, "public", skip, show); - next = timeline_list(&snac, "public", skip + show, 1); - } + if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines"))) + list = timeline_simple_list(&snac, "public", skip, show, &more); + else + list = timeline_list(&snac, "public", skip, show, &more); xs *pins = pinned_list(&snac); pins = xs_list_cat(pins, list); - *body = html_timeline(&snac, pins, 1, skip, show, xs_list_len(next), NULL, "", 1, error); + *body = html_timeline(&snac, pins, 1, skip, show, more, NULL, "", 1, error); *b_size = strlen(*body); status = HTTP_STATUS_OK; @@ -3490,13 +3486,14 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs_dict_get(req, "if-none-match"), etag); } else { + int more = 0; + snac_debug(&snac, 1, xs_fmt("building timeline")); - xs *list = timeline_list(&snac, "private", skip, show); - xs *next = timeline_list(&snac, "private", skip + show, 1); + xs *list = timeline_list(&snac, "private", skip, show, &more); *body = html_timeline(&snac, list, 0, skip, show, - xs_list_len(next), NULL, "/admin", 1, error); + more, NULL, "/admin", 1, error); *b_size = strlen(*body); status = HTTP_STATUS_OK; @@ -3702,7 +3699,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, int cnt = xs_number_get(xs_dict_get_def(srv_config, "max_public_entries", "20")); - xs *elems = timeline_simple_list(&snac, "public", 0, cnt); + xs *elems = timeline_simple_list(&snac, "public", 0, cnt, NULL); xs *bio = xs_dup(xs_dict_get(snac.config, "bio")); xs *rss_title = xs_fmt("%s (@%s@%s)", diff --git a/mastoapi.c b/mastoapi.c index 54b4333..3c445c2 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1676,7 +1676,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, else if (strcmp(opt, "statuses") == 0) { /** **/ /* the public list of posts of a user */ - xs *timeline = timeline_simple_list(&snac2, "public", 0, 256); + xs *timeline = timeline_simple_list(&snac2, "public", 0, 256, NULL); xs_list *p = timeline; const xs_str *v; diff --git a/snac.h b/snac.h index 344dbaa..278e798 100644 --- a/snac.h +++ b/snac.h @@ -157,8 +157,8 @@ int timeline_here(snac *snac, const char *md5); int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg); int timeline_del(snac *snac, const char *id); xs_str *user_index_fn(snac *user, const char *idx_name); -xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show); -xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show); +xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show, int *more); +xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show, int *more); int timeline_add(snac *snac, const char *id, const xs_dict *o_msg); int timeline_admire(snac *snac, const char *id, const char *admirer, int like); -- cgit From 1766d6bf92eb433841c03ccb096c636a4c5dc968 Mon Sep 17 00:00:00 2001 From: default Date: Mon, 27 Jan 2025 20:20:40 +0100 Subject: Added a 'No more unseen posts' mark. --- data.c | 8 ++++++++ html.c | 24 ++++++++++++++++++++++++ snac.h | 4 ++++ 3 files changed, 36 insertions(+) (limited to 'data.c') diff --git a/data.c b/data.c index 550f7cf..480a35b 100644 --- a/data.c +++ b/data.c @@ -1528,6 +1528,14 @@ xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show, int } +void timeline_add_mark(snac *user) +/* adds an "already seen" mark to the private timeline */ +{ + xs *fn = xs_fmt("%s/private.idx", user->basedir); + index_add_md5(fn, MD5_ALREADY_SEEN_MARK); +} + + xs_str *instance_index_fn(void) { return xs_fmt("%s/public.idx", srv_basedir); diff --git a/html.c b/html.c index bd94e9f..771d2af 100644 --- a/html.c +++ b/html.c @@ -2648,10 +2648,31 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_add(body, posts); + int mark_shown = 0; + while (xs_list_iter(&p, &v)) { xs *msg = NULL; int status; + /* "already seen" mark? */ + if (strcmp(v, MD5_ALREADY_SEEN_MARK) == 0) { + if (skip == 0 && !mark_shown) { + xs *s = xs_fmt("%s/admin#top", user->actor); + + xs_html_add(posts, + xs_html_text(L("No more unseen posts")), + xs_html_text(" - "), + xs_html_tag("a", + xs_html_attr("href", s), + xs_html_text(L("Back to top"))), + xs_html_sctag("hr", NULL)); + } + + mark_shown = 1; + + continue; + } + if (utl && user && !is_pinned_by_md5(user, v)) status = timeline_get_by_md5(user, v, &msg); else @@ -3473,6 +3494,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, } } else { + /** the private timeline **/ double t = history_mtime(&snac, "timeline.html_"); /* if enabled by admin, return a cached page if its timestamp is: @@ -3492,6 +3514,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = timeline_list(&snac, "private", skip, show, &more); + timeline_add_mark(&snac); + *body = html_timeline(&snac, list, 0, skip, show, more, NULL, "/admin", 1, error); diff --git a/snac.h b/snac.h index 278e798..6c3ccda 100644 --- a/snac.h +++ b/snac.h @@ -22,6 +22,8 @@ #define MD5_HEX_SIZE 33 +#define MD5_ALREADY_SEEN_MARK "00000000000000000000000000000000" + extern double disk_layout; extern xs_str *srv_basedir; extern xs_dict *srv_config; @@ -163,6 +165,8 @@ int timeline_add(snac *snac, const char *id, const xs_dict *o_msg); int timeline_admire(snac *snac, const char *id, const char *admirer, int like); xs_list *timeline_top_level(snac *snac, const xs_list *list); +void timeline_add_mark(snac *user); + xs_list *local_list(snac *snac, int max); xs_str *instance_index_fn(void); xs_list *timeline_instance_list(int skip, int show); -- cgit From 06ba1174ca7084a3d691aa8c2b552b708d04b8db Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 10:04:23 +0100 Subject: Some tweaks to the already seen mark code. --- data.c | 18 +++++++++++++++++- html.c | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'data.c') diff --git a/data.c b/data.c index 480a35b..7139cdf 100644 --- a/data.c +++ b/data.c @@ -1532,7 +1532,23 @@ void timeline_add_mark(snac *user) /* adds an "already seen" mark to the private timeline */ { xs *fn = xs_fmt("%s/private.idx", user->basedir); - index_add_md5(fn, MD5_ALREADY_SEEN_MARK); + char last_entry[MD5_HEX_SIZE] = ""; + FILE *f; + + /* get the last entry in the index */ + if ((f = fopen(fn, "r")) != NULL) { + index_desc_first(f, last_entry, 0); + fclose(f); + } + + /* is the last entry *not* a mark? */ + if (strcmp(last_entry, MD5_ALREADY_SEEN_MARK) != 0) { + /* add it */ + index_add_md5(fn, MD5_ALREADY_SEEN_MARK); + + /* mark as new */ + timeline_touch(user); + } } diff --git a/html.c b/html.c index c27ab99..8f8b524 100644 --- a/html.c +++ b/html.c @@ -2657,7 +2657,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, /* "already seen" mark? */ if (strcmp(v, MD5_ALREADY_SEEN_MARK) == 0) { if (skip == 0 && !mark_shown) { - xs *s = xs_fmt("%s/admin#top", user->actor); + xs *s = xs_fmt("%s/admin", user->actor); xs_html_add(posts, xs_html_tag("div", @@ -2665,7 +2665,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_text(L("No more unseen posts")), xs_html_text(" - "), xs_html_tag("a", - xs_html_attr("href", s), + xs_html_attr("href", s), xs_html_text(L("Back to top"))))); } -- cgit From aec643838f304468af61ca2ad4e00a9e7125e53b Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 20:36:37 +0100 Subject: Deleted useless code. --- data.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'data.c') diff --git a/data.c b/data.c index 7139cdf..50c6121 100644 --- a/data.c +++ b/data.c @@ -1545,9 +1545,6 @@ void timeline_add_mark(snac *user) if (strcmp(last_entry, MD5_ALREADY_SEEN_MARK) != 0) { /* add it */ index_add_md5(fn, MD5_ALREADY_SEEN_MARK); - - /* mark as new */ - timeline_touch(user); } } -- cgit From 4df4f0c5518cfe8ae90d098612e9d131f4a384f5 Mon Sep 17 00:00:00 2001 From: default Date: Wed, 5 Feb 2025 09:47:38 +0100 Subject: Fixed bug in search. --- data.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'data.c') diff --git a/data.c b/data.c index 50c6121..2f1a52b 100644 --- a/data.c +++ b/data.c @@ -2766,7 +2766,17 @@ xs_list *content_search(snac *user, const char *regex, for (int n = 0; n < 3; n++) { if (md5s[n] != NULL) { xs *fn = _object_fn_by_md5(md5s[n], "content_search"); - double mt = mtime(fn); + double mt; + + while ((mt = mtime(fn)) == 0 && md5s[n] != NULL) { + /* object is not here: move to the next one */ + if (xs_list_next(tls[n], &md5s[n], &c[n])) { + xs_free(fn); + fn = _object_fn_by_md5(md5s[n], "content_search_2"); + } + else + md5s[n] = NULL; + } if (mt > mtime) { newest = n; -- cgit From 22a23dbdd1fca4695c012c31d5e5502f38212ed8 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 6 Feb 2025 10:56:21 +0100 Subject: Minor tweak to inbox_list(). --- data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'data.c') diff --git a/data.c b/data.c index 2f1a52b..9fc54a0 100644 --- a/data.c +++ b/data.c @@ -2601,7 +2601,7 @@ xs_list *inbox_list(void) if ((f = fopen(v, "r")) != NULL) { xs *line = xs_readline(f); - if (line) { + if (line && *line) { line = xs_strip_i(line); ibl = xs_list_append(ibl, line); } -- cgit