From 6af6194f55e751157f74a891738697e635c9c64e Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 Jan 2025 16:51:30 +0100 Subject: Show hashtags that are not already linked from the post content. --- html.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index e8803ab..d1844c2 100644 --- a/html.c +++ b/html.c @@ -2189,6 +2189,39 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, au_tag); } + /* show all hashtags that has not been shown previously in the content */ + const xs_list *tags = xs_dict_get(msg, "tag"); + if (xs_type(tags) == XSTYPE_LIST && xs_list_len(tags)) { + const char *content = xs_dict_get(msg, "content"); + const xs_dict *tag; + + xs_html *add_hashtags = xs_html_tag("ul", + xs_html_attr("class", "snac-more-hashtags")); + + xs_list_foreach(tags, tag) { + const char *type = xs_dict_get(tag, "type"); + + if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Hashtag") == 0) { + const char *href = xs_dict_get(tag, "href"); + + if (xs_type(href) == XSTYPE_STRING && xs_str_in(content, href) == -1) { + /* not in the content: add here */ + const char *name = xs_dict_get(tag, "name"); + + xs_html_add(add_hashtags, + xs_html_tag("li", + xs_html_tag("a", + xs_html_attr("href", href), + xs_html_text(name), + xs_html_text(" ")))); + } + } + } + + xs_html_add(snac_content_wrap, + add_hashtags); + } + /** controls **/ if (!read_only && user) { -- cgit v1.2.3 From 932227bbac7fe740bff1e38bf92b58edef19e32f Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 Jan 2025 16:59:14 +0100 Subject: Bumped copyright year. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index d1844c2..5a62d16 100644 --- a/html.c +++ b/html.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ #include "xs.h" #include "xs_io.h" -- cgit v1.2.3 From b51085831e40dbcbd5ff80e033c1b59702cbc920 Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 Jan 2025 17:20:53 +0100 Subject: Also check for the lowecase URL of the hashtags. --- html.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 5a62d16..bade62a 100644 --- a/html.c +++ b/html.c @@ -12,6 +12,7 @@ #include "xs_match.h" #include "xs_html.h" #include "xs_curl.h" +#include "xs_unicode.h" #include "snac.h" @@ -2203,8 +2204,11 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Hashtag") == 0) { const char *href = xs_dict_get(tag, "href"); + xs *lc_href = xs_utf8_to_lower(href); - if (xs_type(href) == XSTYPE_STRING && xs_str_in(content, href) == -1) { + if (xs_type(href) == XSTYPE_STRING && + xs_str_in(content, href) == -1 && + xs_str_in(content, lc_href) == -1) { /* not in the content: add here */ const char *name = xs_dict_get(tag, "name"); -- cgit v1.2.3 From a6dce9953889156b485405c7de2bd954587b2ddc Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 Jan 2025 17:24:41 +0100 Subject: Do a lower case search of hashtags in the content. --- html.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index bade62a..7c46c76 100644 --- a/html.c +++ b/html.c @@ -2193,7 +2193,8 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, /* show all hashtags that has not been shown previously in the content */ const xs_list *tags = xs_dict_get(msg, "tag"); if (xs_type(tags) == XSTYPE_LIST && xs_list_len(tags)) { - const char *content = xs_dict_get(msg, "content"); + const char *o_content = xs_dict_get(msg, "content"); + xs *content = xs_utf8_to_lower(o_content); const xs_dict *tag; xs_html *add_hashtags = xs_html_tag("ul", @@ -2203,12 +2204,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, const char *type = xs_dict_get(tag, "type"); if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Hashtag") == 0) { - const char *href = xs_dict_get(tag, "href"); - xs *lc_href = xs_utf8_to_lower(href); + const char *o_href = xs_dict_get(tag, "href"); + xs *href = xs_utf8_to_lower(o_href); - if (xs_type(href) == XSTYPE_STRING && - xs_str_in(content, href) == -1 && - xs_str_in(content, lc_href) == -1) { + if (xs_type(href) == XSTYPE_STRING && xs_str_in(content, href) == -1) { /* not in the content: add here */ const char *name = xs_dict_get(tag, "name"); -- cgit v1.2.3 From 935a0a5a7d9f50427fe15b0a8b947d51db177cdc Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 Jan 2025 19:56:15 +0100 Subject: Fixed crash on NULL hashtag href. --- html.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 7c46c76..294faa3 100644 --- a/html.c +++ b/html.c @@ -2205,18 +2205,21 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Hashtag") == 0) { const char *o_href = xs_dict_get(tag, "href"); - xs *href = xs_utf8_to_lower(o_href); - if (xs_type(href) == XSTYPE_STRING && xs_str_in(content, href) == -1) { - /* not in the content: add here */ - const char *name = xs_dict_get(tag, "name"); + if (xs_type(o_href) == XSTYPE_STRING) { + xs *href = xs_utf8_to_lower(o_href); - xs_html_add(add_hashtags, - xs_html_tag("li", - xs_html_tag("a", - xs_html_attr("href", href), - xs_html_text(name), - xs_html_text(" ")))); + if (xs_type(href) == XSTYPE_STRING && xs_str_in(content, href) == -1) { + /* not in the content: add here */ + const char *name = xs_dict_get(tag, "name"); + + xs_html_add(add_hashtags, + xs_html_tag("li", + xs_html_tag("a", + xs_html_attr("href", href), + xs_html_text(name), + xs_html_text(" ")))); + } } } } -- cgit v1.2.3 From 74cd356be8ba270c76202c7c55b5b07ab4bfd22c Mon Sep 17 00:00:00 2001 From: default Date: Wed, 8 Jan 2025 20:06:17 +0100 Subject: Deleted useless check. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 294faa3..7e3d281 100644 --- a/html.c +++ b/html.c @@ -2209,7 +2209,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if (xs_type(o_href) == XSTYPE_STRING) { xs *href = xs_utf8_to_lower(o_href); - if (xs_type(href) == XSTYPE_STRING && xs_str_in(content, href) == -1) { + if (xs_str_in(content, href) == -1) { /* not in the content: add here */ const char *name = xs_dict_get(tag, "name"); -- cgit v1.2.3 From ed729878a6d411038b6dabfc81980c3a193efb97 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 08:00:18 +0100 Subject: New user settings latitude and longitude. --- html.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index 7e3d281..559d139 100644 --- a/html.c +++ b/html.c @@ -1101,6 +1101,8 @@ xs_html *html_top_controls(snac *snac) const xs_val *coll_thrds = xs_dict_get(snac->config, "collapse_threads"); const xs_val *pending = xs_dict_get(snac->config, "approve_followers"); const xs_val *show_foll = xs_dict_get(snac->config, "show_contact_metrics"); + const char *latitude = xs_dict_get_def(snac->config, "latitude", ""); + const char *longitude = xs_dict_get_def(snac->config, "longitude", ""); xs *metadata = NULL; const xs_dict *md = xs_dict_get(snac->config, "metadata"); @@ -1290,6 +1292,20 @@ xs_html *html_top_controls(snac *snac) xs_html_tag("label", xs_html_attr("for", "show_contact_metrics"), xs_html_text(L("Publish follower and following metrics")))), + xs_html_tag("p", + xs_html_text(L("Home location:")), + xs_html_sctag("br", NULL), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", "latitude"), + xs_html_attr("value", latitude), + xs_html_attr("placeholder", "latitude")), + xs_html_text(" "), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", "longitude"), + xs_html_attr("value", longitude), + xs_html_attr("placeholder", "longitude"))), xs_html_tag("p", xs_html_text(L("Profile metadata (key=value pairs in each line):")), xs_html_sctag("br", NULL), @@ -4053,6 +4069,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, else snac.config = xs_dict_set(snac.config, "show_contact_metrics", xs_stock(XSTYPE_FALSE)); + snac.config = xs_dict_set(snac.config, "latitude", xs_dict_get_def(p_vars, "latitude", "")); + snac.config = xs_dict_set(snac.config, "longitude", xs_dict_get_def(p_vars, "longitude", "")); + if ((v = xs_dict_get(p_vars, "metadata")) != NULL) snac.config = xs_dict_set(snac.config, "metadata", v); -- cgit v1.2.3 From ea2eb3299dbb13699cffadb7be445ae87cae00bc Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 08:12:38 +0100 Subject: Show the location in the public page. --- html.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index 559d139..eb4ab1f 100644 --- a/html.c +++ b/html.c @@ -924,6 +924,7 @@ static xs_html *html_user_body(snac *user, int read_only) xs_html_raw("✔ "), xs_html_tag("a", xs_html_attr("rel", "me"), + xs_html_attr("target", "_blank"), xs_html_attr("href", v), xs_html_text(v))); } @@ -960,6 +961,23 @@ static xs_html *html_user_body(snac *user, int read_only) snac_metadata); } + const char *latitude = xs_dict_get_def(user->config, "latitude", ""); + const char *longitude = xs_dict_get_def(user->config, "longitude", ""); + + if (*latitude && *longitude) { + xs *label = xs_fmt(L("%s,%s"), latitude, longitude); + xs *url = xs_fmt(L("https://openstreetmap.org/search?query=%s,%s"), + latitude, longitude); + + xs_html_add(top_user, + xs_html_tag("p", + xs_html_text(L("Location: ")), + xs_html_tag("a", + xs_html_attr("href", url), + xs_html_attr("target", "_blank"), + xs_html_text(label)))); + } + if (xs_is_true(xs_dict_get(user->config, "show_contact_metrics"))) { xs *fwers = follower_list(user); xs *fwing = following_list(user); -- cgit v1.2.3 From 538f6970f86323dca734436861fe19193fae87e5 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 08:29:57 +0100 Subject: If a location is defined, user actors include a 'Place' object. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index eb4ab1f..3498b93 100644 --- a/html.c +++ b/html.c @@ -1311,7 +1311,7 @@ xs_html *html_top_controls(snac *snac) xs_html_attr("for", "show_contact_metrics"), xs_html_text(L("Publish follower and following metrics")))), xs_html_tag("p", - xs_html_text(L("Home location:")), + xs_html_text(L("Current location:")), xs_html_sctag("br", NULL), xs_html_sctag("input", xs_html_attr("type", "text"), -- cgit v1.2.3 From 9fec8fc5ca8b3a45510183b839f15375c2a66695 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 08:47:01 +0100 Subject: Fixed crash. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 3498b93..5ad55a3 100644 --- a/html.c +++ b/html.c @@ -2227,7 +2227,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, /* show all hashtags that has not been shown previously in the content */ const xs_list *tags = xs_dict_get(msg, "tag"); if (xs_type(tags) == XSTYPE_LIST && xs_list_len(tags)) { - const char *o_content = xs_dict_get(msg, "content"); + const char *o_content = xs_dict_get_def(msg, "content", ""); xs *content = xs_utf8_to_lower(o_content); const xs_dict *tag; -- cgit v1.2.3 From 6a5ea9783aac7947fed8b40cc78f67e11bb9a99c Mon Sep 17 00:00:00 2001 From: default Date: Fri, 10 Jan 2025 09:52:20 +0100 Subject: If a post has a location, show it. --- html.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index 5ad55a3..fbaa5d1 100644 --- a/html.c +++ b/html.c @@ -2224,6 +2224,43 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, au_tag); } + /* does it have a location? */ + const xs_dict *location = xs_dict_get(msg, "location"); + if (xs_type(location) == XSTYPE_DICT) { + const xs_number *latitude = xs_dict_get(location, "latitude"); + const xs_number *longitude = xs_dict_get(location, "longitude"); + const char *name = xs_dict_get(location, "name"); + const char *address = xs_dict_get(location, "address"); + xs *label_list = xs_list_new(); + + if (xs_type(name) == XSTYPE_STRING) + label_list = xs_list_append(label_list, name); + if (xs_type(address) == XSTYPE_STRING) + label_list = xs_list_append(label_list, address); + + if (xs_list_len(label_list)) { + xs *label = xs_join(label_list, ", "); + + if (!xs_is_null(latitude) && !xs_is_null(longitude)) { + xs *url = xs_fmt("https://openstreetmap.org/search/?query=%s,%s", + xs_number_str(latitude), xs_number_str(longitude)); + + xs_html_add(snac_content_wrap, + xs_html_tag("p", + xs_html_text(L("Location: ")), + xs_html_tag("a", + xs_html_attr("href", url), + xs_html_attr("target", "_blank"), + xs_html_text(label)))); + } + else + xs_html_add(snac_content_wrap, + xs_html_tag("p", + xs_html_text(L("Location: ")), + xs_html_text(label))); + } + } + /* show all hashtags that has not been shown previously in the content */ const xs_list *tags = xs_dict_get(msg, "tag"); if (xs_type(tags) == XSTYPE_LIST && xs_list_len(tags)) { -- cgit v1.2.3 From 6154ce75826ccb4ade18a45b838d159cd26d81f8 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 12 Jan 2025 11:57:30 +0100 Subject: If an Event has an URL, use it. --- html.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index fbaa5d1..1e890e3 100644 --- a/html.c +++ b/html.c @@ -2239,8 +2239,19 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, label_list = xs_list_append(label_list, address); if (xs_list_len(label_list)) { + const char *url = xs_dict_get(location, "url"); xs *label = xs_join(label_list, ", "); + if (xs_type(url) == XSTYPE_STRING) { + xs_html_add(snac_content_wrap, + xs_html_tag("p", + xs_html_text(L("Location: ")), + xs_html_tag("a", + xs_html_attr("href", url), + xs_html_attr("target", "_blank"), + xs_html_text(label)))); + } + else if (!xs_is_null(latitude) && !xs_is_null(longitude)) { xs *url = xs_fmt("https://openstreetmap.org/search/?query=%s,%s", xs_number_str(latitude), xs_number_str(longitude)); -- cgit v1.2.3 From 6d0b0cdaab829c8c0d98b0f3cdc5d3526f1c5662 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 12 Jan 2025 14:31:45 +0100 Subject: Show event start / end times. This code is a ugly as fuck. --- html.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index 1e890e3..6a5aa10 100644 --- a/html.c +++ b/html.c @@ -2272,6 +2272,49 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, } } + if (strcmp(type, "Event") == 0) { /** Event start and end times **/ + const char *s_time = xs_dict_get(msg, "startTime"); + + if (xs_type(s_time) == XSTYPE_STRING) { + const char *e_time = xs_dict_get(msg, "endTime"); + const char *tz = xs_dict_get(msg, "timezone"); + + xs *s = xs_replace_i(xs_dup(s_time), "T", " "); + xs *e = NULL; + + if (xs_type(e_time) == XSTYPE_STRING) + e = xs_replace_i(xs_dup(e_time), "T", " "); + + /* if the event has a timezone, crop the offsets */ + if (xs_type(tz) == XSTYPE_STRING) { + s = xs_crop_i(s, 0, 19); + + if (e) + e = xs_crop_i(e, 0, 19); + } + else + tz = ""; + + /* if start and end share the same day, crop it from the end */ + if (e && memcmp(s, e, 11) == 0) + e = xs_crop_i(e, 11, strlen(e)); + + if (e) + s = xs_str_cat(s, " / ", e); + + if (*tz) + s = xs_str_cat(s, " (", tz, ")"); + + /* replace ugly decimals */ + s = xs_replace_i(s, ".000", ""); + + xs_html_add(snac_content_wrap, + xs_html_tag("p", + xs_html_text(L("Time: ")), + xs_html_text(s))); + } + } + /* show all hashtags that has not been shown previously in the content */ const xs_list *tags = xs_dict_get(msg, "tag"); if (xs_type(tags) == XSTYPE_LIST && xs_list_len(tags)) { -- cgit v1.2.3 From 5aaa6192ef08de7ab6c63e85708a1c825e9ff5f1 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 12 Jan 2025 14:59:28 +0100 Subject: Better dangling hashtag checking. --- html.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 6a5aa10..322bafa 100644 --- a/html.c +++ b/html.c @@ -2317,8 +2317,9 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, /* show all hashtags that has not been shown previously in the content */ const xs_list *tags = xs_dict_get(msg, "tag"); - if (xs_type(tags) == XSTYPE_LIST && xs_list_len(tags)) { - const char *o_content = xs_dict_get_def(msg, "content", ""); + const char *o_content = xs_dict_get_def(msg, "content", ""); + + if (xs_is_string(o_content) && xs_is_list(tags) && xs_list_len(tags)) { xs *content = xs_utf8_to_lower(o_content); const xs_dict *tag; @@ -2328,16 +2329,15 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs_list_foreach(tags, tag) { const char *type = xs_dict_get(tag, "type"); - if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Hashtag") == 0) { + if (xs_is_string(type) && strcmp(type, "Hashtag") == 0) { const char *o_href = xs_dict_get(tag, "href"); + const char *name = xs_dict_get(tag, "name"); - if (xs_type(o_href) == XSTYPE_STRING) { + if (xs_is_string(o_href) && xs_is_string(name)) { xs *href = xs_utf8_to_lower(o_href); - if (xs_str_in(content, href) == -1) { + if (xs_str_in(content, href) == -1 && xs_str_in(content, name) == -1) { /* not in the content: add here */ - const char *name = xs_dict_get(tag, "name"); - xs_html_add(add_hashtags, xs_html_tag("li", xs_html_tag("a", -- cgit v1.2.3 From ddc8781b3a93d77836b61f3efa884b3c23a1fd35 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 12 Jan 2025 16:21:20 +0100 Subject: Minor improvements to start / end event time showing. --- html.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 322bafa..c55937d 100644 --- a/html.c +++ b/html.c @@ -2275,18 +2275,18 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if (strcmp(type, "Event") == 0) { /** Event start and end times **/ const char *s_time = xs_dict_get(msg, "startTime"); - if (xs_type(s_time) == XSTYPE_STRING) { + if (xs_is_string(s_time) && strlen(s_time) > 20) { const char *e_time = xs_dict_get(msg, "endTime"); const char *tz = xs_dict_get(msg, "timezone"); xs *s = xs_replace_i(xs_dup(s_time), "T", " "); xs *e = NULL; - if (xs_type(e_time) == XSTYPE_STRING) + if (xs_is_string(e_time) && strlen(e_time) > 20) e = xs_replace_i(xs_dup(e_time), "T", " "); /* if the event has a timezone, crop the offsets */ - if (xs_type(tz) == XSTYPE_STRING) { + if (xs_is_string(tz)) { s = xs_crop_i(s, 0, 19); if (e) @@ -2297,7 +2297,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, /* if start and end share the same day, crop it from the end */ if (e && memcmp(s, e, 11) == 0) - e = xs_crop_i(e, 11, strlen(e)); + e = xs_crop_i(e, 11, 0); if (e) s = xs_str_cat(s, " / ", e); -- cgit v1.2.3 From b993e26346f885586ff0533a3b309ed7d1e910cf Mon Sep 17 00:00:00 2001 From: default Date: Thu, 16 Jan 2025 14:20:07 +0100 Subject: Implemented Mastodon-like /authorize_interaction. --- html.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index c55937d..aad2f31 100644 --- a/html.c +++ b/html.c @@ -3124,6 +3124,21 @@ int html_get_handler(const xs_dict *req, const char *q_path, else return HTTP_STATUS_NOT_FOUND; } + else + if (strcmp(v, "auth-int-bridge") == 0) { + const char *login = xs_dict_get(q_vars, "login"); + const char *id = xs_dict_get(q_vars, "id"); + const char *action = xs_dict_get(q_vars, "action"); + + if (xs_is_string(login) && xs_is_string(id) && xs_is_string(action)) { + *body = xs_fmt("%s/%s/authorize_interaction?action=%s&id=%s", + srv_baseurl, login, action, id); + + return HTTP_STATUS_SEE_OTHER; + } + else + return HTTP_STATUS_NOT_FOUND; + } uid = xs_dup(v); @@ -3695,6 +3710,52 @@ int html_get_handler(const xs_dict *req, const char *q_path, status = HTTP_STATUS_SEE_OTHER; } } + else + if (strcmp(p_path, "authorize_interaction") == 0) { /** follow, like or boost from Mastodon **/ + if (!login(&snac, req)) { + *body = xs_dup(uid); + status = HTTP_STATUS_UNAUTHORIZED; + } + else { + status = HTTP_STATUS_NOT_FOUND; + + const char *id = xs_dict_get(q_vars, "id"); + const char *action = xs_dict_get(q_vars, "action"); + + if (xs_is_string(id) && xs_is_string(action)) { + if (strcmp(action, "Follow") == 0) { + xs *msg = msg_follow(&snac, id); + + if (msg != NULL) { + const char *actor = xs_dict_get(msg, "object"); + + following_add(&snac, actor, msg); + + enqueue_output_by_actor(&snac, msg, actor, 0); + + status = HTTP_STATUS_SEE_OTHER; + } + } + else + if (xs_match(action, "Like|Boost|Announce")) { + /* bring the post */ + xs *msg = msg_admiration(&snac, id, *action == 'L' ? "Like" : "Announce"); + + if (msg != NULL) { + enqueue_message(&snac, msg); + timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, *action == 'L' ? 1 : 0); + + status = HTTP_STATUS_SEE_OTHER; + } + } + } + + if (status == HTTP_STATUS_SEE_OTHER) { + *body = xs_fmt("%s/admin", snac.actor); + *b_size = strlen(*body); + } + } + } else status = HTTP_STATUS_NOT_FOUND; -- cgit v1.2.3 From 2ab9db4175cde75889bb43d0805d96759d6215bc Mon Sep 17 00:00:00 2001 From: default Date: Sun, 19 Jan 2025 16:38:13 +0100 Subject: Added controls for the followed hashtags. --- html.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index aad2f31..3ad330d 100644 --- a/html.c +++ b/html.c @@ -1355,6 +1355,38 @@ xs_html *html_top_controls(snac *snac) xs_html_attr("class", "button"), xs_html_attr("value", L("Update user info"))))))); + xs *followed_hashtags_action = xs_fmt("%s/admin/followed-hashtags", snac->actor); + xs *followed_hashtags = xs_join(xs_dict_get_def(snac->config, + "followed_hashtags", xs_stock(XSTYPE_LIST)), "\n"); + + xs_html_add(top_controls, + xs_html_tag("details", + xs_html_tag("summary", + xs_html_text(L("Followed hashtags..."))), + xs_html_tag("p", + xs_html_text(L("One hashtag per line"))), + xs_html_tag("div", + xs_html_attr("class", "snac-followed-hashtags"), + xs_html_tag("form", + xs_html_attr("autocomplete", "off"), + xs_html_attr("method", "post"), + xs_html_attr("action", followed_hashtags_action), + xs_html_attr("enctype", "multipart/form-data"), + + xs_html_tag("textarea", + xs_html_attr("name", "hashtags"), + xs_html_attr("cols", "40"), + xs_html_attr("rows", "4"), + xs_html_attr("placeholder", "#cats\n#windowfriday\n#classicalmusic"), + xs_html_text(followed_hashtags)), + + xs_html_tag("br", NULL), + + xs_html_sctag("input", + xs_html_attr("type", "submit"), + xs_html_attr("class", "button"), + xs_html_attr("value", L("Update hashtags"))))))); + return top_controls; } -- cgit v1.2.3 From ba5d978bf1385647d0f696f4d4cb3e3dd1cc544d Mon Sep 17 00:00:00 2001 From: default Date: Sun, 19 Jan 2025 17:02:43 +0100 Subject: Update user config from admin/followed-hashtags. --- html.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 3ad330d..09dd202 100644 --- a/html.c +++ b/html.c @@ -1374,7 +1374,7 @@ xs_html *html_top_controls(snac *snac) xs_html_attr("enctype", "multipart/form-data"), xs_html_tag("textarea", - xs_html_attr("name", "hashtags"), + xs_html_attr("name", "followed_hashtags"), xs_html_attr("cols", "40"), xs_html_attr("rows", "4"), xs_html_attr("placeholder", "#cats\n#windowfriday\n#classicalmusic"), @@ -4390,6 +4390,35 @@ int html_post_handler(const xs_dict *req, const char *q_path, status = HTTP_STATUS_SEE_OTHER; } + else + if (p_path && strcmp(p_path, "admin/followed-hashtags") == 0) { /** **/ + const char *followed_hashtags = xs_dict_get(p_vars, "followed_hashtags"); + + if (xs_is_string(followed_hashtags)) { + xs *new_hashtags = xs_list_new(); + xs *l = xs_split(followed_hashtags, "\n"); + const char *v; + + xs_list_foreach(l, v) { + xs *s1 = xs_strip_i(xs_dup(v)); + s1 = xs_replace_i(s1, " ", ""); + + if (*s1 == '\0') + continue; + + xs *s2 = xs_utf8_to_lower(s1); + if (*s2 != '#') + s2 = xs_str_prepend_i(s2, "#"); + + new_hashtags = xs_list_append(new_hashtags, s2); + } + + snac.config = xs_dict_set(snac.config, "followed_hashtags", new_hashtags); + user_persist(&snac, 0); + } + + status = HTTP_STATUS_SEE_OTHER; + } if (status == HTTP_STATUS_SEE_OTHER) { const char *redir = xs_dict_get(p_vars, "redir"); -- cgit v1.2.3 From b4add138e10410fc4aeedea50a6de7ebead2f710 Mon Sep 17 00:00:00 2001 From: default Date: Mon, 20 Jan 2025 09:17:57 +0100 Subject: Show the post language under the date 'title'. --- html.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 09dd202..3ece3b2 100644 --- a/html.c +++ b/html.c @@ -114,7 +114,8 @@ xs_str *actor_name(xs_dict *actor, const char *proxy) xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, - const char *udate, const char *url, int priv, int in_people, const char *proxy) + const char *udate, const char *url, int priv, + int in_people, const char *proxy, const char *lang) { xs_html *actor_icon = xs_html_tag("p", NULL); @@ -220,6 +221,9 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, date_title = xs_str_cat(date_title, " / ", udate); } + if (xs_is_string(lang)) + date_title = xs_str_cat(date_title, " (", lang, ")"); + xs_html_add(actor_icon, xs_html_text(" "), xs_html_tag("time", @@ -266,6 +270,7 @@ xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, con const char *date = NULL; const char *udate = NULL; const char *url = NULL; + const char *lang = NULL; int priv = 0; const char *type = xs_dict_get(msg, "type"); @@ -277,7 +282,17 @@ xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, con date = xs_dict_get(msg, "published"); udate = xs_dict_get(msg, "updated"); - actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0, proxy); + lang = xs_dict_get(msg, "contentMap"); + if (xs_is_dict(lang)) { + const char *v; + int c = 0; + + xs_dict_next(lang, &lang, &v, &c); + } + else + lang = NULL; + + actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0, proxy, lang); } return actor_icon; @@ -2769,7 +2784,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t, cons xs_html_tag("div", xs_html_attr("class", "snac-post-header"), html_actor_icon(snac, actor, xs_dict_get(actor, "published"), - NULL, NULL, 0, 1, proxy))); + NULL, NULL, 0, 1, proxy, NULL))); /* content (user bio) */ const char *c = xs_dict_get(actor, "summary"); @@ -3022,7 +3037,7 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_add(entry, xs_html_tag("div", xs_html_attr("class", "snac-post"), - html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0, proxy))); + html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0, proxy, NULL))); } else if (strcmp(type, "Move") == 0) { @@ -3036,7 +3051,7 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_add(entry, xs_html_tag("div", xs_html_attr("class", "snac-post"), - html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0, proxy))); + html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0, proxy, NULL))); } } } -- cgit v1.2.3 From 9e283af12cf8a7e99c9ba13165135e3eff8aba01 Mon Sep 17 00:00:00 2001 From: default Date: Mon, 20 Jan 2025 17:00:59 +0100 Subject: Minor HTML tweak. --- html.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 3ece3b2..2a02d18 100644 --- a/html.c +++ b/html.c @@ -1368,7 +1368,9 @@ xs_html *html_top_controls(snac *snac) xs_html_sctag("input", xs_html_attr("type", "submit"), xs_html_attr("class", "button"), - xs_html_attr("value", L("Update user info"))))))); + xs_html_attr("value", L("Update user info"))), + + xs_html_tag("p", NULL))))); xs *followed_hashtags_action = xs_fmt("%s/admin/followed-hashtags", snac->actor); xs *followed_hashtags = xs_join(xs_dict_get_def(snac->config, -- cgit v1.2.3 From 0cae9a520c7f3d72ecdabf1fac066f1da943605c Mon Sep 17 00:00:00 2001 From: default Date: Wed, 22 Jan 2025 15:23:37 +0100 Subject: Minor visual tweak. --- html.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 2a02d18..fcf2904 100644 --- a/html.c +++ b/html.c @@ -1855,22 +1855,20 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, } } } - else + if (strcmp(type, "Note") == 0) { - if (level == 0) { - /* is the parent not here? */ - const char *parent = get_in_reply_to(msg); + /* is the parent not here? */ + const char *parent = get_in_reply_to(msg); - if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) { - xs_html_add(post_header, - xs_html_tag("div", - xs_html_attr("class", "snac-origin"), - xs_html_text(L("in reply to")), - xs_html_text(" "), - xs_html_tag("a", - xs_html_attr("href", parent), - xs_html_text("»")))); - } + if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) { + xs_html_add(post_header, + xs_html_tag("div", + xs_html_attr("class", "snac-origin"), + xs_html_text(L("in reply to")), + xs_html_text(" "), + xs_html_tag("a", + xs_html_attr("href", parent), + xs_html_text("»")))); } } -- cgit v1.2.3 From 0f0e33f5f6f49b9b4055b24761559b11c80da45e Mon Sep 17 00:00:00 2001 From: default Date: Wed, 22 Jan 2025 15:47:21 +0100 Subject: Fixed bug in 'in reply to' checking. --- html.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index fcf2904..a15bd06 100644 --- a/html.c +++ b/html.c @@ -1856,19 +1856,23 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, } } - if (strcmp(type, "Note") == 0) { + if (user && strcmp(type, "Note") == 0) { /* is the parent not here? */ const char *parent = get_in_reply_to(msg); - if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) { - xs_html_add(post_header, - xs_html_tag("div", - xs_html_attr("class", "snac-origin"), - xs_html_text(L("in reply to")), - xs_html_text(" "), - xs_html_tag("a", - xs_html_attr("href", parent), - xs_html_text("»")))); + if (!xs_is_null(parent) && *parent) { + xs *md5 = xs_md5_hex(parent, strlen(parent)); + + if (!timeline_here(user, md5)) { + xs_html_add(post_header, + xs_html_tag("div", + xs_html_attr("class", "snac-origin"), + xs_html_text(L("in reply to")), + xs_html_text(" "), + xs_html_tag("a", + xs_html_attr("href", parent), + xs_html_text("»")))); + } } } -- cgit v1.2.3 From 0394f835e45975b9a82b0b009de2471e55a6cb7a Mon Sep 17 00:00:00 2001 From: default Date: Thu, 23 Jan 2025 20:09:22 +0100 Subject: Added some code to supress repeated notifications. --- html.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index a15bd06..d325063 100644 --- a/html.c +++ b/html.c @@ -2967,9 +2967,12 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_attr("class", "snac-posts")); xs_html_add(body, posts); - xs_list *p = n_list; + xs_set rep; + xs_set_init(&rep); + const xs_str *v; - while (xs_list_iter(&p, &v)) { + + xs_list_foreach(n_list, v) { xs *noti = notify_get(user, v); if (noti == NULL) @@ -2990,6 +2993,9 @@ xs_str *html_notifications(snac *user, int skip, int show) object_get(id, &obj); + if (xs_set_add(&rep, xs_dict_get(obj, "id")) != 1) + continue; + const char *actor_id = xs_dict_get(noti, "actor"); xs *actor = NULL; @@ -3103,6 +3109,8 @@ xs_str *html_notifications(snac *user, int skip, int show) } } + xs_set_free(&rep); + if (noti_new == NULL && noti_seen == NULL) xs_html_add(body, xs_html_tag("h2", -- cgit v1.2.3 From 95d32cbe7cfbb0321ac37b57ada23b6c268815e2 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 23 Jan 2025 20:17:38 +0100 Subject: Improved notify repetition code. --- html.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index d325063..3fd1e4b 100644 --- a/html.c +++ b/html.c @@ -2993,7 +2993,9 @@ xs_str *html_notifications(snac *user, int skip, int show) object_get(id, &obj); - if (xs_set_add(&rep, xs_dict_get(obj, "id")) != 1) + const char *msg_id = NULL; + + if (xs_is_dict(obj) && (msg_id = xs_dict_get(obj, "id")) && xs_set_add(&rep, msg_id) != 1) continue; const char *actor_id = xs_dict_get(noti, "actor"); -- cgit v1.2.3 From 5c303d539b48cdec5cc9cca77472faaa7c5c8d71 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 24 Jan 2025 14:54:55 +0100 Subject: Improved notification messages. --- html.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 3fd1e4b..e1f21bb 100644 --- a/html.c +++ b/html.c @@ -2967,8 +2967,8 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_attr("class", "snac-posts")); xs_html_add(body, posts); - xs_set rep; - xs_set_init(&rep); + /* dict to store previous notification labels */ + xs *admiration_labels = xs_dict_new(); const xs_str *v; @@ -2995,8 +2995,8 @@ xs_str *html_notifications(snac *user, int skip, int show) const char *msg_id = NULL; - if (xs_is_dict(obj) && (msg_id = xs_dict_get(obj, "id")) && xs_set_add(&rep, msg_id) != 1) - continue; + if (xs_is_dict(obj)) + msg_id = xs_dict_get(obj, "id"); const char *actor_id = xs_dict_get(noti, "actor"); xs *actor = NULL; @@ -3030,9 +3030,7 @@ xs_str *html_notifications(snac *user, int skip, int show) xs *s_date = xs_crop_i(xs_dup(date), 0, 10); - xs_html *entry = xs_html_tag("div", - xs_html_attr("class", "snac-post-with-desc"), - xs_html_tag("p", + xs_html *this_html_label = xs_html_container( xs_html_tag("b", xs_html_text(label), xs_html_text(" by "), @@ -3043,7 +3041,37 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_tag("time", xs_html_attr("class", "dt-published snac-pubdate"), xs_html_attr("title", date), - xs_html_text(s_date)))); + xs_html_text(s_date))); + + xs_html *html_label = NULL; + + if (xs_is_string(msg_id)) { + const xs_val *prev_label = xs_dict_get(admiration_labels, msg_id); + + if (xs_type(prev_label) == XSTYPE_DATA) { + /* there is a previous list of admiration labels! */ + xs_data_get(&html_label, prev_label); + + xs_html_add(html_label, + xs_html_sctag("br", NULL), + this_html_label); + + continue; + } + } + + xs_html *entry = NULL; + + html_label = xs_html_tag("p", + this_html_label); + + /* store in the admiration labels dict */ + xs *pl = xs_data_new(&html_label, sizeof(html_label)); + admiration_labels = xs_dict_set(admiration_labels, msg_id, pl); + + entry = xs_html_tag("div", + xs_html_attr("class", "snac-post-with-desc"), + html_label); if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0 || strcmp(type, "Block") == 0) { xs_html_add(entry, @@ -3111,8 +3139,6 @@ xs_str *html_notifications(snac *user, int skip, int show) } } - xs_set_free(&rep); - if (noti_new == NULL && noti_seen == NULL) xs_html_add(body, xs_html_tag("h2", -- cgit v1.2.3 From 896a36837c8da070d85abe92d62d12c4009fca1c Mon Sep 17 00:00:00 2001 From: default Date: Sat, 25 Jan 2025 21:45:14 +0100 Subject: Another tweak to fix repeated notifications. --- html.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index e1f21bb..31d8d97 100644 --- a/html.c +++ b/html.c @@ -2967,6 +2967,9 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_attr("class", "snac-posts")); xs_html_add(body, posts); + xs_set rep; + xs_set_init(&rep); + /* dict to store previous notification labels */ xs *admiration_labels = xs_dict_new(); @@ -2983,6 +2986,7 @@ xs_str *html_notifications(snac *user, int skip, int show) const char *utype = xs_dict_get(noti, "utype"); const char *id = xs_dict_get(noti, "objid"); const char *date = xs_dict_get(noti, "date"); + const char *id2 = xs_dict_get_path(noti, "msg.id"); xs *wrk = NULL; if (xs_is_null(id)) @@ -2991,6 +2995,9 @@ xs_str *html_notifications(snac *user, int skip, int show) if (is_hidden(user, id)) continue; + if (xs_is_string(id2) && xs_set_add(&rep, id2) != 1) + continue; + object_get(id, &obj); const char *msg_id = NULL; @@ -3158,6 +3165,8 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_text(L("More..."))))); } + xs_set_free(&rep); + xs_html_add(body, html_footer()); -- cgit v1.2.3 From 5d267968cb0d2670f8a4bd7587e505f812dfa3bc Mon Sep 17 00:00:00 2001 From: default Date: Sat, 25 Jan 2025 23:13:59 +0100 Subject: Fixed crash in the notification area after deleting a post. --- html.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 31d8d97..3b63cfc 100644 --- a/html.c +++ b/html.c @@ -3074,7 +3074,9 @@ xs_str *html_notifications(snac *user, int skip, int show) /* store in the admiration labels dict */ xs *pl = xs_data_new(&html_label, sizeof(html_label)); - admiration_labels = xs_dict_set(admiration_labels, msg_id, pl); + + if (xs_is_string(msg_id)) + admiration_labels = xs_dict_set(admiration_labels, msg_id, pl); entry = xs_html_tag("div", xs_html_attr("class", "snac-post-with-desc"), -- cgit v1.2.3