From 6b1721c977294ee28f54150579c36514aa3ee62a Mon Sep 17 00:00:00 2001 From: default Date: Tue, 7 May 2024 19:40:28 +0200 Subject: [PATCH 1/8] List timelines can now be (manually) navigated from the web UI. URLs are {srv_baseurl}/{user}/list/{list_id} (you must know the list id). --- data.c | 24 +++++++++++++++++++----- html.c | 23 +++++++++++++++++++++++ mastoapi.c | 2 +- snac.h | 1 + 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/data.c b/data.c index b9c1141..5b4936b 100644 --- a/data.c +++ b/data.c @@ -1836,6 +1836,23 @@ xs_val *list_maint(snac *user, const char *list, int op) } +xs_list *list_timeline(snac *user, const char *list, int skip, int show) +/* returns the timeline of a list */ +{ + xs_list *l = NULL; + + if (!xs_is_hex(list)) + return NULL; + + xs *fn = xs_fmt("%s/list/%s.idx", user->basedir, list); + + if (mtime(fn) > 0.0) + l = index_list_desc(fn, skip, show); + + return l; +} + + xs_val *list_content(snac *user, const char *list, const char *actor_md5, int op) /* list content management */ { @@ -1869,11 +1886,8 @@ xs_val *list_content(snac *user, const char *list, const char *actor_md5, int op break; - case 3: /** list timeline **/ - fn = xs_replace_i(fn, ".lst", ".idx"); - - l = index_list_desc(fn, 0, 2048); - + default: + srv_log(xs_fmt("ERROR: list_content: bad op %d", op)); break; } diff --git a/html.c b/html.c index ee5c2cd..b34fc81 100644 --- a/html.c +++ b/html.c @@ -2658,6 +2658,29 @@ int html_get_handler(const xs_dict *req, const char *q_path, } } else + if (xs_startswith(p_path, "list/")) { /** list timelines **/ + if (!login(&snac, req)) { + *body = xs_dup(uid); + status = 401; + } + else { + xs *l = xs_split(p_path, "/"); + char *lid = xs_list_get(l, -1); + + xs *list = list_timeline(&snac, lid, skip, show); + xs *next = list_timeline(&snac, lid, skip + show, 1); + + if (list != NULL) { + xs *base = xs_fmt("/list/%s", lid); + + *body = html_timeline(&snac, list, 0, skip, show, + xs_list_len(next), NULL, base, 0); + *b_size = strlen(*body); + status = 200; + } + } + } + else if (xs_startswith(p_path, "p/")) { /** a timeline with just one entry **/ if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) return 403; diff --git a/mastoapi.c b/mastoapi.c index 1f7f0b2..d39a6f9 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1669,7 +1669,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, xs *l = xs_split(cmd, "/"); char *list = xs_list_get(l, -1); - xs *timeline = list_content(&snac1, list, NULL, 3); + xs *timeline = list_timeline(&snac1, list, 0, 2048); xs *out = xs_list_new(); int c = 0; char *md5; diff --git a/snac.h b/snac.h index 481a1ae..ab8fc7c 100644 --- a/snac.h +++ b/snac.h @@ -175,6 +175,7 @@ void tag_index(const char *id, const xs_dict *obj); xs_list *tag_search(char *tag, int skip, int show); xs_val *list_maint(snac *user, const char *list, int op); +xs_list *list_timeline(snac *user, const char *list, int skip, int show); xs_val *list_content(snac *user, const char *list_id, const char *actor_md5, int op); void list_distribute(snac *user, const char *who, const xs_dict *post); From b57409a9590c737da66c0aaa679a47c2c947fbf8 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 7 May 2024 19:45:10 +0200 Subject: [PATCH 2/8] Fixed typo. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index b34fc81..536879c 100644 --- a/html.c +++ b/html.c @@ -2674,7 +2674,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *base = xs_fmt("/list/%s", lid); *body = html_timeline(&snac, list, 0, skip, show, - xs_list_len(next), NULL, base, 0); + xs_list_len(next), NULL, base, 1); *b_size = strlen(*body); status = 200; } From 82ec4ea95cb1040c5b9b983ec649dbde024d20f8 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 7 May 2024 20:32:13 +0200 Subject: [PATCH 3/8] Minor "Back to top" "More..." link refactoring. --- html.c | 34 ++++++++++++++-------------------- httpd.c | 10 +++++++--- snac.h | 2 +- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/html.c b/html.c index 536879c..bd3179d 100644 --- a/html.c +++ b/html.c @@ -509,7 +509,7 @@ xs_html *html_instance_head(void) } -static xs_html *html_instance_body(char *tag) +static xs_html *html_instance_body(char *title) { char *host = xs_dict_get(srv_config, "host"); char *sdesc = xs_dict_get(srv_config, "short_description"); @@ -560,14 +560,11 @@ static xs_html *html_instance_body(char *tag) xs_html_text(handle))))); } - { - xs *l = tag ? xs_fmt(L("Search results for #%s"), tag) : - xs_dup(L("Recent posts by users in this instance")); - + if (title != NULL) { xs_html_add(body, xs_html_tag("h2", xs_html_attr("class", "snac-header"), - xs_html_text(l))); + xs_html_text(title))); } return body; @@ -1996,7 +1993,7 @@ xs_html *html_footer(void) xs_str *html_timeline(snac *user, const xs_list *list, int read_only, int skip, int show, int show_more, - char *tag, char *page, int utl) + char *title, char *page, int utl) /* returns the HTML for the timeline */ { xs_list *p = (xs_list *)list; @@ -2026,7 +2023,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, } else { head = html_instance_head(); - body = html_instance_body(tag); + body = html_instance_body(title); } xs_html *html = xs_html_tag("html", @@ -2126,25 +2123,22 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, } if (show_more) { - xs *t = NULL; xs *m = NULL; xs *ss = xs_fmt("skip=%d&show=%d", skip + show, show); - xs *url = page == NULL || user == NULL ? - xs_dup(srv_baseurl) : xs_fmt("%s%s", user->actor, page); + xs *url = xs_dup(user == NULL ? srv_baseurl : user->actor); - if (tag) { - t = xs_fmt("%s?t=%s", url, tag); - m = xs_fmt("%s&%s", t, ss); - } - else { - t = xs_dup(url); - m = xs_fmt("%s?%s", t, ss); - } + if (page != NULL) + url = xs_str_cat(url, page); + + if (xs_str_in(url, "?") != -1) + m = xs_fmt("%s&%s", url, ss); + else + m = xs_fmt("%s?%s", url, ss); xs_html *more_links = xs_html_tag("p", xs_html_tag("a", - xs_html_attr("href", t), + xs_html_attr("href", url), xs_html_attr("name", "snac-more"), xs_html_text(L("Back to top"))), xs_html_text(" - "), diff --git a/httpd.c b/httpd.c index 30367c8..81b0853 100644 --- a/httpd.c +++ b/httpd.c @@ -200,14 +200,18 @@ int server_get_handler(xs_dict *req, const char *q_path, *body = timeline_to_rss(NULL, tl, link, link, link); *ctype = "application/rss+xml; charset=utf-8"; } - else - *body = html_timeline(NULL, tl, 0, skip, show, more, t, NULL, 0); + else { + xs *page = xs_fmt("?t=%s", t); + xs *title = xs_fmt(L("Search results for #%s"), t); + *body = html_timeline(NULL, tl, 0, skip, show, more, title, page, 0); + } } else if (xs_type(xs_dict_get(srv_config, "show_instance_timeline")) == XSTYPE_TRUE) { /** instance timeline **/ xs *tl = timeline_instance_list(0, 30); - *body = html_timeline(NULL, tl, 0, 0, 0, 0, NULL, NULL, 0); + *body = html_timeline(NULL, tl, 0, 0, 0, 0, + L("Recent posts by users in this instance"), NULL, 0); } else *body = greeting_html(); diff --git a/snac.h b/snac.h index ab8fc7c..2a988f1 100644 --- a/snac.h +++ b/snac.h @@ -318,7 +318,7 @@ xs_str *encode_html(const char *str); xs_str *html_timeline(snac *user, const xs_list *list, int read_only, int skip, int show, int show_more, - char *tag, char *page, int utl); + char *title, char *page, int utl); int html_get_handler(const xs_dict *req, const char *q_path, char **body, int *b_size, char **ctype, xs_str **etag); From 3355d5559dc03f01382282409f33ca6908e495fe Mon Sep 17 00:00:00 2001 From: default Date: Tue, 7 May 2024 20:51:24 +0200 Subject: [PATCH 4/8] New op #3 to list_maint() (get list name). --- data.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/data.c b/data.c index 5b4936b..4e1682c 100644 --- a/data.c +++ b/data.c @@ -1829,6 +1829,19 @@ xs_val *list_maint(snac *user, const char *list, int op) } } + break; + + case 3: /** get list name **/ + if (xs_is_hex(list)) { + FILE *f; + xs *fn = xs_fmt("%s/list/%s.id", user->basedir, list); + + if ((f = fopen(fn, "r")) != NULL) { + l = xs_strip_i(xs_readline(f)); + fclose(f); + } + } + break; } From d3cdbf170251db70121b2162513a6cfa2addd8c4 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 7 May 2024 20:51:43 +0200 Subject: [PATCH 5/8] Added a title to list timelines. --- html.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/html.c b/html.c index bd3179d..86cb2f5 100644 --- a/html.c +++ b/html.c @@ -2034,6 +2034,13 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_add(body, html_top_controls(user)); + if (user && title) { + xs_html_add(body, + xs_html_tag("h2", + xs_html_attr("class", "snac-header"), + xs_html_text(title))); + } + xs_html_add(body, xs_html_tag("a", xs_html_attr("name", "snac-posts"))); @@ -2666,9 +2673,11 @@ int html_get_handler(const xs_dict *req, const char *q_path, if (list != NULL) { xs *base = xs_fmt("/list/%s", lid); + xs *name = list_maint(&snac, lid, 3); + xs *title = xs_fmt(L("Showing timeline for list %s"), name); *body = html_timeline(&snac, list, 0, skip, show, - xs_list_len(next), NULL, base, 1); + xs_list_len(next), title, base, 1); *b_size = strlen(*body); status = 200; } From 2322de4900312653d04ec19e8ee2850e0f5d4ac4 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 7 May 2024 20:53:58 +0200 Subject: [PATCH 6/8] Added a title to the instance timeline. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index 86cb2f5..5521a9f 100644 --- a/html.c +++ b/html.c @@ -2653,7 +2653,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *next = timeline_instance_list(skip + show, 1); *body = html_timeline(&snac, list, 0, skip, show, - xs_list_len(next), NULL, "/instance", 0); + xs_list_len(next), L("Showing instance timeline"), "/instance", 0); *b_size = strlen(*body); status = 200; } From fa8b40192757a2022da1cc945e4d0c3c1dc014b2 Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 May 2024 04:15:36 +0200 Subject: [PATCH 7/8] More HTML simplification. --- html.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/html.c b/html.c index 5521a9f..27fc713 100644 --- a/html.c +++ b/html.c @@ -509,7 +509,7 @@ xs_html *html_instance_head(void) } -static xs_html *html_instance_body(char *title) +static xs_html *html_instance_body(void) { char *host = xs_dict_get(srv_config, "host"); char *sdesc = xs_dict_get(srv_config, "short_description"); @@ -560,13 +560,6 @@ static xs_html *html_instance_body(char *title) xs_html_text(handle))))); } - if (title != NULL) { - xs_html_add(body, - xs_html_tag("h2", - xs_html_attr("class", "snac-header"), - xs_html_text(title))); - } - return body; } @@ -2023,7 +2016,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, } else { head = html_instance_head(); - body = html_instance_body(title); + body = html_instance_body(); } xs_html *html = xs_html_tag("html", @@ -2034,7 +2027,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_add(body, html_top_controls(user)); - if (user && title) { + if (title) { xs_html_add(body, xs_html_tag("h2", xs_html_attr("class", "snac-header"), From d27a60dfe7a440ad76540b826d9105a82711f70b Mon Sep 17 00:00:00 2001 From: khm Date: Tue, 7 May 2024 23:28:51 -0700 Subject: [PATCH 8/8] allow unboosting your own posts --- html.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/html.c b/html.c index ee5c2cd..018cdc8 100644 --- a/html.c +++ b/html.c @@ -1265,8 +1265,8 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const } if (is_msg_public(msg)) { - if (strcmp(actor, snac->actor) == 0 || xs_list_in(boosts, snac->md5) == -1) { - /* not already boosted or us; add button */ + if (xs_list_in(boosts, snac->md5) == -1) { + /* not already boosted; add button */ xs_html_add(form, html_button("boost", L("Boost"), L("Announce this post to your followers"))); }