diff --git a/daemon.py b/daemon.py index ccffdc711..bf805dccb 100644 --- a/daemon.py +++ b/daemon.py @@ -377,6 +377,7 @@ from fitnessFunctions import fitness_thread from fitnessFunctions import sorted_watch_points from fitnessFunctions import html_watch_points_graph from siteactive import referer_is_active +from webapp_likers import html_likers_of_post import os @@ -10421,6 +10422,66 @@ class PubServer(BaseHTTPRequestHandler): self.server.debug) return result + def _show_likers_of_post(self, authorized: bool, + calling_domain: str, path: str, + base_dir: str, http_prefix: str, + domain: str, domain_full: str, port: int, + onion_domain: str, i2p_domain: str, + getreq_start_time, + proxy_type: str, cookie: str, + debug: str) -> bool: + """Show the likers of a post + """ + if not authorized: + return False + if '?likers=' not in path: + return False + if '/users/' not in path: + return False + nickname = path.split('/users/')[1] + if '?' in nickname: + nickname = nickname.split('?')[0] + post_url = path.split('?likers=')[1] + if '?' in post_url: + post_url = post_url.split('?')[0] + post_url = post_url.replace('--', '/') + + msg = \ + html_likers_of_post(base_dir, nickname, domain, port, + post_url, self.server.translate, + http_prefix, + self.server.theme_name, + self.server.access_keys, + self.server.recent_posts_cache, + self.server.max_recent_posts, + self.server.session, + self.server.cached_webfingers, + self.server.person_cache, + self.server.project_version, + self.server.yt_replace_domain, + self.server.twitter_replacement_domain, + self.server.show_published_date_only, + self.server.peertube_instances, + self.server.allow_local_network_access, + self.server.system_language, + self.server.max_like_count, + self.server.signing_priv_key_pem, + self.server.cw_lists, + self.server.lists_enabled, + 'inbox', self.server.default_timeline) + if not msg: + self._404() + return True + msg = msg.encode('utf-8') + msglen = len(msg) + self._set_headers('text/html', msglen, + cookie, calling_domain, False) + self._write(msg) + fitness_performance(getreq_start_time, self.server.fitness, + '_GET', '_show_likers_of_post', + self.server.debug) + return True + def _show_post_from_file(self, post_filename: str, liked_by: str, react_by: str, react_emoji: str, authorized: bool, @@ -16487,6 +16548,22 @@ class PubServer(BaseHTTPRequestHandler): self.server.getreq_busy = False return + # show the likers of a post + if self._show_likers_of_post(authorized, + calling_domain, self.path, + self.server.base_dir, + self.server.http_prefix, + self.server.domain, + self.server.domain_full, + self.server.port, + self.server.onion_domain, + self.server.i2p_domain, + getreq_start_time, + self.server.proxy_type, + cookie, self.server.debug): + self.server.getreq_busy = False + return + fitness_performance(getreq_start_time, self.server.fitness, '_GET', 'individual post done', self.server.debug) diff --git a/default_tos.md b/default_tos.md index 93ecb72bb..898177446 100644 --- a/default_tos.md +++ b/default_tos.md @@ -24,7 +24,7 @@ Moderators rely upon your reports. Don't assume that something of concern has al Content found to be non-compliant with this policy will be removed and any accounts on this instance producing, repeating or linking to such content will be deleted typically without prior notification. ### Federation Policy -In a proactive effort to avoid the classic fate of *"embrace, extend, extinguish"* this system will block any instance launched, acquired or funded by Alphabet/Google, Facebook, Twitter, Microsoft, Apple, Amazon, Elsevier or other monopolistic Silicon Valley companies. +In a proactive effort to avoid the classic fate of *"embrace, extend, extinguish"* this system will block any instance launched, acquired or funded by Alphabet/Google, Facebook/Meta, Twitter, Microsoft, Apple, Amazon, Elsevier or other monopolistic Silicon Valley companies. This system will not federate with instances whose moderation policy is incompatible with the content policy described above. If an instance lacks a moderation policy, or refuses to enforce one, it will be assumed to be incompatible. diff --git a/epicyon-profile.css b/epicyon-profile.css index c770cdb4c..b8b203e41 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -1,6 +1,12 @@ @charset "UTF-8"; :root { + --likes-names-margin: 2%; + --likes-names-size1: 30px; + --likes-names-size2: 40px; + --liker-names-margin: 2%; + --liker-names-vertical-spacing1: 50px; + --liker-names-vertical-spacing2: 100px; --pwa-theme-color: apple-mobile-web-app-status-bar-style; --pwa-theme-background-color: black-translucent; --avatar-rounding: 10%; @@ -54,8 +60,14 @@ --font-size4: 18px; --font-size5: 16px; --font-size-likes: 14px; - --font-size-likes-mobile: 32px; + --font-size-likes-mobile: 64px; --font-size-likes-tiny: 16px; + --likes-margin-left-tiny: 10px; + --likes-margin-right-tiny: 10px; + --likes-margin-top-tiny: -10px; + --likes-margin-left-mobile: 20px; + --likes-margin-right-mobile: 0px; + --likes-margin-top-mobile: 0px; --font-size-pgp-key: 16px; --font-size-pgp-key2: 18px; --font-size-tox: 16px; @@ -166,8 +178,6 @@ --containericons-vertical-align-mobile: 1%; --containericons-vertical-align-tiny: 0.5%; --likes-count-offset: 5px; - --likes-count-offset-mobile: 10px; - --likes-count-offset-tiny: 5px; --publish-button-vertical-offset: 10px; --publish-button-bottom-offset: 10px; --banner-height: 20vh; @@ -1078,6 +1088,12 @@ div.container { font-size: var(--font-size); color: var(--title-color); } + .likerNames { + font-size: var(--liker-names-size1); + font-family: Arial, Helvetica, sans-serif; + margin: var(--liker-names-margin); + line-height: var(--liker-names-vertical-spacing1); + } .profileHeader img.vcard { width: var(--vcard-icon-size); float: right; @@ -1845,6 +1861,12 @@ div.container { blockquote { font-size: var(--quote-font-size-mobile); } + .likerNames { + font-size: var(--liker-names-size2); + font-family: Arial, Helvetica, sans-serif; + margin: var(--liker-names-margin); + line-height: var(--liker-names-vertical-spacing2); + } .profileHeader img.vcard { width: var(--vcard-icon-size-mobile); float: right; @@ -2026,9 +2048,9 @@ div.container { .likesCount { font-size: var(--font-size-likes-mobile); font-family: 'NimbusSanL'; - float: right; - padding: 32px 0; - transform: translateX(var(--likes-count-offset-mobile)); + margin-left: var(--likes-margin-left-mobile); + margin-right: var(--likes-margin-right-mobile); + margin-top: var(--likes-margin-top-mobile); font-weight: bold; } .container p.administeredby { @@ -2584,6 +2606,12 @@ div.container { blockquote { font-size: var(--quote-font-size-tiny); } + .likerNames { + font-size: var(--font-size2); + font-family: 'NimbusSanL'; + margin: var(--liker-names-margin); + line-height: var(--liker-names-vertical-spacing2); + } .profileHeader img.vcard { width: var(--vcard-icon-size-tiny); float: right; @@ -2765,9 +2793,9 @@ div.container { .likesCount { font-size: var(--font-size-likes-tiny); font-family: 'NimbusSanL'; - float: right; - padding: 32px 0; - transform: translateX(var(--likes-count-offset-tiny)); + margin-left: var(--likes-margin-left-tiny); + margin-right: var(--likes-margin-right-tiny); + margin-top: var(--likes-margin-top-tiny); font-weight: bold; } .container p.administeredby { diff --git a/like.py b/like.py index a878d35d5..42b007cf8 100644 --- a/like.py +++ b/like.py @@ -36,7 +36,7 @@ from posts import get_person_box def no_of_likes(post_json_object: {}) -> int: - """Returns the number of likes ona given post + """Returns the number of likes on a given post """ obj = post_json_object if has_object_dict(post_json_object): diff --git a/theme/zen/theme.json b/theme/zen/theme.json index 8bae85a10..e883907fa 100644 --- a/theme/zen/theme.json +++ b/theme/zen/theme.json @@ -1,4 +1,8 @@ { + "font-size-likes-mobile": "64px", + "likes-margin-left-mobile": "20px", + "likes-margin-right-mobile": "0px", + "likes-margin-top-mobile": "0px", "pwa-theme-color": "apple-mobile-web-app-status-bar-style", "pwa-theme-background-color": "black-translucent", "dropdown-fg-color": "#d5c7b7", diff --git a/translations/ar.json b/translations/ar.json index 03f70b19b..c957dc507 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -511,5 +511,6 @@ "Lots of things": "أشياء كثيرة", "Created": "مخلوق", "It is done": "تم", - "Time Zone": "وحدة زمنية" + "Time Zone": "وحدة زمنية", + "Show who liked this post": "أظهر من أحب هذا المنشور" } diff --git a/translations/ca.json b/translations/ca.json index d21b6c45d..dacb28c4b 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -511,5 +511,6 @@ "Lots of things": "Moltes coses", "Created": "Creat", "It is done": "Esta fet", - "Time Zone": "Fus horari" + "Time Zone": "Fus horari", + "Show who liked this post": "Mostra a qui li agrada aquesta publicació" } diff --git a/translations/cy.json b/translations/cy.json index 3eecd68fb..9748400f2 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -511,5 +511,6 @@ "Lots of things": "Llawer o pethau", "Created": "Wedi creu", "It is done": "Mae'n cael ei wneud", - "Time Zone": "Parth Amser" + "Time Zone": "Parth Amser", + "Show who liked this post": "Dangoswch pwy oedd yn hoffi'r post hwn" } diff --git a/translations/de.json b/translations/de.json index 58ee7c708..6affc0714 100644 --- a/translations/de.json +++ b/translations/de.json @@ -511,5 +511,6 @@ "Lots of things": "Viele Dinge", "Created": "Erstellt", "It is done": "Es ist vollbracht", - "Time Zone": "Zeitzone" + "Time Zone": "Zeitzone", + "Show who liked this post": "Zeigen, wem dieser Beitrag gefallen hat" } diff --git a/translations/en.json b/translations/en.json index 6b00bcec0..6d63e9362 100644 --- a/translations/en.json +++ b/translations/en.json @@ -511,5 +511,6 @@ "Lots of things": "Lots of things", "Created": "Created", "It is done": "It is done", - "Time Zone": "Time Zone" + "Time Zone": "Time Zone", + "Show who liked this post": "Show who liked this post" } diff --git a/translations/es.json b/translations/es.json index 81d5f3471..85622b5ec 100644 --- a/translations/es.json +++ b/translations/es.json @@ -511,5 +511,6 @@ "Lots of things": "Muchas cosas", "Created": "Creada", "It is done": "Se hace", - "Time Zone": "Zona horaria" + "Time Zone": "Zona horaria", + "Show who liked this post": "Mostrar a quién le gustó esta publicación" } diff --git a/translations/fr.json b/translations/fr.json index 680fcfec9..d2e81c3cf 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -511,5 +511,6 @@ "Lots of things": "Beaucoup de choses", "Created": "Créé", "It is done": "C'est fait", - "Time Zone": "Fuseau horaire" + "Time Zone": "Fuseau horaire", + "Show who liked this post": "Montrer qui a aimé ce post" } diff --git a/translations/ga.json b/translations/ga.json index 5e52fc87d..094738e3f 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -511,5 +511,6 @@ "Lots of things": "A lán rudaí", "Created": "Cruthaithe", "It is done": "Déantar é", - "Time Zone": "Crios Ama" + "Time Zone": "Crios Ama", + "Show who liked this post": "Taispeáin cé a thaitin an postáil seo" } diff --git a/translations/hi.json b/translations/hi.json index ee544ed69..ad4c7e2a2 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -511,5 +511,6 @@ "Lots of things": "बहुत सी बातें", "Created": "बनाया था", "It is done": "हो गया है", - "Time Zone": "समय क्षेत्र" + "Time Zone": "समय क्षेत्र", + "Show who liked this post": "दिखाएँ कि इस पोस्ट को किसने पसंद किया" } diff --git a/translations/it.json b/translations/it.json index d95a3efb2..d9219f0a5 100644 --- a/translations/it.json +++ b/translations/it.json @@ -511,5 +511,6 @@ "Lots of things": "Un sacco di cose", "Created": "Creata", "It is done": "È fatta", - "Time Zone": "Fuso orario" + "Time Zone": "Fuso orario", + "Show who liked this post": "Mostra a chi è piaciuto questo post" } diff --git a/translations/ja.json b/translations/ja.json index f84add1c2..5c8c77d71 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -511,5 +511,6 @@ "Lots of things": "多くの物", "Created": "作成した", "It is done": "されております", - "Time Zone": "タイムゾーン" + "Time Zone": "タイムゾーン", + "Show who liked this post": "この投稿を高く評価した人を表示する" } diff --git a/translations/ku.json b/translations/ku.json index a1f8c0da7..f8ea5c51c 100644 --- a/translations/ku.json +++ b/translations/ku.json @@ -511,5 +511,6 @@ "Lots of things": "Gelek tişt", "Created": "Afirandin", "It is done": "Tê kirin", - "Time Zone": "Qada demê" + "Time Zone": "Qada demê", + "Show who liked this post": "Nîşan bide kê ev post eciband" } diff --git a/translations/oc.json b/translations/oc.json index 99f8e5cba..95ebeb902 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -507,5 +507,6 @@ "Lots of things": "Lots of things", "Created": "Created", "It is done": "It is done", - "Time Zone": "Time Zone" + "Time Zone": "Time Zone", + "Show who liked this post": "Show who liked this post" } diff --git a/translations/pt.json b/translations/pt.json index 928a76174..84c1a68f2 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -511,5 +511,6 @@ "Lots of things": "Muitas coisas", "Created": "Criada", "It is done": "Está feito", - "Time Zone": "Fuso horário" + "Time Zone": "Fuso horário", + "Show who liked this post": "Mostrar quem gostou deste post" } diff --git a/translations/ru.json b/translations/ru.json index 1bdac4cdc..34e0bce98 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -511,5 +511,6 @@ "Lots of things": "Много всего", "Created": "Созданный", "It is done": "Сделано", - "Time Zone": "Часовой пояс" + "Time Zone": "Часовой пояс", + "Show who liked this post": "Показать, кому понравился этот пост" } diff --git a/translations/sw.json b/translations/sw.json index d087b180d..ab7e8f5f8 100644 --- a/translations/sw.json +++ b/translations/sw.json @@ -511,5 +511,6 @@ "Lots of things": "Mambo mengi", "Created": "Imeundwa", "It is done": "Imefanyika", - "Time Zone": "Eneo la Saa" + "Time Zone": "Eneo la Saa", + "Show who liked this post": "Onyesha ni nani aliyependa chapisho hili" } diff --git a/translations/zh.json b/translations/zh.json index 4667646f1..56b2b45ca 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -511,5 +511,6 @@ "Lots of things": "很多事情", "Created": "已创建", "It is done": "完成了", - "Time Zone": "时区" + "Time Zone": "时区", + "Show who liked this post": "显示谁喜欢这篇文章" } diff --git a/webapp_likers.py b/webapp_likers.py new file mode 100644 index 000000000..088f69104 --- /dev/null +++ b/webapp_likers.py @@ -0,0 +1,136 @@ +__filename__ = "webapp_likers.py" +__author__ = "Bob Mottram" +__license__ = "AGPL3+" +__version__ = "1.3.0" +__maintainer__ = "Bob Mottram" +__email__ = "bob@libreserver.org" +__status__ = "Production" +__module_group__ = "ActivityPub" + +import os +from utils import locate_post +from utils import get_config_param +from utils import get_account_timezone +from utils import get_display_name +from utils import get_nickname_from_actor +from utils import has_object_dict +from utils import load_json +from webapp_utils import html_header_with_external_style +from webapp_utils import html_footer +from webapp_utils import get_banner_file +from webapp_post import individual_post_as_html + + +def html_likers_of_post(base_dir: str, nickname: str, + domain: str, port: int, + post_url: str, translate: {}, + http_prefix: str, + theme: str, access_keys: {}, + recent_posts_cache: {}, max_recent_posts: int, + session, cached_webfingers: {}, + person_cache: {}, + project_version: str, + yt_replace_domain: str, + twitter_replacement_domain: str, + show_published_date_only: bool, + peertube_instances: [], + allow_local_network_access: bool, + system_language: str, + max_like_count: int, signing_priv_key_pem: str, + cw_lists: {}, lists_enabled: str, + boxName: str, default_timeline: str) -> str: + """Returns html for a screen showing who liked a post + """ + css_filename = base_dir + '/epicyon-profile.css' + if os.path.isfile(base_dir + '/epicyon.css'): + css_filename = base_dir + '/epicyon.css' + + instance_title = get_config_param(base_dir, 'instanceTitle') + html_str = \ + html_header_with_external_style(css_filename, instance_title, None) + + # get the post which was liked + filename = locate_post(base_dir, nickname, domain, post_url) + if not filename: + return None + post_json_object = load_json(filename) + if not post_json_object: + return None + if not post_json_object.get('actor') or not post_json_object.get('object'): + return None + + # show the top banner + banner_file, _ = \ + get_banner_file(base_dir, nickname, domain, theme) + html_str += \ + '
\n' + \ + '\n' + html_str += '\n' + \ + '
\n' + + # show the post which was liked + timezone = get_account_timezone(base_dir, nickname, domain) + html_str += \ + individual_post_as_html(signing_priv_key_pem, + True, recent_posts_cache, + max_recent_posts, + translate, None, + base_dir, session, + cached_webfingers, + person_cache, + nickname, domain, port, + post_json_object, + None, True, False, + http_prefix, + project_version, + boxName, + yt_replace_domain, + twitter_replacement_domain, + show_published_date_only, + peertube_instances, + allow_local_network_access, + theme, system_language, + max_like_count, + False, False, False, + False, False, False, + cw_lists, lists_enabled, + timezone) + + # show likers beneath the post + obj = post_json_object + if has_object_dict(post_json_object): + obj = post_json_object['object'] + if not obj.get('likes'): + return None + if not isinstance(obj['likes'], dict): + return None + if not obj['likes'].get('items'): + return None + + html_str += '

' + translate['Liked by'] + '

\n' + + likers_list = '' + for like_item in obj['likes']['items']: + if not like_item.get('actor'): + continue + liker_actor = like_item['actor'] + liker_display_name = \ + get_display_name(base_dir, liker_actor, person_cache) + if liker_display_name: + liker_name = liker_display_name + else: + liker_name = get_nickname_from_actor(liker_actor) + if likers_list: + likers_list += ' ' + likers_list += \ + '' + html_str += '
\n' + likers_list + '\n
\n' + + return html_str + html_footer() diff --git a/webapp_post.py b/webapp_post.py index c82dc0257..0043b2233 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -651,22 +651,29 @@ def _get_like_icon_html(nickname: str, domain_full: str, _log_post_timing(enable_timing_log, post_start_time, '12.2') - like_str = '' - if like_count_str: - # show the number of likes next to icon - like_str += '\n' like_post_id = remove_hash_from_post_id(post_json_object['id']) like_post_id = remove_id_ending(like_post_id) + + like_str = '' + if like_count_str: + likers_post_id = like_post_id.replace('/', '--') + likers_screen_link = \ + '/users/' + nickname + '?likers=' + likers_post_id + + # show the number of likes next to icon + like_str += '\n' + like_str += \ ' \n' + '?tl=' + box_name + '" title="' + like_title + like_count_str + '">\n' like_str += \ ' ' + \ '