From dae314b806c259f56594b0fa8540d8a556860429 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 9 Feb 2023 17:34:01 +0000 Subject: [PATCH 01/14] Styling of post scope icon --- epicyon-profile.css | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/epicyon-profile.css b/epicyon-profile.css index 65adaa37e..85314cd9e 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -758,15 +758,6 @@ a:focus { vertical-align: middle; } -.container img.postScopeIcon { - float: none; - width: 30px; - margin: 0 0; - padding: 0 0; - border-radius: 0; - vertical-align: -6px; -} - .container.darker { background-color: var(--main-bg-color-reply); } @@ -1187,6 +1178,14 @@ h3 { font-size: var(--font-size); color: var(--title-color); } + .container img.postScopeIcon { + float: none; + width: 30px; + margin: 0 0; + padding: 0 0; + border-radius: 0; + vertical-align: -6px; + } figcaption img.emojiheader { float: none; width: 25px; @@ -2009,6 +2008,14 @@ h3 { font-size: var(--font-size-mobile); color: var(--title-color); } + .container img.postScopeIcon { + float: none; + width: 50px; + margin: 0 0; + padding: 0 0; + border-radius: 0; + vertical-align: -6px; + } blockquote { font-size: var(--quote-font-size-mobile); } @@ -2821,6 +2828,14 @@ h3 { font-size: var(--font-size-tiny); color: var(--title-color); } + .container img.postScopeIcon { + float: none; + width: 50px; + margin: 0 0; + padding: 0 0; + border-radius: 0; + vertical-align: -6px; + } blockquote { font-size: var(--quote-font-size-tiny); } From d863eb25e41ddb3237c05ef77ef5065615fec452 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 9 Feb 2023 20:40:42 +0000 Subject: [PATCH 02/14] Three representations of public post --- inbox.py | 4 +++- posts.py | 38 +++++++++++++++++++++++++++++--------- utils.py | 12 +++++++++--- webapp_utils.py | 8 ++++++-- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/inbox.py b/inbox.py index 68e821ea6..b6ff35ec0 100644 --- a/inbox.py +++ b/inbox.py @@ -822,7 +822,9 @@ def _inbox_post_recipients_add(base_dir: str, http_prefix: str, to_list: [], handle + ' does not exist') else: if debug: - if recipient.endswith('#Public'): + if recipient.endswith('#Public') or \ + recipient == 'as:Public' or \ + recipient == 'Public': print('DEBUG: #Public recipient is too non-specific. ' + recipient + ' ' + domain_match) else: diff --git a/posts.py b/posts.py index d2ab8977a..0bfee861c 100644 --- a/posts.py +++ b/posts.py @@ -456,7 +456,9 @@ def _is_public_feed_post(item: {}, person_posts: {}, debug: bool) -> bool: if this_item.get('to'): is_public = False for recipient in this_item['to']: - if recipient.endswith('#Public'): + if recipient.endswith('#Public') or \ + recipient == 'as:Public' or \ + recipient == 'Public': is_public = True break if not is_public: @@ -465,7 +467,9 @@ def _is_public_feed_post(item: {}, person_posts: {}, debug: bool) -> bool: if item.get('to'): is_public = False for recipient in item['to']: - if recipient.endswith('#Public'): + if recipient.endswith('#Public') or \ + recipient == 'as:Public' or \ + recipient == 'Public': is_public = True break if not is_public: @@ -1402,7 +1406,12 @@ def _create_post_mentions(cc_url: str, new_post: {}, to_cc = new_post['object']['cc'] if len(to_recipients) != 1: return - if to_recipients[0].endswith('#Public') and \ + to_public_recipient = False + if to_recipients[0].endswith('#Public') or \ + to_recipients[0] == 'as:Public' or \ + to_recipients[0] == 'Public': + to_public_recipient = True + if to_public_recipient and \ cc_url.endswith('/followers'): for tag in tags: if tag['type'] != 'Mention': @@ -1582,7 +1591,9 @@ def _create_post_base(base_dir: str, is_public = False for recipient in to_recipients: - if recipient.endswith('#Public'): + if recipient.endswith('#Public') or \ + recipient == 'as:Public' or \ + recipient == 'Public': is_public = True break @@ -2834,7 +2845,9 @@ def _add_followers_to_public_post(post_json_object: {}) -> None: if len(post_json_object['to']) == 0: return if not post_json_object['to'][0].endswith('#Public'): - return + if not post_json_object['to'][0] == 'as:Public': + if not post_json_object['to'][0] == 'Public': + return if post_json_object.get('cc'): return post_json_object['cc'] = post_json_object['actor'] + '/followers' @@ -2846,7 +2859,9 @@ def _add_followers_to_public_post(post_json_object: {}) -> None: if len(post_json_object['object']['to']) == 0: return if not post_json_object['object']['to'][0].endswith('#Public'): - return + if not post_json_object['object']['to'][0] == 'as:Public': + if not post_json_object['object']['to'][0] == 'Public': + return if post_json_object['object'].get('cc'): return post_json_object['object']['cc'] = \ @@ -3222,7 +3237,9 @@ def _send_to_named_addresses(server, session, session_onion, session_i2p, continue if '/' not in address: continue - if address.endswith('#Public'): + if address.endswith('#Public') or \ + address == 'as:Public' or \ + address == 'Public': continue if address.endswith('/followers'): continue @@ -3231,7 +3248,9 @@ def _send_to_named_addresses(server, session, session_onion, session_i2p, address = recipients_object[rtype] if address: if '/' in address: - if address.endswith('#Public'): + if address.endswith('#Public') or \ + address == 'as:Public' or \ + address == 'Public': continue if address.endswith('/followers'): continue @@ -3900,7 +3919,8 @@ def _add_post_string_to_timeline(post_str: str, boxname: str, ('"Create"' in post_str or '"Update"' in post_str))): if boxname == 'dm': - if '#Public' in post_str or '/followers' in post_str: + if '#Public' in post_str or \ + '/followers' in post_str: return False elif boxname == 'tlreplies': if box_actor not in post_str: diff --git a/utils.py b/utils.py index 6a0f9d751..652ca496b 100644 --- a/utils.py +++ b/utils.py @@ -2096,7 +2096,9 @@ def is_dm(post_json_object: {}) -> bool: if not post_json_object['object'].get(field_name): continue for to_address in post_json_object['object'][field_name]: - if to_address.endswith('#Public'): + if to_address.endswith('#Public') or \ + to_address == 'as:Public' or \ + to_address == 'Public': return False if to_address.endswith('followers'): return False @@ -2428,7 +2430,9 @@ def is_public_post(post_json_object: {}) -> bool: if not post_json_object['object'].get('to'): return False for recipient in post_json_object['object']['to']: - if recipient.endswith('#Public'): + if recipient.endswith('#Public') or \ + recipient == 'as:Public' or \ + recipient == 'Public': return True return False @@ -2471,7 +2475,9 @@ def is_unlisted_post(post_json_object: {}) -> bool: if not has_followers: return False for recipient in post_json_object['object']['cc']: - if recipient.endswith('#Public'): + if recipient.endswith('#Public') or \ + recipient == 'as:Public' or \ + recipient == 'Public': return True return False diff --git a/webapp_utils.py b/webapp_utils.py index 22465ec7d..43348c65f 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -564,13 +564,17 @@ def post_contains_public(post_json_object: {}) -> bool: return contains_public for to_address in post_json_object['object']['to']: - if to_address.endswith('#Public'): + if to_address.endswith('#Public') or \ + to_address == 'as:Public' or \ + to_address == 'Public': contains_public = True break if not contains_public: if post_json_object['object'].get('cc'): for to_address2 in post_json_object['object']['cc']: - if to_address2.endswith('#Public'): + if to_address2.endswith('#Public') or \ + to_address2 == 'as:Public' or \ + to_address2 == 'Public': contains_public = True break return contains_public From 50c47b89f8b35b0de1d7f9ce217a5091e6508777 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 10 Feb 2023 12:02:10 +0000 Subject: [PATCH 03/14] Import blocked domains from csv --- blocking.py | 98 ++++++++++++++++++++++++++++++++++++++++++++ daemon.py | 25 +++++++++++ translations/ar.json | 4 +- translations/bn.json | 4 +- translations/ca.json | 4 +- translations/cy.json | 4 +- translations/de.json | 4 +- translations/el.json | 4 +- translations/en.json | 4 +- translations/es.json | 4 +- translations/fa.json | 4 +- translations/fr.json | 4 +- translations/ga.json | 4 +- translations/hi.json | 4 +- translations/it.json | 4 +- translations/ja.json | 4 +- translations/ko.json | 4 +- translations/ku.json | 4 +- translations/nl.json | 4 +- translations/oc.json | 4 +- translations/pl.json | 4 +- translations/pt.json | 4 +- translations/ru.json | 4 +- translations/sw.json | 4 +- translations/tr.json | 4 +- translations/uk.json | 4 +- translations/yi.json | 4 +- translations/zh.json | 4 +- webapp_profile.py | 15 +++++++ 29 files changed, 216 insertions(+), 26 deletions(-) diff --git a/blocking.py b/blocking.py index 05f68dd93..3b254d086 100644 --- a/blocking.py +++ b/blocking.py @@ -1460,3 +1460,101 @@ def get_cw_list_variable(list_name: str) -> str: """Returns the variable associated with a CW list """ return 'list' + list_name.replace(' ', '').replace("'", '') + + +def import_blocks(base_dir: str, nickname: str, domain: str, + filename: str) -> bool: + """Imports blocked domains for a given account + """ + lines = [] + try: + with open(filename, 'r', encoding='utf-8') as fp_blocks: + lines = fp_blocks.read().splitlines() + except OSError: + print('EX: unable to import blocked instances from file ' + + filename) + if not lines: + return False + if len(lines) < 2: + return False + if not lines[0].startswith('#domain,#') or \ + 'comment' not in lines[0]: + return False + fieldnames = lines[0].split(',') + comment_field_index = 0 + for field_str in fieldnames: + if 'comment' in field_str: + break + comment_field_index += 1 + if comment_field_index >= len(fieldnames): + return False + + account_directory = acct_dir(base_dir, nickname, domain) + blocking_filename = \ + account_directory + '/blocking.txt' + blocking_reasons_filename = \ + account_directory + '/blocking_reasons.txt' + + existing_lines = [] + if os.path.isfile(blocking_filename): + try: + with open(blocking_filename, 'r', encoding='utf-8') as fp_blocks: + existing_lines = fp_blocks.read().splitlines() + except OSError: + print('EX: ' + + 'unable to import existing blocked instances from file ' + + blocking_filename) + existing_reasons = [] + if os.path.isfile(blocking_reasons_filename): + try: + with open(blocking_reasons_filename, + 'r', encoding='utf-8') as fp_blocks: + existing_reasons = fp_blocks.read().splitlines() + except OSError: + print('EX: ' + + 'unable to import existing ' + + 'blocked instance reasons from file ' + + blocking_reasons_filename) + + append_blocks = [] + append_reasons = [] + for line_str in lines: + if line_str.startswith('#'): + continue + block_fields = line_str.split(',') + blocked_domain_name = block_fields[0].strip() + if ' ' in blocked_domain_name or \ + '.' not in blocked_domain_name: + continue + if blocked_domain_name in existing_lines: + # already blocked + continue + append_blocks.append(blocked_domain_name) + blocked_comment = block_fields[comment_field_index].strip() + if blocked_comment: + if blocked_comment not in existing_reasons: + append_reasons.append(blocked_domain_name + ' ' + + blocked_comment) + if not append_blocks: + return True + + try: + with open(blocking_filename, 'a+', encoding='utf-8') as fp_blocks: + for new_block in append_blocks: + fp_blocks.write(new_block + '\n') + except OSError: + print('EX: ' + + 'unable to append imported blocks to ' + + blocking_filename) + + try: + with open(blocking_reasons_filename, 'a+', + encoding='utf-8') as fp_blocks: + for new_reason in append_reasons: + fp_blocks.write(new_reason + '\n') + except OSError: + print('EX: ' + + 'unable to append imported block reasons to ' + + blocking_reasons_filename) + + return True diff --git a/daemon.py b/daemon.py index 28f715512..5f72edc44 100644 --- a/daemon.py +++ b/daemon.py @@ -147,6 +147,7 @@ from media import replace_twitter from media import attach_media from media import path_is_video from media import path_is_audio +from blocking import import_blocks from blocking import add_account_blocks from blocking import get_cw_list_variable from blocking import load_cw_lists @@ -6172,6 +6173,7 @@ class PubServer(BaseHTTPRequestHandler): 'instanceLogo', 'left_col_image', 'right_col_image', 'submitImportFollows', + 'submitImportBlocks', 'submitImportTheme' ) profile_media_types_uploaded = {} @@ -6220,6 +6222,10 @@ class PubServer(BaseHTTPRequestHandler): filename_base = \ acct_dir(base_dir, nickname, domain) + \ '/import_following.csv' + elif m_type == 'submitImportBlocks': + filename_base = \ + acct_dir(base_dir, nickname, domain) + \ + '/import_blocks.csv' else: filename_base = \ acct_dir(base_dir, nickname, domain) + \ @@ -6244,6 +6250,25 @@ class PubServer(BaseHTTPRequestHandler): nickname) continue + if m_type == 'submitImportBlocks': + if os.path.isfile(filename_base): + blocks_import_succeeded = False + if import_blocks(base_dir, nickname, domain, + filename_base): + print(nickname + ' imported blocks csv') + blocks_import_succeeded = True + try: + os.remove(filename_base) + except OSError: + print('EX: ' + + 'unable to remove imported blocks file ' + + filename_base) + if blocks_import_succeeded: + continue + print('WARN: failed to import blocks from csv for ' + + nickname) + continue + if m_type == 'submitImportTheme': if nickname == admin_nickname or \ is_artist(base_dir, nickname): diff --git a/translations/ar.json b/translations/ar.json index b81b52f08..4ebdfbdd9 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -617,5 +617,7 @@ "Buy link": "رابط شراء", "Buy links are allowed from the following domains": "روابط الشراء مسموح بها من المجالات التالية", "Media license": "رخصة وسائل الإعلام", - "Media creator": "صانع الوسائط" + "Media creator": "صانع الوسائط", + "Import Blocks": "استيراد مثيلات محظورة", + "Export Blocks": "تصدير المثيلات المحظورة" } diff --git a/translations/bn.json b/translations/bn.json index c5032d6cc..633265209 100644 --- a/translations/bn.json +++ b/translations/bn.json @@ -617,5 +617,7 @@ "Buy link": "সংযোগ কেনা", "Buy links are allowed from the following domains": "নিম্নলিখিত ডোমেনগুলি থেকে লিঙ্কগুলি কেনার অনুমতি দেওয়া হয়েছে", "Media license": "মিডিয়া লাইসেন্স", - "Media creator": "মিডিয়া নির্মাতা" + "Media creator": "মিডিয়া নির্মাতা", + "Import Blocks": "অবরুদ্ধ দৃষ্টান্ত আমদানি করুন", + "Export Blocks": "অবরুদ্ধ দৃষ্টান্ত রপ্তানি করুন" } diff --git a/translations/ca.json b/translations/ca.json index ad5ed9676..05ebf95ac 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -617,5 +617,7 @@ "Buy link": "Enllaç de compra", "Buy links are allowed from the following domains": "Els enllaços de compra es permeten des dels dominis següents", "Media license": "Llicència de mitjans", - "Media creator": "Creador de mitjans" + "Media creator": "Creador de mitjans", + "Import Blocks": "Importa instàncies bloquejades", + "Export Blocks": "Exporta instàncies bloquejades" } diff --git a/translations/cy.json b/translations/cy.json index 8446a0fc9..a9fa19e6a 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -617,5 +617,7 @@ "Buy link": "Prynu dolen", "Buy links are allowed from the following domains": "Caniateir dolenni prynu o'r parthau canlynol", "Media license": "Trwydded cyfryngau", - "Media creator": "Crëwr cyfryngau" + "Media creator": "Crëwr cyfryngau", + "Import Blocks": "Mewnforio Achosion wedi'u Rhwystro", + "Export Blocks": "Allforio Achosion wedi'u Rhwystro" } diff --git a/translations/de.json b/translations/de.json index e8c010de1..17659190a 100644 --- a/translations/de.json +++ b/translations/de.json @@ -617,5 +617,7 @@ "Buy link": "Link kaufen", "Buy links are allowed from the following domains": "Kauflinks sind von den folgenden Domains erlaubt", "Media license": "Medienlizenz", - "Media creator": "Mediengestalter" + "Media creator": "Mediengestalter", + "Import Blocks": "Blockierte Instanzen importieren", + "Export Blocks": "Blockierte Instanzen exportieren" } diff --git a/translations/el.json b/translations/el.json index af95a1f9a..e50e8fa51 100644 --- a/translations/el.json +++ b/translations/el.json @@ -617,5 +617,7 @@ "Buy link": "Σύνδεσμος αγοράς", "Buy links are allowed from the following domains": "Οι σύνδεσμοι αγοράς επιτρέπονται από τους παρακάτω τομείς", "Media license": "Άδεια ΜΜΕ", - "Media creator": "Δημιουργός πολυμέσων" + "Media creator": "Δημιουργός πολυμέσων", + "Import Blocks": "Εισαγωγή αποκλεισμένων παρουσιών", + "Export Blocks": "Εξαγωγή αποκλεισμένων παρουσιών" } diff --git a/translations/en.json b/translations/en.json index 278db6e9f..dca7d64b7 100644 --- a/translations/en.json +++ b/translations/en.json @@ -617,5 +617,7 @@ "Buy link": "Buy link", "Buy links are allowed from the following domains": "Buy links are allowed from the following domains", "Media license": "Media license", - "Media creator": "Media creator" + "Media creator": "Media creator", + "Import Blocks": "Import Blocks", + "Export Blocks": "Export Blocks" } diff --git a/translations/es.json b/translations/es.json index 6e8a14a62..b30c32413 100644 --- a/translations/es.json +++ b/translations/es.json @@ -617,5 +617,7 @@ "Buy link": "Enlace de compra", "Buy links are allowed from the following domains": "Se permiten enlaces de compra de los siguientes dominios", "Media license": "Licencia de medios", - "Media creator": "Creadora de medios" + "Media creator": "Creadora de medios", + "Import Blocks": "Importar instancias bloqueadas", + "Export Blocks": "Exportar instancias bloqueadas" } diff --git a/translations/fa.json b/translations/fa.json index f4895eb61..25f0fe70c 100644 --- a/translations/fa.json +++ b/translations/fa.json @@ -617,5 +617,7 @@ "Buy link": "لینک خرید", "Buy links are allowed from the following domains": "لینک خرید از دامنه های زیر مجاز است", "Media license": "مجوز رسانه", - "Media creator": "سازنده رسانه" + "Media creator": "سازنده رسانه", + "Import Blocks": "وارد کردن موارد مسدود شده", + "Export Blocks": "نمونه های مسدود شده را صادر کنید" } diff --git a/translations/fr.json b/translations/fr.json index 4f84280c8..7b3d2bf19 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -617,5 +617,7 @@ "Buy link": "Acheter un lien", "Buy links are allowed from the following domains": "Les liens d'achat sont autorisés à partir des domaines suivants", "Media license": "Licence média", - "Media creator": "Créateur de médias" + "Media creator": "Créateur de médias", + "Import Blocks": "Importer des instances bloquées", + "Export Blocks": "Exporter les instances bloquées" } diff --git a/translations/ga.json b/translations/ga.json index 0e7e7d460..c5383252f 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -617,5 +617,7 @@ "Buy link": "Ceannaigh nasc", "Buy links are allowed from the following domains": "Ceadaítear naisc cheannaigh ó na fearainn seo a leanas", "Media license": "Ceadúnas meáin", - "Media creator": "Cruthaitheoir meáin" + "Media creator": "Cruthaitheoir meáin", + "Import Blocks": "Iompórtáil Cásanna Blocáilte", + "Export Blocks": "Easpórtáil Cásanna Blocáilte" } diff --git a/translations/hi.json b/translations/hi.json index 5b2992dcc..3c8fc236a 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -617,5 +617,7 @@ "Buy link": "लिंक खरीदें", "Buy links are allowed from the following domains": "निम्नलिखित डोमेन से खरीदें लिंक की अनुमति है", "Media license": "मीडिया लाइसेंस", - "Media creator": "मीडिया निर्माता" + "Media creator": "मीडिया निर्माता", + "Import Blocks": "अवरोधित उदाहरण आयात करें", + "Export Blocks": "निर्यात अवरुद्ध उदाहरण" } diff --git a/translations/it.json b/translations/it.json index ab986d350..a0ddb6430 100644 --- a/translations/it.json +++ b/translations/it.json @@ -617,5 +617,7 @@ "Buy link": "Link per l'acquisto", "Buy links are allowed from the following domains": "I link di acquisto sono consentiti dai seguenti domini", "Media license": "Licenza multimediale", - "Media creator": "Creatore multimediale" + "Media creator": "Creatore multimediale", + "Import Blocks": "Importa istanze bloccate", + "Export Blocks": "Esporta istanze bloccate" } diff --git a/translations/ja.json b/translations/ja.json index 0c2cb9a78..3d530171e 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -617,5 +617,7 @@ "Buy link": "購入リンク", "Buy links are allowed from the following domains": "次のドメインからの購入リンクが許可されています", "Media license": "メディアライセンス", - "Media creator": "メディアクリエーター" + "Media creator": "メディアクリエーター", + "Import Blocks": "ブロックされたインスタンスのインポート", + "Export Blocks": "ブロックされたインスタンスのエクスポート" } diff --git a/translations/ko.json b/translations/ko.json index dc6d6f577..416e33d76 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -617,5 +617,7 @@ "Buy link": "구매 링크", "Buy links are allowed from the following domains": "다음 도메인에서 구매 링크가 허용됩니다.", "Media license": "미디어 라이센스", - "Media creator": "미디어 크리에이터" + "Media creator": "미디어 크리에이터", + "Import Blocks": "차단된 인스턴스 가져오기", + "Export Blocks": "차단된 인스턴스 내보내기" } diff --git a/translations/ku.json b/translations/ku.json index 385541118..e739010a4 100644 --- a/translations/ku.json +++ b/translations/ku.json @@ -617,5 +617,7 @@ "Buy link": "Girêdanê bikirin", "Buy links are allowed from the following domains": "Zencîreyên kirînê ji domên jêrîn têne destûr kirin", "Media license": "Lîsansa medyayê", - "Media creator": "Afirînerê medyayê" + "Media creator": "Afirînerê medyayê", + "Import Blocks": "Mînakên Astengkirî Import", + "Export Blocks": "Mînakên Astengkirî Export" } diff --git a/translations/nl.json b/translations/nl.json index 7c53151d7..98ac9c26f 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -617,5 +617,7 @@ "Buy link": "koop link", "Buy links are allowed from the following domains": "Kooplinks zijn toegestaan vanaf de volgende domeinen", "Media license": "Media licentie", - "Media creator": "Media-maker" + "Media creator": "Media-maker", + "Import Blocks": "Importeer geblokkeerde instanties", + "Export Blocks": "Exporteer geblokkeerde instanties" } diff --git a/translations/oc.json b/translations/oc.json index 45e2bb7de..922848b71 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -613,5 +613,7 @@ "Buy link": "Buy link", "Buy links are allowed from the following domains": "Buy links are allowed from the following domains", "Media license": "Media license", - "Media creator": "Media creator" + "Media creator": "Media creator", + "Import Blocks": "Import Blocks", + "Export Blocks": "Export Blocks" } diff --git a/translations/pl.json b/translations/pl.json index 3858f49fa..866dc0f2f 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -617,5 +617,7 @@ "Buy link": "Kup Link", "Buy links are allowed from the following domains": "Kupuj linki są dozwolone z następujących domen", "Media license": "Licencja medialna", - "Media creator": "Kreator mediów" + "Media creator": "Kreator mediów", + "Import Blocks": "Importuj zablokowane instancje", + "Export Blocks": "Eksportuj zablokowane instancje" } diff --git a/translations/pt.json b/translations/pt.json index 6c11a0d59..1b6c9c7dd 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -617,5 +617,7 @@ "Buy link": "Link de compra", "Buy links are allowed from the following domains": "Links de compra são permitidos nos seguintes domínios", "Media license": "Licença de mídia", - "Media creator": "Criador de mídia" + "Media creator": "Criador de mídia", + "Import Blocks": "Importar instâncias bloqueadas", + "Export Blocks": "Exportar instâncias bloqueadas" } diff --git a/translations/ru.json b/translations/ru.json index f859e1d58..4679f935c 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -617,5 +617,7 @@ "Buy link": "Купить ссылку", "Buy links are allowed from the following domains": "Ссылки на покупку разрешены со следующих доменов", "Media license": "Медиа лицензия", - "Media creator": "Создатель медиа" + "Media creator": "Создатель медиа", + "Import Blocks": "Импорт заблокированных экземпляров", + "Export Blocks": "Экспорт заблокированных экземпляров" } diff --git a/translations/sw.json b/translations/sw.json index f4f04873f..9a1bad0f3 100644 --- a/translations/sw.json +++ b/translations/sw.json @@ -617,5 +617,7 @@ "Buy link": "Nunua kiungo", "Buy links are allowed from the following domains": "Viungo vya kununua vinaruhusiwa kutoka kwa vikoa vifuatavyo", "Media license": "Leseni ya media", - "Media creator": "Muundaji wa media" + "Media creator": "Muundaji wa media", + "Import Blocks": "Ingiza Matukio Yaliyozuiwa", + "Export Blocks": "Hamisha Matukio Yaliyozuiwa" } diff --git a/translations/tr.json b/translations/tr.json index b6a480bde..a6e84aab7 100644 --- a/translations/tr.json +++ b/translations/tr.json @@ -617,5 +617,7 @@ "Buy link": "Bağlantı satın al", "Buy links are allowed from the following domains": "Aşağıdaki alanlardan satın alma bağlantılarına izin verilir", "Media license": "Medya lisansı", - "Media creator": "Medya yaratıcısı" + "Media creator": "Medya yaratıcısı", + "Import Blocks": "Engellenen Örnekleri İçe Aktar", + "Export Blocks": "Engellenen Örnekleri Dışa Aktar" } diff --git a/translations/uk.json b/translations/uk.json index bbecd07ac..42f0d4ae6 100644 --- a/translations/uk.json +++ b/translations/uk.json @@ -617,5 +617,7 @@ "Buy link": "Купити посилання", "Buy links are allowed from the following domains": "Посилання на купівлю дозволено з таких доменів", "Media license": "Медіа ліцензія", - "Media creator": "Творець медіа" + "Media creator": "Творець медіа", + "Import Blocks": "Імпортувати заблоковані екземпляри", + "Export Blocks": "Експортувати заблоковані екземпляри" } diff --git a/translations/yi.json b/translations/yi.json index acf8981ba..b1214f9b1 100644 --- a/translations/yi.json +++ b/translations/yi.json @@ -617,5 +617,7 @@ "Buy link": "קויפן לינק", "Buy links are allowed from the following domains": "קויפן פֿאַרבינדונגען זענען ערלויבט פֿון די פאלגענדע דאָומיינז", "Media license": "מעדיע דערלויבעניש", - "Media creator": "מעדיע באשעפער" + "Media creator": "מעדיע באשעפער", + "Import Blocks": "ימפּאָרט בלאַקט ינסטאַנסיז", + "Export Blocks": "עקספּאָרט בלאַקט ינסטאַנסיז" } diff --git a/translations/zh.json b/translations/zh.json index 9a88921a4..df2228367 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -617,5 +617,7 @@ "Buy link": "购买链接", "Buy links are allowed from the following domains": "允许来自以下域的购买链接", "Media license": "媒体许可证", - "Media creator": "媒体创作者" + "Media creator": "媒体创作者", + "Import Blocks": "导入被阻止的实例", + "Export Blocks": "导出被阻止的实例" } diff --git a/webapp_profile.py b/webapp_profile.py index aee6c8bb3..9d85fdc41 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -92,6 +92,7 @@ from roles import is_devops from session import site_is_verified THEME_FORMATS = '.zip, .gz' +BLOCKFILE_FORMATS = '.csv' def _valid_profile_preview_post(post_json_object: {}, @@ -2043,6 +2044,20 @@ def _html_edit_profile_filtering(base_dir: str, nickname: str, domain: str, edit_text_area(translate['Blocked accounts'], None, 'blocked', blocked_str, 200, '', False) + # import and export blocks + edit_profile_form += \ + ' \n' + edit_profile_form += ' \n' + edit_profile_form += \ + '
\n' + edit_profile_form += \ + '
\n' + idx = 'Direct messages are always allowed from these instances.' edit_profile_form += \ edit_text_area(translate['Direct Message permitted instances'], None, From daea7de461de9a7883d410b41cea78c0d1ff2d6f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 10 Feb 2023 13:08:41 +0000 Subject: [PATCH 04/14] Export blocked domains as csv --- blocking.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ daemon.py | 40 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/blocking.py b/blocking.py index 3b254d086..3b2ac7cef 100644 --- a/blocking.py +++ b/blocking.py @@ -1558,3 +1558,53 @@ def import_blocks(base_dir: str, nickname: str, domain: str, blocking_reasons_filename) return True + + +def export_blocks(base_dir: str, nickname: str, domain: str) -> str: + """exports account level blocks in a csv format + """ + account_directory = acct_dir(base_dir, nickname, domain) + blocking_filename = \ + account_directory + '/blocking.txt' + blocking_reasons_filename = \ + account_directory + '/blocking_reasons.txt' + + blocks_header = \ + '#domain,#severity,#reject_media,#reject_reports,' + \ + '#public_comment,#obfuscate\n' + + if not os.path.isfile(blocking_filename): + return blocks_header + + blocking_lines = [] + if os.path.isfile(blocking_filename): + try: + with open(blocking_filename, 'r', encoding='utf-8') as fp_block: + blocking_lines = fp_block.read().splitlines() + except OSError: + print('EX: export_blocks failed to read ' + blocking_filename) + + blocking_reasons = [] + if os.path.isfile(blocking_reasons_filename): + try: + with open(blocking_reasons_filename, 'r', + encoding='utf-8') as fp_block: + blocking_reasons = fp_block.read().splitlines() + except OSError: + print('EX: export_blocks failed to read ' + + blocking_reasons_filename) + + blocks_str = blocks_header + for blocked_domain in blocking_lines: + blocked_domain = blocked_domain.strip() + if blocked_domain.startwith('#'): + continue + reason_str = '' + for reason_line in blocking_reasons: + if reason_line.startswith(blocked_domain + ' '): + reason_str = reason_line.split(' ')[1] + break + blocks_str += \ + blocked_domain + ',suspend,false,false,"' + \ + reason_str + '",false\n' + return blocks_str diff --git a/daemon.py b/daemon.py index 5f72edc44..9879b592d 100644 --- a/daemon.py +++ b/daemon.py @@ -148,6 +148,7 @@ from media import attach_media from media import path_is_video from media import path_is_audio from blocking import import_blocks +from blocking import export_blocks from blocking import add_account_blocks from blocking import get_cw_list_variable from blocking import load_cw_lists @@ -6341,6 +6342,14 @@ class PubServer(BaseHTTPRequestHandler): cookie, calling_domain) self.server.postreq_busy = False return + elif 'name="submitExportBlocks"' in post_bytes_str: + print('submitExportBlocks') + blocks_download_path = actor_str + '/exports/blocks.csv' + print('submitExportBlocks path=' + blocks_download_path) + self._redirect_headers(blocks_download_path, + cookie, calling_domain) + self.server.postreq_busy = False + return # extract all of the text fields into a dict fields = \ @@ -8388,6 +8397,25 @@ class PubServer(BaseHTTPRequestHandler): self._write(export_binary) self._404() + def _get_exported_blocks(self, path: str, base_dir: str, + domain: str, + calling_domain: str) -> None: + """Returns an exported blocks csv file + """ + filename = path.split('/exports/', 1)[1] + filename = base_dir + '/exports/' + filename + nickname = get_nickname_from_actor(path) + if nickname: + blocks_str = export_blocks(base_dir, nickname, domain) + if blocks_str: + msg = blocks_str.encode('utf-8') + msglen = len(msg) + self._set_headers('text/csv', + msglen, None, calling_domain, False) + self._write(msg) + return + self._404() + def _get_fonts(self, calling_domain: str, path: str, base_dir: str, debug: bool, getreq_start_time) -> None: @@ -17318,9 +17346,15 @@ class PubServer(BaseHTTPRequestHandler): return if authorized and '/exports/' in self.path: - self._get_exported_theme(self.path, - self.server.base_dir, - self.server.domain_full) + if 'blocks.csv' in self.path: + self._get_exported_blocks(self.path, + self.server.base_dir, + self.server.domain, + calling_domain) + else: + self._get_exported_theme(self.path, + self.server.base_dir, + self.server.domain_full) return # get fonts From 63a313eb96aa3e69ddf6d2c4b1d5458c604317cb Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 10 Feb 2023 13:13:05 +0000 Subject: [PATCH 05/14] Typo --- blocking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocking.py b/blocking.py index 3b2ac7cef..693c9ce10 100644 --- a/blocking.py +++ b/blocking.py @@ -1597,7 +1597,7 @@ def export_blocks(base_dir: str, nickname: str, domain: str) -> str: blocks_str = blocks_header for blocked_domain in blocking_lines: blocked_domain = blocked_domain.strip() - if blocked_domain.startwith('#'): + if blocked_domain.startswith('#'): continue reason_str = '' for reason_line in blocking_reasons: From 8198daa3e526de6a16bca72f28639c097f1c2001 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 10 Feb 2023 13:16:13 +0000 Subject: [PATCH 06/14] Only split once --- blocking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocking.py b/blocking.py index 693c9ce10..5e184a292 100644 --- a/blocking.py +++ b/blocking.py @@ -1602,7 +1602,7 @@ def export_blocks(base_dir: str, nickname: str, domain: str) -> str: reason_str = '' for reason_line in blocking_reasons: if reason_line.startswith(blocked_domain + ' '): - reason_str = reason_line.split(' ')[1] + reason_str = reason_line.split(' ', 1)[1] break blocks_str += \ blocked_domain + ',suspend,false,false,"' + \ From f9384492f74920293e16bff19e19ba7060a7ca09 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 10 Feb 2023 13:38:29 +0000 Subject: [PATCH 07/14] Improve handling of quotes within csv file --- blocking.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/blocking.py b/blocking.py index 5e184a292..e42b3bfac 100644 --- a/blocking.py +++ b/blocking.py @@ -1530,11 +1530,22 @@ def import_blocks(base_dir: str, nickname: str, domain: str, # already blocked continue append_blocks.append(blocked_domain_name) - blocked_comment = block_fields[comment_field_index].strip() - if blocked_comment: - if blocked_comment not in existing_reasons: + blocked_comment = '' + if '"' in line_str: + quote_section = line_str.split('"') + if len(quote_section) > 1: + blocked_comment = quote_section[1] append_reasons.append(blocked_domain_name + ' ' + blocked_comment) + if not blocked_comment: + if len(block_fields) > comment_field_index: + blocked_comment = block_fields[comment_field_index].strip() + if blocked_comment: + if blocked_comment.startswith('"'): + blocked_comment = blocked_comment.replace('"', '') + if blocked_comment not in existing_reasons: + append_reasons.append(blocked_domain_name + ' ' + + blocked_comment) if not append_blocks: return True From 1fe000adb1d0d5b9c0d1dc4a60e543eafe1feba9 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 10 Feb 2023 13:52:07 +0000 Subject: [PATCH 08/14] Import blocks --- daemon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index 9879b592d..af5bdd6cd 100644 --- a/daemon.py +++ b/daemon.py @@ -6255,7 +6255,7 @@ class PubServer(BaseHTTPRequestHandler): if os.path.isfile(filename_base): blocks_import_succeeded = False if import_blocks(base_dir, nickname, domain, - filename_base): + filename): print(nickname + ' imported blocks csv') blocks_import_succeeded = True try: From 507085494ee6e3703a66b02d83bbd951f0b74791 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 10 Feb 2023 17:04:26 +0000 Subject: [PATCH 09/14] import variable names --- daemon.py | 18 +++++++++--------- webapp_profile.py | 6 +++--- webapp_theme_designer.py | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/daemon.py b/daemon.py index af5bdd6cd..b478552f2 100644 --- a/daemon.py +++ b/daemon.py @@ -6173,9 +6173,9 @@ class PubServer(BaseHTTPRequestHandler): 'banner', 'search_banner', 'instanceLogo', 'left_col_image', 'right_col_image', - 'submitImportFollows', - 'submitImportBlocks', - 'submitImportTheme' + 'import_follows', + 'import_blocks', + 'import_theme' ) profile_media_types_uploaded = {} for m_type in profile_media_types: @@ -6208,7 +6208,7 @@ class PubServer(BaseHTTPRequestHandler): if m_type == 'instanceLogo': filename_base = \ base_dir + '/accounts/login.temp' - elif m_type == 'submitImportTheme': + elif m_type == 'import_theme': if not os.path.isdir(base_dir + '/imports'): os.mkdir(base_dir + '/imports') filename_base = \ @@ -6219,11 +6219,11 @@ class PubServer(BaseHTTPRequestHandler): except OSError: print('EX: _profile_edit unable to delete ' + filename_base) - elif m_type == 'submitImportFollows': + elif m_type == 'import_follows': filename_base = \ acct_dir(base_dir, nickname, domain) + \ '/import_following.csv' - elif m_type == 'submitImportBlocks': + elif m_type == 'import_blocks': filename_base = \ acct_dir(base_dir, nickname, domain) + \ '/import_blocks.csv' @@ -6243,7 +6243,7 @@ class PubServer(BaseHTTPRequestHandler): ' media, zip, csv or font filename in POST') continue - if m_type == 'submitImportFollows': + if m_type == 'import_follows': if os.path.isfile(filename_base): print(nickname + ' imported follows csv') else: @@ -6251,7 +6251,7 @@ class PubServer(BaseHTTPRequestHandler): nickname) continue - if m_type == 'submitImportBlocks': + if m_type == 'import_blocks': if os.path.isfile(filename_base): blocks_import_succeeded = False if import_blocks(base_dir, nickname, domain, @@ -6270,7 +6270,7 @@ class PubServer(BaseHTTPRequestHandler): nickname) continue - if m_type == 'submitImportTheme': + if m_type == 'import_theme': if nickname == admin_nickname or \ is_artist(base_dir, nickname): if import_theme(base_dir, filename): diff --git a/webapp_profile.py b/webapp_profile.py index 9d85fdc41..e4dc1114d 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -1540,7 +1540,7 @@ def _html_edit_profile_graphic_design(base_dir: str, translate: {}) -> str: ' \n' graphics_str += ' \n' graphics_str += \ '