From f0764396388b3597caf5e2912da87f362e96785c Mon Sep 17 00:00:00 2001 From: default Date: Thu, 27 Feb 2025 16:15:50 +0100 Subject: Added web UI for the blocked hashtags. --- html.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index 6573630..92a81cc 100644 --- a/html.c +++ b/html.c @@ -1514,6 +1514,38 @@ xs_html *html_top_controls(snac *user) xs_html_attr("class", "button"), xs_html_attr("value", L("Update hashtags"))))))); + xs *blocked_hashtags_action = xs_fmt("%s/admin/blocked-hashtags", user->actor); + xs *blocked_hashtags = xs_join(xs_dict_get_def(user->config, + "blocked_hashtags", xs_stock(XSTYPE_LIST)), "\n"); + + xs_html_add(top_controls, + xs_html_tag("details", + xs_html_tag("summary", + xs_html_text(L("Blocked hashtags..."))), + xs_html_tag("p", + xs_html_text(L("One hashtag per line"))), + xs_html_tag("div", + xs_html_attr("class", "snac-blocked-hashtags"), + xs_html_tag("form", + xs_html_attr("autocomplete", "off"), + xs_html_attr("method", "post"), + xs_html_attr("action", blocked_hashtags_action), + xs_html_attr("enctype", "multipart/form-data"), + + xs_html_tag("textarea", + xs_html_attr("name", "blocked_hashtags"), + xs_html_attr("cols", "40"), + xs_html_attr("rows", "4"), + xs_html_attr("placeholder", "#cats\n#windowfriday\n#classicalmusic"), + xs_html_text(blocked_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; } @@ -4683,6 +4715,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/blocked-hashtags") == 0) { /** **/ + const char *hashtags = xs_dict_get(p_vars, "blocked_hashtags"); + + if (xs_is_string(hashtags)) { + xs *new_hashtags = xs_list_new(); + xs *l = xs_split(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, "blocked_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 From be3be930ad95dd58a32d8bae0a0bbe5bd5966219 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 28 Feb 2025 09:05:05 +0100 Subject: SVG support can be enabled by setting enable_svg to true in server.json. --- html.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 92a81cc..cb30eec 100644 --- a/html.c +++ b/html.c @@ -83,16 +83,20 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p const char *u = xs_dict_get(i, "url"); const char *mt = xs_dict_get(i, "mediaType"); - if (xs_is_string(u) && xs_is_string(mt) && strcmp(mt, "image/svg+xml")) { - xs *url = make_url(u, proxy, 0); + if (xs_is_string(u) && xs_is_string(mt)) { + if (strcmp(mt, "image/svg+xml") == 0 && !xs_is_true(xs_dict_get(srv_config, "enable_svg"))) + s = xs_replace_i(s, n, ""); + else { + xs *url = make_url(u, proxy, 0); - xs_html *img = xs_html_sctag("img", - xs_html_attr("loading", "lazy"), - xs_html_attr("src", url), - xs_html_attr("style", style)); + xs_html *img = xs_html_sctag("img", + xs_html_attr("loading", "lazy"), + xs_html_attr("src", url), + xs_html_attr("style", style)); - xs *s1 = xs_html_render(img); - s = xs_replace_i(s, n, s1); + xs *s1 = xs_html_render(img); + s = xs_replace_i(s, n, s1); + } } else s = xs_replace_i(s, n, ""); @@ -2313,8 +2317,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, continue; /* drop silently any attachment that may include JavaScript */ - if (strcmp(type, "image/svg+xml") == 0 || - strcmp(type, "text/html") == 0) + if (strcmp(type, "text/html") == 0) + continue; + + if (strcmp(type, "image/svg+xml") == 0 && !xs_is_true(xs_dict_get(srv_config, "enable_svg"))) continue; /* do this attachment include an icon? */ -- cgit From 8bd364bd49116b8b335272300ca05f25e1267df7 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 2 Mar 2025 06:04:52 +0100 Subject: msg_note() accepts a nullable post date. --- activitypub.c | 11 ++++++++--- html.c | 6 +++--- main.c | 2 +- mastoapi.c | 5 +++-- snac.h | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) (limited to 'html.c') diff --git a/activitypub.c b/activitypub.c index 5e1dd55..c9f700f 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1555,7 +1555,7 @@ xs_dict *msg_follow(snac *snac, const char *q) xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, const xs_str *in_reply_to, const xs_list *attach, - int scope, const char *lang_str) + int scope, const char *lang_str, const char *msg_date) /* creates a 'Note' message */ /* scope: 0, public; 1, private (mentioned only); 2, "quiet public"; 3, followers only */ { @@ -1569,7 +1569,12 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, xs *irt = NULL; xs *tag = xs_list_new(); xs *atls = xs_list_new(); - xs_dict *msg = msg_base(snac, "Note", id, NULL, "@now", NULL); + + /* discard non-parseable dates */ + if (!xs_is_string(msg_date) || xs_parse_iso_date(msg_date, 0) == 0) + msg_date = NULL; + + xs_dict *msg = msg_base(snac, "Note", id, NULL, xs_or(msg_date, "@now"), NULL); xs_list *p; const xs_val *v; @@ -1782,7 +1787,7 @@ xs_dict *msg_question(snac *user, const char *content, xs_list *attach, const xs_list *opts, int multiple, int end_secs) /* creates a Question message */ { - xs_dict *msg = msg_note(user, content, NULL, NULL, attach, 0, NULL); + xs_dict *msg = msg_note(user, content, NULL, NULL, attach, 0, NULL, NULL); int max = 8; xs_set seen; diff --git a/html.c b/html.c index cb30eec..8ffa2be 100644 --- a/html.c +++ b/html.c @@ -4020,7 +4020,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, const char *b64 = xs_dict_get(q_vars, "content"); int sz; xs *content = xs_base64_dec(b64, &sz); - xs *msg = msg_note(&snac, content, NULL, NULL, NULL, 0, NULL); + xs *msg = msg_note(&snac, content, NULL, NULL, NULL, 0, NULL, NULL); xs *c_msg = msg_create(&snac, msg); timeline_add(&snac, xs_dict_get(msg, "id"), msg); @@ -4220,7 +4220,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, enqueue_close_question(&snac, xs_dict_get(msg, "id"), end_secs); } else - msg = msg_note(&snac, content_2, to, in_reply_to, attach_list, priv, NULL); + msg = msg_note(&snac, content_2, to, in_reply_to, attach_list, priv, NULL, NULL); if (sensitive != NULL) { msg = xs_dict_set(msg, "sensitive", xs_stock(XSTYPE_TRUE)); @@ -4659,7 +4659,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, int c = 0; while (xs_list_next(ls, &v, &c)) { - xs *msg = msg_note(&snac, "", actor, irt, NULL, 1, NULL); + xs *msg = msg_note(&snac, "", actor, irt, NULL, 1, NULL, NULL); /* set the option */ msg = xs_dict_append(msg, "name", v); diff --git a/main.c b/main.c index a4ea961..3cd4524 100644 --- a/main.c +++ b/main.c @@ -710,7 +710,7 @@ int main(int argc, char *argv[]) if (strcmp(cmd, "note_unlisted") == 0) scope = 2; - msg = msg_note(&snac, content, NULL, NULL, attl, scope, getenv("LANG")); + msg = msg_note(&snac, content, NULL, NULL, attl, scope, getenv("LANG"), NULL); c_msg = msg_create(&snac, msg); diff --git a/mastoapi.c b/mastoapi.c index 797a4da..25b17e2 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -2628,6 +2628,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, const char *summary = xs_dict_get(args, "spoiler_text"); const char *media_ids = xs_dict_get(args, "media_ids"); const char *language = xs_dict_get(args, "language"); + const char *sched_date = xs_dict_get(args, "scheduled_at"); if (xs_is_null(media_ids)) media_ids = xs_dict_get(args, "media_ids[]"); @@ -2684,7 +2685,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, if (strcmp(visibility, "public") == 0) scope = 0; - xs *msg = msg_note(&snac, content, NULL, irt, attach_list, scope, language); + xs *msg = msg_note(&snac, content, NULL, irt, attach_list, scope, language, sched_date); if (!xs_is_null(summary) && *summary) { msg = xs_dict_set(msg, "sensitive", xs_stock(XSTYPE_TRUE)); @@ -3034,7 +3035,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, if (o) { const char *name = xs_dict_get(o, "name"); - xs *msg = msg_note(&snac, "", atto, (char *)id, NULL, 1, NULL); + xs *msg = msg_note(&snac, "", atto, (char *)id, NULL, 1, NULL, NULL); msg = xs_dict_append(msg, "name", name); xs *c_msg = msg_create(&snac, msg); diff --git a/snac.h b/snac.h index ac1abcd..ac30c44 100644 --- a/snac.h +++ b/snac.h @@ -329,7 +329,7 @@ xs_dict *msg_follow(snac *snac, const char *actor); xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, const xs_str *in_reply_to, const xs_list *attach, - int scope, const char *lang); + int scope, const char *lang_str, const char *msg_date); xs_dict *msg_undo(snac *snac, const xs_val *object); xs_dict *msg_delete(snac *snac, const char *id); -- cgit From 2ca1bfae79dcb613840a48ced14bd683b4235712 Mon Sep 17 00:00:00 2001 From: default Date: Sat, 8 Mar 2025 07:26:02 +0100 Subject: Fixed some stray translatable strings. --- html.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 8ffa2be..a90a51f 100644 --- a/html.c +++ b/html.c @@ -416,7 +416,7 @@ xs_html *html_note(snac *user, const char *summary, xs_html_sctag("input", xs_html_attr("type", "url"), xs_html_attr("name", "in_reply_to"), - xs_html_attr("placeholder", "Optional URL to reply to"))); + xs_html_attr("placeholder", L("Optional URL to reply to")))); xs_html_add(form, xs_html_tag("p", NULL), @@ -523,7 +523,7 @@ xs_html *html_note(snac *user, const char *summary, xs_html_attr("name", "poll_options"), xs_html_attr("rows", "4"), xs_html_attr("wrap", "virtual"), - xs_html_attr("placeholder", "Option 1...\nOption 2...\nOption 3...\n..."))), + xs_html_attr("placeholder", L("Option 1...\nOption 2...\nOption 3...\n...")))), xs_html_tag("select", xs_html_attr("name", "poll_multiple"), xs_html_tag("option", @@ -1342,13 +1342,13 @@ xs_html *html_top_controls(snac *user) xs_html_attr("type", "text"), xs_html_attr("name", "telegram_bot"), xs_html_attr("value", telegram_bot), - xs_html_attr("placeholder", "Bot API key")), + xs_html_attr("placeholder", L("Bot API key"))), xs_html_text(" "), xs_html_sctag("input", xs_html_attr("type", "text"), xs_html_attr("name", "telegram_chat_id"), xs_html_attr("value", telegram_chat_id), - xs_html_attr("placeholder", "Chat id"))), + xs_html_attr("placeholder", L("Chat id")))), xs_html_tag("p", xs_html_text(L("ntfy notifications (ntfy server and token):")), xs_html_sctag("br", NULL), @@ -1356,13 +1356,13 @@ xs_html *html_top_controls(snac *user) xs_html_attr("type", "text"), xs_html_attr("name", "ntfy_server"), xs_html_attr("value", ntfy_server), - xs_html_attr("placeholder", "ntfy server - full URL (example: https://ntfy.sh/YourTopic)")), + xs_html_attr("placeholder", L("ntfy server - full URL (example: https://ntfy.sh/YourTopic)"))), xs_html_text(" "), xs_html_sctag("input", xs_html_attr("type", "text"), xs_html_attr("name", "ntfy_token"), xs_html_attr("value", ntfy_token), - xs_html_attr("placeholder", "ntfy token - if needed"))), + xs_html_attr("placeholder", L("ntfy token - if needed")))), xs_html_tag("p", xs_html_text(L("Maximum days to keep posts (0: server settings):")), xs_html_sctag("br", NULL), @@ -2762,7 +2762,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_attr("href", url), xs_html_attr("class", "snac-list-link"), xs_html_attr("title", L("Pinned posts")), - xs_html_text("pinned")))); + xs_html_text(L("pinned"))))); } { @@ -2774,7 +2774,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_attr("href", url), xs_html_attr("class", "snac-list-link"), xs_html_attr("title", L("Bookmarked posts")), - xs_html_text("bookmarks")))); + xs_html_text(L("bookmarks"))))); } { @@ -2786,7 +2786,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_attr("href", url), xs_html_attr("class", "snac-list-link"), xs_html_attr("title", L("Post drafts")), - xs_html_text("drafts")))); + xs_html_text(L("drafts"))))); } /* the list of followed hashtags */ -- cgit