Bob Mottram 2023-02-10 20:14:53 +00:00
commit d242738229
37 changed files with 429 additions and 67 deletions

View File

@ -1460,3 +1460,155 @@ 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_blocking_file(base_dir: str, nickname: str, domain: str,
lines: []) -> bool:
"""Imports blocked domains for a given account
"""
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 = ''
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
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
def export_blocking_file(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.startswith('#'):
continue
reason_str = ''
for reason_line in blocking_reasons:
if reason_line.startswith(blocked_domain + ' '):
reason_str = reason_line.split(' ', 1)[1]
break
blocks_str += \
blocked_domain + ',suspend,false,false,"' + \
reason_str + '",false\n'
return blocks_str

View File

@ -1705,7 +1705,8 @@ def extract_text_fields_in_post(post_bytes, boundary: str, debug: bool,
fields_with_semicolon_allowed = (
'message', 'bio', 'autoCW', 'password', 'passwordconfirm',
'instanceDescription', 'instanceDescriptionShort',
'subject', 'location', 'imageDescription'
'subject', 'location', 'imageDescription', 'importBlocks',
'importFollows', 'importTheme'
)
if debug:
if 'password' not in message_fields:

100
daemon.py
View File

@ -147,6 +147,8 @@ 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_blocking_file
from blocking import export_blocking_file
from blocking import add_account_blocks
from blocking import get_cw_list_variable
from blocking import load_cw_lists
@ -6163,6 +6165,9 @@ class PubServer(BaseHTTPRequestHandler):
if b'--LYNX' in post_bytes:
boundary = '--LYNX'
if debug:
print('post_bytes: ' + str(post_bytes))
if boundary:
# get the various avatar, banner and background images
actor_changed = True
@ -6171,8 +6176,8 @@ class PubServer(BaseHTTPRequestHandler):
'banner', 'search_banner',
'instanceLogo',
'left_col_image', 'right_col_image',
'submitImportFollows',
'submitImportTheme'
'importFollows',
'importTheme'
)
profile_media_types_uploaded = {}
for m_type in profile_media_types:
@ -6205,7 +6210,7 @@ class PubServer(BaseHTTPRequestHandler):
if m_type == 'instanceLogo':
filename_base = \
base_dir + '/accounts/login.temp'
elif m_type == 'submitImportTheme':
elif m_type == 'importTheme':
if not os.path.isdir(base_dir + '/imports'):
os.mkdir(base_dir + '/imports')
filename_base = \
@ -6216,7 +6221,7 @@ class PubServer(BaseHTTPRequestHandler):
except OSError:
print('EX: _profile_edit unable to delete ' +
filename_base)
elif m_type == 'submitImportFollows':
elif m_type == 'importFollows':
filename_base = \
acct_dir(base_dir, nickname, domain) + \
'/import_following.csv'
@ -6236,7 +6241,7 @@ class PubServer(BaseHTTPRequestHandler):
' media, zip, csv or font filename in POST')
continue
if m_type == 'submitImportFollows':
if m_type == 'importFollows':
if os.path.isfile(filename_base):
print(nickname + ' imported follows csv')
else:
@ -6244,7 +6249,7 @@ class PubServer(BaseHTTPRequestHandler):
nickname)
continue
if m_type == 'submitImportTheme':
if m_type == 'importTheme':
if nickname == admin_nickname or \
is_artist(base_dir, nickname):
if import_theme(base_dir, filename):
@ -6316,6 +6321,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 = \
@ -7807,6 +7820,50 @@ class PubServer(BaseHTTPRequestHandler):
else:
add_account_blocks(base_dir,
nickname, domain, '')
# import blocks from csv file
if fields.get('importBlocks'):
blocks_str = fields['importBlocks']
while blocks_str.startswith('\n'):
blocks_str = blocks_str[1:]
blocks_lines = blocks_str.split('\n')
if import_blocking_file(base_dir, nickname, domain,
blocks_lines):
print('blocks imported for ' + nickname)
else:
print('blocks not imported for ' + nickname)
if fields.get('importFollows'):
filename_base = \
acct_dir(base_dir, nickname, domain) + \
'/import_following.csv'
follows_str = fields['importFollows']
while follows_str.startswith('\n'):
follows_str = follows_str[1:]
try:
with open(filename_base, 'w+',
encoding='utf-8') as fp_foll:
fp_foll.write(follows_str)
except OSError:
print('EX: unable to write imported follows ' +
filename_base)
if fields.get('importTheme'):
if not os.path.isdir(base_dir + '/imports'):
os.mkdir(base_dir + '/imports')
filename_base = \
base_dir + '/imports/newtheme.zip'
if os.path.isfile(filename_base):
try:
os.remove(filename_base)
except OSError:
print('EX: _profile_edit unable to delete ' +
filename_base)
if nickname == admin_nickname or \
is_artist(base_dir, nickname):
if import_theme(base_dir, filename_base):
print(nickname + ' uploaded a theme')
else:
print('Only admin or artist can import a theme')
# Save DM allowed instances list.
# The allow list for incoming DMs,
@ -8363,6 +8420,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_blocking_file(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:
@ -17293,9 +17369,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

View File

@ -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);
}

View File

@ -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:

View File

@ -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:

View File

@ -5995,7 +5995,17 @@ def _test_extract_text_fields_from_post():
'116202748023898664511855843036\r\nContent-Disposition: ' + \
'form-data; name="attachpic"; filename=""\r\nContent-Type: ' + \
'application/octet-stream\r\n\r\n\r\n----------------------' + \
'-------116202748023898664511855843036--\r\n'
'-------116202748023898664511855843036--\r\n' + \
'Content-Disposition: form-data; name="importBlocks"; ' + \
'filename="wildebeest_suspend.csv"\r\nContent-Type: ' + \
'text/csv\r\n\r\n#domain,#severity,#reject_media,#reject_reports,' + \
'#public_comment,#obfuscate\nbgp.social,suspend,false,false,' + \
'"Wildebeest",false\ncesko.social,suspend,false,false,' + \
'"Wildebeest",false\ncloudflare.social,suspend,false,false,' + \
'"Wildebeest",false\ndogfood.social,suspend,false,false,' + \
'"Wildebeest",false\ndomo.cafe,suspend,false,false,"Wildebeest",' + \
'false\nemaw.social,suspend,false,false\n\r\n ' + \
'-----------------------------116202748023898664511855843036--\r\n'
debug = False
fields = extract_text_fields_in_post(None, boundary, debug, form_data)
assert fields['submitPost'] == 'Submit'
@ -6006,6 +6016,9 @@ def _test_extract_text_fields_from_post():
assert fields['location'] == ''
assert fields['imageDescription'] == ''
assert fields['message'] == 'This is a ; test'
if not fields['importBlocks'][1:].startswith('#domain,#severity,'):
print(fields['importBlocks'])
assert fields['importBlocks'][1:].startswith('#domain,#severity,')
def _test_speaker_replace_link():

View File

@ -617,5 +617,7 @@
"Buy link": "رابط شراء",
"Buy links are allowed from the following domains": "روابط الشراء مسموح بها من المجالات التالية",
"Media license": "رخصة وسائل الإعلام",
"Media creator": "صانع الوسائط"
"Media creator": "صانع الوسائط",
"Import Blocks": "استيراد مثيلات محظورة",
"Export Blocks": "تصدير المثيلات المحظورة"
}

View File

@ -617,5 +617,7 @@
"Buy link": "সংযোগ কেনা",
"Buy links are allowed from the following domains": "নিম্নলিখিত ডোমেনগুলি থেকে লিঙ্কগুলি কেনার অনুমতি দেওয়া হয়েছে",
"Media license": "মিডিয়া লাইসেন্স",
"Media creator": "মিডিয়া নির্মাতা"
"Media creator": "মিডিয়া নির্মাতা",
"Import Blocks": "অবরুদ্ধ দৃষ্টান্ত আমদানি করুন",
"Export Blocks": "অবরুদ্ধ দৃষ্টান্ত রপ্তানি করুন"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -617,5 +617,7 @@
"Buy link": "Σύνδεσμος αγοράς",
"Buy links are allowed from the following domains": "Οι σύνδεσμοι αγοράς επιτρέπονται από τους παρακάτω τομείς",
"Media license": "Άδεια ΜΜΕ",
"Media creator": "Δημιουργός πολυμέσων"
"Media creator": "Δημιουργός πολυμέσων",
"Import Blocks": "Εισαγωγή αποκλεισμένων παρουσιών",
"Export Blocks": "Εξαγωγή αποκλεισμένων παρουσιών"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -617,5 +617,7 @@
"Buy link": "لینک خرید",
"Buy links are allowed from the following domains": "لینک خرید از دامنه های زیر مجاز است",
"Media license": "مجوز رسانه",
"Media creator": "سازنده رسانه"
"Media creator": "سازنده رسانه",
"Import Blocks": "وارد کردن موارد مسدود شده",
"Export Blocks": "نمونه های مسدود شده را صادر کنید"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -617,5 +617,7 @@
"Buy link": "लिंक खरीदें",
"Buy links are allowed from the following domains": "निम्नलिखित डोमेन से खरीदें लिंक की अनुमति है",
"Media license": "मीडिया लाइसेंस",
"Media creator": "मीडिया निर्माता"
"Media creator": "मीडिया निर्माता",
"Import Blocks": "अवरोधित उदाहरण आयात करें",
"Export Blocks": "निर्यात अवरुद्ध उदाहरण"
}

View File

@ -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"
}

View File

@ -617,5 +617,7 @@
"Buy link": "購入リンク",
"Buy links are allowed from the following domains": "次のドメインからの購入リンクが許可されています",
"Media license": "メディアライセンス",
"Media creator": "メディアクリエーター"
"Media creator": "メディアクリエーター",
"Import Blocks": "ブロックされたインスタンスのインポート",
"Export Blocks": "ブロックされたインスタンスのエクスポート"
}

View File

@ -617,5 +617,7 @@
"Buy link": "구매 링크",
"Buy links are allowed from the following domains": "다음 도메인에서 구매 링크가 허용됩니다.",
"Media license": "미디어 라이센스",
"Media creator": "미디어 크리에이터"
"Media creator": "미디어 크리에이터",
"Import Blocks": "차단된 인스턴스 가져오기",
"Export Blocks": "차단된 인스턴스 내보내기"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -617,5 +617,7 @@
"Buy link": "Купить ссылку",
"Buy links are allowed from the following domains": "Ссылки на покупку разрешены со следующих доменов",
"Media license": "Медиа лицензия",
"Media creator": "Создатель медиа"
"Media creator": "Создатель медиа",
"Import Blocks": "Импорт заблокированных экземпляров",
"Export Blocks": "Экспорт заблокированных экземпляров"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -617,5 +617,7 @@
"Buy link": "Купити посилання",
"Buy links are allowed from the following domains": "Посилання на купівлю дозволено з таких доменів",
"Media license": "Медіа ліцензія",
"Media creator": "Творець медіа"
"Media creator": "Творець медіа",
"Import Blocks": "Імпортувати заблоковані екземпляри",
"Export Blocks": "Експортувати заблоковані екземпляри"
}

View File

@ -617,5 +617,7 @@
"Buy link": "קויפן לינק",
"Buy links are allowed from the following domains": "קויפן פֿאַרבינדונגען זענען ערלויבט פֿון די פאלגענדע דאָומיינז",
"Media license": "מעדיע דערלויבעניש",
"Media creator": "מעדיע באשעפער"
"Media creator": "מעדיע באשעפער",
"Import Blocks": "ימפּאָרט בלאַקט ינסטאַנסיז",
"Export Blocks": "עקספּאָרט בלאַקט ינסטאַנסיז"
}

View File

@ -617,5 +617,7 @@
"Buy link": "购买链接",
"Buy links are allowed from the following domains": "允许来自以下域的购买链接",
"Media license": "媒体许可证",
"Media creator": "媒体创作者"
"Media creator": "媒体创作者",
"Import Blocks": "导入被阻止的实例",
"Export Blocks": "导出被阻止的实例"
}

View File

@ -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

View File

@ -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: {},
@ -1538,8 +1539,8 @@ def _html_edit_profile_graphic_design(base_dir: str, translate: {}) -> str:
graphics_str += \
' <label class="labels">' + \
translate['Import Theme'] + '</label>\n'
graphics_str += ' <input type="file" id="import_theme" '
graphics_str += 'name="submitImportTheme" '
graphics_str += ' <input type="file" id="importTheme" '
graphics_str += 'name="importTheme" '
graphics_str += 'accept="' + THEME_FORMATS + '">\n'
graphics_str += \
' <label class="labels">' + \
@ -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 += \
' <label class="labels">' + \
translate['Import Blocks'] + '</label>\n'
edit_profile_form += ' <input type="file" id="importBlocks" '
edit_profile_form += 'name="importBlocks" '
edit_profile_form += 'accept="' + BLOCKFILE_FORMATS + '">\n'
edit_profile_form += \
' <label class="labels">' + \
translate['Export Blocks'] + '</label><br>\n'
edit_profile_form += \
' <button type="submit" class="button" ' + \
'name="submitExportBlocks">➤</button><br>\n'
idx = 'Direct messages are always allowed from these instances.'
edit_profile_form += \
edit_text_area(translate['Direct Message permitted instances'], None,
@ -2266,8 +2281,8 @@ def _html_edit_profile_import_export(nickname: str, domain: str,
edit_profile_form += \
'<p><label class="labels">' + \
translate['Import Follows'] + '</label>\n'
edit_profile_form += '<input type="file" id="import_follows" '
edit_profile_form += 'name="submitImportFollows" '
edit_profile_form += '<input type="file" id="importFollows" '
edit_profile_form += 'name="importFollows" '
edit_profile_form += 'accept=".csv"></p>\n'
edit_profile_form += \

View File

@ -333,8 +333,8 @@ def html_theme_designer(base_dir: str,
export_import_str += \
' <label class="labels">' + \
translate['Import Theme'] + '</label>\n'
export_import_str += ' <input type="file" id="import_theme" '
export_import_str += 'name="submitImportTheme" '
export_import_str += ' <input type="file" id="importTheme" '
export_import_str += 'name="importTheme" '
export_import_str += 'accept="' + theme_formats + '">\n'
export_import_str += \
' <label class="labels">' + \

View File

@ -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