diff --git a/daemon.py b/daemon.py index b9b710bef..2e8b4f996 100644 --- a/daemon.py +++ b/daemon.py @@ -415,6 +415,7 @@ from crawlers import load_known_web_bots from qrcode import save_domain_qrcode from importFollowing import run_import_following_watchdog from maps import map_format_from_tagmaps_path +from relationships import get_moved_feed import os @@ -14363,6 +14364,145 @@ class PubServer(BaseHTTPRequestHandler): return True return False + def _show_moved_feed(self, authorized: bool, + calling_domain: str, referer_domain: str, + path: str, base_dir: str, http_prefix: str, + domain: str, port: int, getreq_start_time, + proxy_type: str, cookie: str, + debug: str, curr_session) -> bool: + """Shows the moved feed + """ + following = \ + get_moved_feed(base_dir, domain, port, path, + http_prefix, authorized, FOLLOWS_PER_PAGE) + if following: + if self._request_http(): + page_number = 1 + if '?page=' not in path: + search_path = path + # get a page of following, not the summary + following = \ + get_following_feed(base_dir, + domain, + port, + path + '?page=true', + http_prefix, + authorized, FOLLOWS_PER_PAGE) + else: + page_number_str = path.split('?page=')[1] + if ';' in page_number_str: + page_number_str = page_number_str.split(';')[0] + if '#' in page_number_str: + page_number_str = page_number_str.split('#')[0] + if len(page_number_str) > 5: + page_number_str = "1" + if page_number_str.isdigit(): + page_number = int(page_number_str) + search_path = path.split('?page=')[0] + get_person = \ + person_lookup(domain, + search_path.replace('/moved', ''), + base_dir) + if get_person: + curr_session = \ + self._establish_session("show_moved_feed", + curr_session, proxy_type) + if not curr_session: + self._404() + return True + + access_keys = self.server.access_keys + city = None + timezone = None + if '/users/' in path: + nickname = path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + if self.server.key_shortcuts.get(nickname): + access_keys = \ + self.server.key_shortcuts[nickname] + + city = get_spoofed_city(self.server.city, + base_dir, nickname, domain) + if self.server.account_timezone.get(nickname): + timezone = \ + self.server.account_timezone.get(nickname) + content_license_url = \ + self.server.content_license_url + shared_items_federated_domains = \ + self.server.shared_items_federated_domains + bold_reading = False + if self.server.bold_reading.get(nickname): + bold_reading = True + msg = \ + html_profile(self.server.signing_priv_key_pem, + self.server.rss_icon_at_top, + self.server.icons_as_buttons, + self.server.default_timeline, + self.server.recent_posts_cache, + self.server.max_recent_posts, + self.server.translate, + self.server.project_version, + base_dir, http_prefix, + authorized, + get_person, 'moved', + curr_session, + self.server.cached_webfingers, + self.server.person_cache, + self.server.yt_replace_domain, + self.server.twitter_replacement_domain, + self.server.show_published_date_only, + self.server.newswire, + self.server.theme_name, + self.server.dormant_months, + self.server.peertube_instances, + self.server.allow_local_network_access, + self.server.text_mode_banner, + self.server.debug, + access_keys, city, + self.server.system_language, + self.server.max_like_count, + shared_items_federated_domains, + following, + page_number, + FOLLOWS_PER_PAGE, + self.server.cw_lists, + self.server.lists_enabled, + content_license_url, + timezone, bold_reading).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_moved_feed', + debug) + return True + else: + if self._secure_mode(curr_session, proxy_type): + msg_str = json.dumps(following, + ensure_ascii=False) + msg_str = self._convert_domains(calling_domain, + referer_domain, + msg_str) + msg = msg_str.encode('utf-8') + msglen = len(msg) + accept_str = self.headers['Accept'] + protocol_str = \ + get_json_content_from_accept(accept_str) + self._set_headers(protocol_str, msglen, + None, calling_domain, False) + self._write(msg) + fitness_performance(getreq_start_time, + self.server.fitness, + '_GET', '_show_moved_feed json', + debug) + else: + self._404() + return True + return False + def _show_followers_feed(self, authorized: bool, calling_domain: str, referer_domain: str, path: str, base_dir: str, http_prefix: str, @@ -19147,6 +19287,24 @@ class PubServer(BaseHTTPRequestHandler): '_GET', 'show profile 3 done', self.server.debug) + if self._show_moved_feed(authorized, + calling_domain, referer_domain, + self.path, + self.server.base_dir, + self.server.http_prefix, + self.server.domain, + self.server.port, + getreq_start_time, + proxy_type, + cookie, self.server.debug, + curr_session): + self.server.getreq_busy = False + return + + fitness_performance(getreq_start_time, self.server.fitness, + '_GET', 'show moved 4 done', + self.server.debug) + if self._show_followers_feed(authorized, calling_domain, referer_domain, self.path, @@ -19162,7 +19320,7 @@ class PubServer(BaseHTTPRequestHandler): return fitness_performance(getreq_start_time, self.server.fitness, - '_GET', 'show profile 4 done', + '_GET', 'show profile 5 done', self.server.debug) # look up a person diff --git a/relationships.py b/relationships.py index a906199b1..784cc46c5 100644 --- a/relationships.py +++ b/relationships.py @@ -7,9 +7,13 @@ __email__ = "bob@libreserver.org" __status__ = "Production" __module_group__ = "Core" - import os from utils import acct_dir +from utils import valid_nickname +from utils import get_full_domain +from utils import local_actor_url +from utils import remove_domain_port +from utils import remove_eol def get_moved_accounts(base_dir: str, nickname: str, domain: str, @@ -51,3 +55,122 @@ def get_moved_accounts(base_dir: str, nickname: str, domain: str, if refollow_dict.get(handle): result[handle] = refollow_dict[handle] return result + + +def get_moved_feed(base_dir: str, domain: str, port: int, path: str, + http_prefix: str, authorized: bool, + follows_per_page=12) -> {}: + """Returns the moved accounts feed from GET requests. + """ + # Show a small number of follows to non-authorized viewers + if not authorized: + follows_per_page = 6 + + if '/moved' not in path: + return None + # handle page numbers + header_only = True + page_number = None + if '?page=' in path: + page_number = path.split('?page=')[1] + if len(page_number) > 5: + page_number = "1" + if page_number == 'true' or not authorized: + page_number = 1 + else: + try: + page_number = int(page_number) + except BaseException: + print('EX: get_moved_feed unable to convert to int ' + + str(page_number)) + path = path.split('?page=')[0] + header_only = False + + if not path.endswith('/moved'): + return None + nickname = None + if path.startswith('/users/'): + nickname = \ + path.replace('/users/', '', 1).replace('/moved', '') + if path.startswith('/@'): + nickname = path.replace('/@', '', 1).replace('/moved', '') + if not nickname: + return None + if not valid_nickname(domain, nickname): + return None + + domain = get_full_domain(domain, port) + + lines = get_moved_accounts(base_dir, nickname, domain, + 'following.txt') + + if header_only: + first_str = \ + local_actor_url(http_prefix, nickname, domain) + \ + '/moved?page=1' + id_str = \ + local_actor_url(http_prefix, nickname, domain) + '/moved' + total_str = str(len(lines.items())) + following = { + '@context': 'https://www.w3.org/ns/activitystreams', + 'first': first_str, + 'id': id_str, + 'totalItems': total_str, + 'type': 'OrderedCollection' + } + return following + + if not page_number: + page_number = 1 + + next_page_number = int(page_number + 1) + id_str = \ + local_actor_url(http_prefix, nickname, domain) + \ + '/moved?page=' + str(page_number) + part_of_str = \ + local_actor_url(http_prefix, nickname, domain) + '/moved' + following = { + '@context': 'https://www.w3.org/ns/activitystreams', + 'id': id_str, + 'orderedItems': [], + 'partOf': part_of_str, + 'totalItems': 0, + 'type': 'OrderedCollectionPage' + } + + handle_domain = domain + handle_domain = remove_domain_port(handle_domain) + accounts_dir = acct_dir(base_dir, nickname, handle_domain) + filename = accounts_dir + '/moved.txt' + if not os.path.isfile(filename): + return following + curr_page = 1 + page_ctr = 0 + total_ctr = 0 + for handle, new_handle in lines.items(): + # nickname@domain + page_ctr += 1 + total_ctr += 1 + if curr_page == page_number: + line2_lower = handle.lower() + line2 = remove_eol(line2_lower) + nick = line2.split('@')[0] + dom = line2.split('@')[1] + if not nick.startswith('!'): + # person actor + url = local_actor_url(http_prefix, nick, dom) + else: + # group actor + url = http_prefix + '://' + dom + '/c/' + nick + following['orderedItems'].append(url) + if page_ctr >= follows_per_page: + page_ctr = 0 + curr_page += 1 + following['totalItems'] = total_ctr + last_page = int(total_ctr / follows_per_page) + last_page = max(last_page, 1) + if next_page_number > last_page: + following['next'] = \ + local_actor_url(http_prefix, nickname, domain) + \ + '/moved?page=' + str(last_page) + return following diff --git a/translations/ar.json b/translations/ar.json index fa4713dbf..426ed88ed 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -602,5 +602,6 @@ "Minimize all images": "تصغير كل الصور", "Edit post": "تعديل المنشور", "Preview posts on profile screen": "معاينة المشاركات على شاشة الملف الشخصي", - "Reverse timelines": "عكس الجداول الزمنية" + "Reverse timelines": "عكس الجداول الزمنية", + "Moved": "انتقل" } diff --git a/translations/bn.json b/translations/bn.json index 7d29655b1..2aeb2c333 100644 --- a/translations/bn.json +++ b/translations/bn.json @@ -602,5 +602,6 @@ "Minimize all images": "সমস্ত ছবি ছোট করুন", "Edit post": "পোস্ট সম্পাদনা করুন", "Preview posts on profile screen": "প্রোফাইল স্ক্রিনে পোস্টের পূর্বরূপ দেখুন", - "Reverse timelines": "বিপরীত সময়রেখা" + "Reverse timelines": "বিপরীত সময়রেখা", + "Moved": "সরানো হয়েছে" } diff --git a/translations/ca.json b/translations/ca.json index d67b78592..cf2a852cb 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -602,5 +602,6 @@ "Minimize all images": "Minimitzar totes les imatges", "Edit post": "Edita la publicació", "Preview posts on profile screen": "Previsualitza les publicacions a la pantalla del perfil", - "Reverse timelines": "Cronologia inversa" + "Reverse timelines": "Cronologia inversa", + "Moved": "Mogut" } diff --git a/translations/cy.json b/translations/cy.json index c12103107..386b8f363 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -602,5 +602,6 @@ "Minimize all images": "Lleihau pob delwedd", "Edit post": "Golygu post", "Preview posts on profile screen": "Rhagolwg postiadau ar sgrin proffil", - "Reverse timelines": "Gwrthdroi llinellau amser" + "Reverse timelines": "Gwrthdroi llinellau amser", + "Moved": "Wedi symud" } diff --git a/translations/de.json b/translations/de.json index 72c4c5bf3..7769e49f5 100644 --- a/translations/de.json +++ b/translations/de.json @@ -602,5 +602,6 @@ "Minimize all images": "Alle Bilder minimieren", "Edit post": "Beitrag bearbeiten", "Preview posts on profile screen": "Vorschau von Beiträgen auf dem Profilbildschirm", - "Reverse timelines": "Umgekehrte Zeitlinien" + "Reverse timelines": "Umgekehrte Zeitlinien", + "Moved": "Gerührt" } diff --git a/translations/el.json b/translations/el.json index cf04ff8d0..044e5ae55 100644 --- a/translations/el.json +++ b/translations/el.json @@ -602,5 +602,6 @@ "Minimize all images": "Ελαχιστοποίηση όλων των εικόνων", "Edit post": "Επεξεργασία ανάρτησης", "Preview posts on profile screen": "Προεπισκόπηση αναρτήσεων στην οθόνη προφίλ", - "Reverse timelines": "Αντίστροφα χρονοδιαγράμματα" + "Reverse timelines": "Αντίστροφα χρονοδιαγράμματα", + "Moved": "Μετακινήθηκε" } diff --git a/translations/en.json b/translations/en.json index 9799205e6..c5a8cce9a 100644 --- a/translations/en.json +++ b/translations/en.json @@ -602,5 +602,6 @@ "Minimize all images": "Minimize all images", "Edit post": "Edit post", "Preview posts on profile screen": "Preview posts on profile screen", - "Reverse timelines": "Reverse timelines" + "Reverse timelines": "Reverse timelines", + "Moved": "Moved" } diff --git a/translations/es.json b/translations/es.json index 5e8192763..0a17c74d6 100644 --- a/translations/es.json +++ b/translations/es.json @@ -602,5 +602,6 @@ "Minimize all images": "Minimizar todas las imágenes", "Edit post": "Editar post", "Preview posts on profile screen": "Vista previa de publicaciones en la pantalla de perfil", - "Reverse timelines": "Líneas de tiempo inversas" + "Reverse timelines": "Líneas de tiempo inversas", + "Moved": "Movida" } diff --git a/translations/fa.json b/translations/fa.json index e7163e242..a6efb711b 100644 --- a/translations/fa.json +++ b/translations/fa.json @@ -602,5 +602,6 @@ "Minimize all images": "تمام تصاویر را به حداقل برسانید", "Edit post": "ویرایش پست", "Preview posts on profile screen": "پیش نمایش پست ها در صفحه نمایه", - "Reverse timelines": "جدول های زمانی معکوس" + "Reverse timelines": "جدول های زمانی معکوس", + "Moved": "منتقل شد" } diff --git a/translations/fr.json b/translations/fr.json index fb339e044..4a9ce3288 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -602,5 +602,6 @@ "Minimize all images": "Réduire toutes les images", "Edit post": "Modifier le message", "Preview posts on profile screen": "Prévisualiser les messages sur l'écran de profil", - "Reverse timelines": "Chronologies inversées" + "Reverse timelines": "Chronologies inversées", + "Moved": "Déplacée" } diff --git a/translations/ga.json b/translations/ga.json index a79625165..46ab271f7 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -602,5 +602,6 @@ "Minimize all images": "Íoslaghdaigh gach íomhá", "Edit post": "Cuir postáil in eagar", "Preview posts on profile screen": "Réamhamhairc postálacha ar an scáileán próifíle", - "Reverse timelines": "Amlínte droim ar ais" + "Reverse timelines": "Amlínte droim ar ais", + "Moved": "Ar athraíodh a ionad" } diff --git a/translations/hi.json b/translations/hi.json index deb79d897..23e5949d1 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -602,5 +602,6 @@ "Minimize all images": "सभी छवियों को छोटा करें", "Edit post": "संपादित पोस्ट", "Preview posts on profile screen": "प्रोफ़ाइल स्क्रीन पर पोस्ट का पूर्वावलोकन करें", - "Reverse timelines": "रिवर्स टाइमलाइन" + "Reverse timelines": "रिवर्स टाइमलाइन", + "Moved": "ले जाया गया" } diff --git a/translations/it.json b/translations/it.json index c4ec40463..b330f7c8a 100644 --- a/translations/it.json +++ b/translations/it.json @@ -602,5 +602,6 @@ "Minimize all images": "Riduci a icona tutte le immagini", "Edit post": "Modifica post", "Preview posts on profile screen": "Visualizza l'anteprima dei post nella schermata del profilo", - "Reverse timelines": "Invertire le tempistiche" + "Reverse timelines": "Invertire le tempistiche", + "Moved": "Mosso" } diff --git a/translations/ja.json b/translations/ja.json index 68b15e773..9914625de 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -602,5 +602,6 @@ "Minimize all images": "すべての画像を最小化", "Edit post": "投稿を編集", "Preview posts on profile screen": "プロフィール画面で投稿をプレビュー", - "Reverse timelines": "逆タイムライン" + "Reverse timelines": "逆タイムライン", + "Moved": "移動しました" } diff --git a/translations/ko.json b/translations/ko.json index 09722272a..af3f89ab7 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -602,5 +602,6 @@ "Minimize all images": "모든 이미지 최소화", "Edit post": "게시물 수정", "Preview posts on profile screen": "프로필 화면에서 게시물 미리보기", - "Reverse timelines": "역방향 타임라인" + "Reverse timelines": "역방향 타임라인", + "Moved": "움직이는" } diff --git a/translations/ku.json b/translations/ku.json index 8e7b5ee3b..7646fcb92 100644 --- a/translations/ku.json +++ b/translations/ku.json @@ -602,5 +602,6 @@ "Minimize all images": "Hemî wêneyan kêm bikin", "Edit post": "Biguherîne post", "Preview posts on profile screen": "Mesajên li ser ekrana profîlê pêşdîtin", - "Reverse timelines": "Reverse timelines" + "Reverse timelines": "Reverse timelines", + "Moved": "Moved" } diff --git a/translations/nl.json b/translations/nl.json index 933f1ecf3..70c523ea6 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -602,5 +602,6 @@ "Minimize all images": "Alle afbeeldingen minimaliseren", "Edit post": "Bericht bewerken", "Preview posts on profile screen": "Bekijk berichten op het profielscherm", - "Reverse timelines": "Omgekeerde tijdlijnen" + "Reverse timelines": "Omgekeerde tijdlijnen", + "Moved": "Verhuisd" } diff --git a/translations/oc.json b/translations/oc.json index 3fb7854f8..67edd637c 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -598,5 +598,6 @@ "Minimize all images": "Minimize all images", "Edit post": "Edit post", "Preview posts on profile screen": "Preview posts on profile screen", - "Reverse timelines": "Reverse timelines" + "Reverse timelines": "Reverse timelines", + "Moved": "Moved" } diff --git a/translations/pl.json b/translations/pl.json index 8d2b72a20..897f5ffa0 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -602,5 +602,6 @@ "Minimize all images": "Zminimalizuj wszystkie obrazy", "Edit post": "Edytuj post", "Preview posts on profile screen": "Podgląd postów na ekranie profilu", - "Reverse timelines": "Odwróć ramy czasowe" + "Reverse timelines": "Odwróć ramy czasowe", + "Moved": "Przeniósł" } diff --git a/translations/pt.json b/translations/pt.json index 23c0b6dbd..84b26dc4e 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -602,5 +602,6 @@ "Minimize all images": "Minimize todas as imagens", "Edit post": "Editar post", "Preview posts on profile screen": "Visualizar postagens na tela do perfil", - "Reverse timelines": "Cronogramas reversos" + "Reverse timelines": "Cronogramas reversos", + "Moved": "Mudou-se" } diff --git a/translations/ru.json b/translations/ru.json index 474607369..26812bb66 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -602,5 +602,6 @@ "Minimize all images": "Свернуть все изображения", "Edit post": "Редактировать сообщение", "Preview posts on profile screen": "Предварительный просмотр сообщений на экране профиля", - "Reverse timelines": "Обратные сроки" + "Reverse timelines": "Обратные сроки", + "Moved": "Взолнованный" } diff --git a/translations/sw.json b/translations/sw.json index 6c2f0da49..12a7a0802 100644 --- a/translations/sw.json +++ b/translations/sw.json @@ -602,5 +602,6 @@ "Minimize all images": "Punguza picha zote", "Edit post": "Badilisha chapisho", "Preview posts on profile screen": "Hakiki machapisho kwenye skrini ya wasifu", - "Reverse timelines": "Обратные сроки" + "Reverse timelines": "Обратные сроки", + "Moved": "Imehamishwa" } diff --git a/translations/tr.json b/translations/tr.json index 0730e7864..6e20405bc 100644 --- a/translations/tr.json +++ b/translations/tr.json @@ -602,5 +602,6 @@ "Minimize all images": "Tüm görüntüleri simge durumuna küçült", "Edit post": "Gönderiyi düzenle", "Preview posts on profile screen": "Gönderileri profil ekranında önizleyin", - "Reverse timelines": "Обратные сроки" + "Reverse timelines": "Обратные сроки", + "Moved": "Etkilenmiş" } diff --git a/translations/uk.json b/translations/uk.json index 2373f681c..db0d15dc8 100644 --- a/translations/uk.json +++ b/translations/uk.json @@ -602,5 +602,6 @@ "Minimize all images": "Згорнути всі зображення", "Edit post": "Редагувати пост", "Preview posts on profile screen": "Попередній перегляд дописів на екрані профілю", - "Reverse timelines": "Обратные сроки" + "Reverse timelines": "Обратные сроки", + "Moved": "Переїхав" } diff --git a/translations/yi.json b/translations/yi.json index 57c12a08e..fb6db4559 100644 --- a/translations/yi.json +++ b/translations/yi.json @@ -602,5 +602,6 @@ "Minimize all images": "מינאַמייז אַלע בילדער", "Edit post": "רעדאַגירן פּאָסטן", "Preview posts on profile screen": "פאָרויסיקע ווייַזונג אַרטיקלען אויף פּראָפיל פאַרשטעלן", - "Reverse timelines": "פאַרקערט טיימליינז" + "Reverse timelines": "פאַרקערט טיימליינז", + "Moved": "אריבערגעפארן" } diff --git a/translations/zh.json b/translations/zh.json index 92619799b..58433cde0 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -602,5 +602,6 @@ "Minimize all images": "最小化所有图像", "Edit post": "编辑帖子", "Preview posts on profile screen": "在个人资料屏幕上预览帖子", - "Reverse timelines": "倒转时间线" + "Reverse timelines": "倒转时间线", + "Moved": "אריבערגעפארן" } diff --git a/utils.py b/utils.py index 34ca8912e..496da8ea9 100644 --- a/utils.py +++ b/utils.py @@ -2240,7 +2240,7 @@ def _get_reserved_words() -> str: 'minimal', 'search', 'eventdelete', 'searchemoji', 'catalog', 'conversationId', 'mention', 'http', 'https', 'ipfs', 'ipns', - 'ontologies', 'data', 'postedit') + 'ontologies', 'data', 'postedit', 'moved') def get_nickname_validation_pattern() -> str: diff --git a/webapp_profile.py b/webapp_profile.py index 919bd773e..da0d316d1 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -680,6 +680,8 @@ def html_profile(signing_priv_key_pem: str, profile_description = standardize_text(profile_description) posts_button = 'button' following_button = 'button' + moved_button = 'button' + moved_button = 'button' followers_button = 'button' roles_button = 'button' skills_button = 'button' @@ -689,6 +691,8 @@ def html_profile(signing_priv_key_pem: str, posts_button = 'buttonselected' elif selected == 'following': following_button = 'buttonselected' + elif selected == 'moved': + moved_button = 'buttonselected' elif selected == 'followers': followers_button = 'buttonselected' elif selected == 'roles': @@ -1032,6 +1036,12 @@ def html_profile(signing_priv_key_pem: str, '' if not is_group: + if authorized: + profile_str += \ + ' ' + \ + '' profile_str += \ ' ' + \ @@ -1109,6 +1119,19 @@ def html_profile(signing_priv_key_pem: str, max_items_per_page, dormant_months, debug, signing_priv_key_pem) + if authorized and selected == 'moved': + profile_str += \ + _html_profile_following(translate, base_dir, http_prefix, + authorized, nickname, + domain, session, + cached_webfingers, + person_cache, extra_json, + project_version, ["unfollow"], + selected, + users_path, page_number, + max_items_per_page, + dormant_months, debug, + signing_priv_key_pem) if selected == 'followers': profile_str += \ _html_profile_following(translate, base_dir, http_prefix,