diff options
Diffstat (limited to 'html.c')
| -rw-r--r-- | html.c | 164 |
1 files changed, 123 insertions, 41 deletions
@@ -321,13 +321,11 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, name_link); if (!xs_is_null(url)) { - xs *md5 = xs_md5_hex(url, strlen(url)); - xs_html_add(actor_icon, xs_html_text(" "), xs_html_tag("a", xs_html_attr("href", (char *)url), - xs_html_attr("title", md5), + xs_html_attr("title", xs_is_string(md5) ? md5 : ""), xs_html_text("ยป"))); } @@ -347,6 +345,14 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, xs_html_attr("title", "mutual relation"), xs_html_raw("🤝"))); } + else + if (fwer) { + xs_html_add(actor_icon, + xs_html_text(" "), + xs_html_tag("span", + xs_html_attr("title", "follows you"), + xs_html_raw("👍"))); + } if (instance_failure(actor_id, 0) == -1) { xs_html_add(actor_icon, @@ -1634,6 +1640,7 @@ xs_html *html_top_controls(snac *user) const char *longitude = xs_dict_get_def(user->config, "longitude", ""); const char *webhook = xs_dict_get_def(user->config, "notify_webhook", ""); const char *post_langs = xs_dict_get_def(user->config, "post_langs", ""); + const char *excluded_langs = xs_dict_get_def(user->config, "excluded_langs", ""); xs *metadata = NULL; const xs_dict *md = xs_dict_get(user->config, "metadata"); @@ -1872,6 +1879,15 @@ xs_html *html_top_controls(snac *user) xs_html_attr("placeholder", L("en fr es de_AT")))), xs_html_tag("p", + xs_html_text(L("Don't show posts written in these languages:")), + xs_html_sctag("br", NULL), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", "excluded_langs"), + xs_html_attr("value", excluded_langs), + xs_html_attr("placeholder", L("en fr es de_AT")))), + + xs_html_tag("p", xs_html_text(L("New password:")), xs_html_sctag("br", NULL), xs_html_sctag("input", @@ -2056,6 +2072,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); @@ -2339,6 +2376,17 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, int c = 0; xs_dict_next(cmap, &lang, &dummy, &c); + + if (user && xs_is_string(lang)) { + /* discard posts in excluded languages */ + const char *excluded_langs = xs_dict_get(user->config, "excluded_langs"); + + if (xs_is_string(excluded_langs) && + xs_str_in(excluded_langs, lang) != -1) { + snac_debug(user, 1, xs_fmt("excluded post in language '%s'", lang)); + return NULL; + } + } } if (strcmp(type, "Follow") == 0) { @@ -2837,7 +2885,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, /* quoted post */ const char *quoted_id = xs_or(xs_dict_get(msg, "quoteUri"), xs_dict_get(msg, "quoteUrl")); - if (xs_is_string(quoted_id) && xs_match(quoted_id, "https://*|http://*")) { /** **/ + if (level < 3 && xs_is_string(quoted_id) && xs_match(quoted_id, "https://*|http://*")) { /** **/ xs *quoted_post = NULL; if (valid_status(object_get(quoted_id, "ed_post))) { @@ -3447,7 +3495,6 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, int utl, const char *error, int terse) /* returns the HTML for the timeline */ { - xs_list *p = (xs_list *)list; const char *v; double t = ftime(); int hide_children = xs_is_true(xs_dict_get(srv_config, "strict_public_timelines")) && read_only; @@ -3543,6 +3590,18 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, { /* show the list of bookmarked posts */ + xs *url = xs_fmt("%s/admirations", user->actor); + xs_html_add(lol, + xs_html_tag("li", + xs_html_tag("a", + xs_html_attr("href", url), + xs_html_attr("class", "snac-list-link"), + xs_html_attr("title", L("Liked, boosted or reacted posts")), + xs_html_text(L("admirations"))))); + } + + { + /* show the list of bookmarked posts */ xs *url = xs_fmt("%s/bookmarks", user->actor); xs_html_add(lol, xs_html_tag("li", @@ -3627,7 +3686,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, int show_unlisted = user ? xs_is_true(xs_dict_get(user->config, "show_unlisted")) : 0; - while (xs_list_iter(&p, &v)) { + xs_list_foreach(list, v) { xs *msg = NULL; int status; @@ -4790,54 +4849,52 @@ int html_get_handler(const xs_dict *req, const char *q_path, /* searching for an URL? */ if (q && xs_match(q, "https://*|http://*")) { - /* may by an actor; try a webfinger */ + /* bring it to the user's timeline */ xs *actor_obj = NULL; + xs *object = NULL; + int status; - if (valid_status(webfinger_request(q, &actor_obj, &url_acct)) && xs_is_string(url_acct)) { - /* it's an actor; do the dirty trick of changing q to the account name */ - q = url_acct; - } - else { - /* bring it to the user's timeline */ - xs *object = NULL; - int status; - - status = activitypub_request(&snac, q, &object); - snac_debug(&snac, 1, xs_fmt("Request searched URL %s %d", q, status)); + status = activitypub_request(&snac, q, &object); + snac_debug(&snac, 1, xs_fmt("Request searched URL %s %d", q, status)); - if (valid_status(status)) { - /* got it; also request the actor */ - const char *attr_to = get_atto(object); + if (valid_status(status) && xs_is_dict(object)) { + /* got it; also request the actor */ + const char *attr_to = get_atto(object); - if (!xs_is_null(attr_to)) { - status = actor_request(&snac, attr_to, &actor_obj); + if (!xs_is_null(attr_to)) { + status = actor_request(&snac, attr_to, &actor_obj); - if (valid_status(status)) { - /* reset the query string to be the real id */ - url_acct = xs_dup(xs_dict_get(object, "id")); - q = url_acct; + if (valid_status(status)) { + /* reset the query string to be the real id */ + url_acct = xs_dup(xs_dict_get(object, "id")); + q = url_acct; - /* add the post to the timeline */ - if (!timeline_here(&snac, q)) - timeline_add(&snac, q, object); - } + /* add the post to the timeline */ + if (!timeline_here(&snac, q)) + timeline_add(&snac, q, object); } - else { - /* retry webfinger, this time with the 'official' id */ - const char *id = xs_dict_get(object, "id"); + } + else { + /* retry webfinger, this time with the 'official' id */ + const char *id = xs_dict_get(object, "id"); - if (xs_is_string(id) && valid_status(webfinger_request(id, &actor_obj, &url_acct)) && - xs_is_string(url_acct)) - q = url_acct; - } + if (xs_is_string(id) && valid_status(webfinger_request_fake(id, &actor_obj, &url_acct)) && + xs_is_string(url_acct)) + q = url_acct; } } + else + /* may by an actor; try a webfinger */ + if (valid_status(webfinger_request(q, &actor_obj, &url_acct)) && xs_is_string(url_acct)) { + /* it's an actor; do the dirty trick of changing q to the account name */ + q = url_acct; + } /* fall through */ } if (q && *q) { - if (xs_regex_match(q, "^@?[a-zA-Z0-9._]+@[a-zA-Z0-9-]+\\.")) { + if (xs_regex_match(q, "^@?[^@]+@[a-zA-Z0-9-]+\\.")) { /** search account **/ xs *actor = NULL; xs *acct = NULL; @@ -5065,6 +5122,22 @@ int html_get_handler(const xs_dict *req, const char *q_path, } } else + if (strcmp(p_path, "admirations") == 0) { /** list of admired posts **/ + if (!login(&snac, req)) { + *body = xs_dup(uid); + status = HTTP_STATUS_UNAUTHORIZED; + } + else { + int more = 0; + xs *list = timeline_list(&snac, "admire", skip, show, &more); + + *body = html_timeline(&snac, list, 0, skip, show, + more, L("Liked, boosted or reacted posts"), "/admirations", 0, error, terse); + *b_size = strlen(*body); + status = HTTP_STATUS_OK; + } + } + else if (strcmp(p_path, "bookmarks") == 0) { /** list of bookmarked posts **/ if (!login(&snac, req)) { *body = xs_dup(uid); @@ -5385,7 +5458,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, uid = xs_list_get(l, 1); if (!uid || !user_open(&snac, uid)) { /* invalid user */ - srv_debug(1, xs_fmt("html_post_handler bad user %s", uid)); + srv_debug(1, xs_fmt("html_post_handler bad user %s", xs_or(uid, "(null)"))); return HTTP_STATUS_NOT_FOUND; } @@ -5656,6 +5729,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, const char *eid = xs_dict_get(p_vars, "eid"); if (eid != NULL) { + object_user_cache_del(&snac, id, "admire"); xs *n_msg = msg_emoji_unreact(&snac, id, eid); if (n_msg != NULL) @@ -5670,8 +5744,10 @@ int html_post_handler(const xs_dict *req, const char *q_path, xs *ret = msg_emoji_init(&snac, id, eid); /* fails if either invalid or already reacted */ - if (!ret) + if (!ret) { + object_user_cache_del(&snac, id, "admire"); ret = msg_emoji_unreact(&snac, id, eid); + } if (!ret) status = HTTP_STATUS_NOT_FOUND; } @@ -5698,6 +5774,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, xs *msg = msg_repulsion(&snac, id, "Like"); if (msg != NULL) { + object_user_cache_del(&snac, id, "admire"); enqueue_message(&snac, msg); } } @@ -5706,6 +5783,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, xs *msg = msg_repulsion(&snac, id, "Announce"); if (msg != NULL) { + object_user_cache_del(&snac, id, "admire"); enqueue_message(&snac, msg); } } @@ -5950,6 +6028,10 @@ int html_post_handler(const xs_dict *req, const char *q_path, snac.config = xs_dict_set(snac.config, "tz", v); if ((v = xs_dict_get(p_vars, "post_langs")) != NULL) snac.config = xs_dict_set(snac.config, "post_langs", v); + if ((v = xs_dict_get(p_vars, "excluded_langs")) != NULL) + snac.config = xs_dict_set(snac.config, "excluded_langs", v); + else + snac.config = xs_dict_del(snac.config, "excluded_langs"); 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", "")); |