Language mapped preferred username

main
bashrc 2026-05-08 10:34:31 +01:00
parent 480544debb
commit e39a73b625
12 changed files with 69 additions and 28 deletions

View File

@ -453,7 +453,8 @@ def daemon_http_get(self) -> None:
if show_vcard(self, self.server.base_dir,
self.path, calling_domain, referer_domain,
self.server.domain, self.server.translate):
self.server.domain, self.server.translate,
self.server.system_language):
return
# getting the public key for an account

View File

@ -22,7 +22,8 @@ from data import is_a_file
def show_vcard(self, base_dir: str, path: str, calling_domain: str,
referer_domain: str, domain: str, translate: {}) -> bool:
referer_domain: str, domain: str, translate: {},
system_language: str) -> bool:
"""Returns a vcard for the given account
"""
if not has_accept(self, calling_domain):
@ -68,10 +69,12 @@ def show_vcard(self, base_dir: str, path: str, calling_domain: str,
self.server.vcard_is_active = False
return True
if 'application/vcard+xml' in accept_str:
vcard_str = actor_to_vcard_xml(actor_json, domain, translate)
vcard_str = \
actor_to_vcard_xml(actor_json, domain, translate, system_language)
header_type = 'application/vcard+xml; charset=utf-8'
else:
vcard_str = actor_to_vcard(actor_json, domain, translate)
vcard_str = \
actor_to_vcard(actor_json, domain, translate, system_language)
header_type = 'text/vcard; charset=utf-8'
if vcard_str:
msg = vcard_str.encode('utf-8')

View File

@ -180,7 +180,8 @@ def _profile_post_save_actor(base_dir: str, http_prefix: str,
curr_session, proxy_type: str,
send_move_activity: bool,
self, cached_webfingers: {},
person_cache: {}, project_version: str) -> None:
person_cache: {}, project_version: str,
system_language: str) -> None:
""" HTTP POST save actor json file within accounts
"""
add_name_emojis_to_tags(base_dir, http_prefix,
@ -198,7 +199,7 @@ def _profile_post_save_actor(base_dir: str, http_prefix: str,
actor_json['featured'] = actor_json['id'] + '/collections/featured'
if not actor_json.get('featuredTags'):
actor_json['featuredTags'] = actor_json['id'] + '/collections/tags'
randomize_actor_images(actor_json)
randomize_actor_images(actor_json, system_language)
add_actor_update_timestamp(actor_json)
# save the actor
save_json(actor_json, actor_filename)
@ -3361,7 +3362,8 @@ def profile_edit(self, calling_domain: str, cookie: str,
curr_session, proxy_type,
send_move_activity,
self, cached_webfingers,
person_cache, project_version)
person_cache, project_version,
system_language)
if _profile_post_deactivate_account(base_dir, nickname, domain,
calling_domain,

View File

@ -21,6 +21,7 @@ from utils import lines_in_file
from utils import data_dir
from utils import account_is_indexable
from utils import is_yggdrasil_address
from utils import get_preferred_username
from data import load_list
from data import load_string
from data import is_a_file
@ -75,9 +76,8 @@ def _meta_data_instance_v1(show_accounts: bool,
elif admin_actor['type'] != 'Person':
is_bot = True
url = \
http_prefix + '://' + domain_full + '/@' + \
admin_actor['preferredUsername']
preferred_username = get_preferred_username(admin_actor, system_language)
url = http_prefix + '://' + domain_full + '/@' + preferred_username
if show_accounts:
active_accounts: int = no_of_accounts(base_dir)
@ -112,7 +112,7 @@ def _meta_data_instance_v1(show_accounts: bool,
'locked': admin_actor['manuallyApprovesFollowers'],
'note': '<p>Admin of ' + domain + '</p>',
'url': url,
'username': admin_actor['preferredUsername']
'username': preferred_username
},
'description': instance_description,
'languages': [system_language],

View File

@ -19,6 +19,7 @@ from utils import lines_in_file
from utils import data_dir
from utils import account_is_indexable
from utils import is_yggdrasil_address
from utils import get_preferred_username
from formats import get_image_mime_type
from formats import get_image_extensions
from formats import get_audio_extensions
@ -82,9 +83,8 @@ def _meta_data_instance_v2(show_accounts: bool,
elif admin_actor['type'] != 'Person':
is_bot = True
url = \
http_prefix + '://' + domain_full + '/@' + \
admin_actor['preferredUsername']
preferred_username = get_preferred_username(admin_actor, system_language)
url = http_prefix + '://' + domain_full + '/@' + preferred_username
if show_accounts:
active_accounts: int = no_of_accounts(base_dir)

View File

@ -40,6 +40,7 @@ from media import process_meta_data
from flags import is_image_file
from timeFunctions import date_utcnow
from timeFunctions import get_current_time_int
from utils import get_preferred_username
from utils import string_starts_with
from utils import is_yggdrasil_address
from utils import get_person_icon
@ -201,7 +202,7 @@ def _account_exists(base_dir: str, nickname: str, domain: str) -> bool:
is_a_dir(base_dir + '/deactivated/' + nickname + '@' + domain)
def randomize_actor_images(person_json: {}) -> None:
def randomize_actor_images(person_json: {}, system_language: str) -> None:
"""Randomizes the filenames for avatar image and background
This causes other instances to update their cached avatar image
"""
@ -213,7 +214,7 @@ def randomize_actor_images(person_json: {}) -> None:
# secure names
rand_str = str(randint(10000000000000, 99999999999999)) # nosec
base_url = person_id.split('/users/')[0]
nickname = person_json['preferredUsername']
nickname = get_preferred_username(person_json, system_language)
person_json['icon']['url'] = \
base_url + '/system/accounts/avatars/' + nickname + \
'/avatar' + rand_str + '.' + existing_extension
@ -246,7 +247,7 @@ def get_actor_update_json(actor_json: {}) -> {}:
if actor_json.get('attributionDomains'):
if isinstance(actor_json['attributionDomains'], list):
attribution_domains = actor_json['attributionDomains']
return {
actor_update: dict = {
'@context': [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
@ -362,6 +363,10 @@ def get_actor_update_json(actor_json: {}) -> {}:
"publicKey": actor_json['publicKey']
}
}
if 'preferredUsernameMap' in actor_json:
actor_update['preferredUsernameMap'] = \
actor_json['preferredUsernameMap']
return actor_update
def get_actor_move_json(actor_json: {}) -> {}:
@ -2175,6 +2180,14 @@ def valid_sending_actor(session, base_dir: str,
sending_actor + ' ' + bio_str)
return False
bio_str += ' ' + remove_html(actor_json['preferredUsername'])
# include the username map
if 'preferredUsernameMap' in actor_json:
username_map = actor_json['preferredUsernameMap']
if isinstance(username_map, dict):
for _, preferred_username in username_map.items():
if not isinstance(preferred_username, str):
continue
bio_str += ' ' + remove_html(preferred_username)
if actor_json.get('attachment'):
if isinstance(actor_json['attachment'], list):

18
pgp.py
View File

@ -14,6 +14,7 @@ from person import get_actor_json
from flags import is_pgp_encrypted
from flags import contains_pgp_public_key
from occupation import get_occupation_skills
from utils import get_preferred_username
from utils import get_url_from_post
from utils import safe_system_string
from utils import get_full_domain
@ -889,15 +890,17 @@ def pgp_public_key_upload(base_dir: str, session,
return actor_update
def actor_to_vcard(actor: {}, domain: str, translate: {}) -> str:
def actor_to_vcard(actor: {}, domain: str, translate: {},
system_language: str) -> str:
"""Returns a vcard for a given actor
"""
actor_url_str = get_url_from_post(actor['url'])
preferred_username = get_preferred_username(actor, system_language)
vcard_str = 'BEGIN:VCARD\n'
vcard_str += 'VERSION:4.0\n'
vcard_str += 'REV:' + actor['published'] + '\n'
vcard_str += 'FN:' + remove_html(actor['name']) + '\n'
vcard_str += 'NICKNAME:' + actor['preferredUsername'] + '\n'
vcard_str += 'NICKNAME:' + preferred_username + '\n'
vcard_str += 'NOTE:' + remove_html(actor['summary']) + '\n'
url_str = get_url_from_post(actor['icon']['url'])
if url_str:
@ -909,8 +912,7 @@ def actor_to_vcard(actor: {}, domain: str, translate: {}) -> str:
email_address = get_email_address(actor)
if email_address:
vcard_str += 'EMAIL;TYPE=internet:' + email_address + '\n'
vcard_str += 'IMPP:fediverse:' + \
actor['preferredUsername'] + '@' + domain + '\n'
vcard_str += 'IMPP:fediverse:' + preferred_username + '@' + domain + '\n'
if actor.get('vcard:bday'):
birthday_str = actor['vcard:bday']
if '-' in birthday_str:
@ -1004,16 +1006,18 @@ def actor_to_vcard(actor: {}, domain: str, translate: {}) -> str:
return vcard_str
def actor_to_vcard_xml(actor: {}, domain: str, translate: {}) -> str:
def actor_to_vcard_xml(actor: {}, domain: str, translate: {},
system_language: str) -> str:
"""Returns a xml formatted vcard for a given actor
"""
preferred_username = get_preferred_username(actor, system_language)
vcard_str = '<?xml version="1.0" encoding="UTF-8"?>\n'
vcard_str += '<vcards xmlns="urn:ietf:params:xml:ns:vcard-4.0">\n'
vcard_str += ' <vcard>\n'
vcard_str += ' <fn><text>' + \
remove_html(actor['name']) + '</text></fn>\n'
vcard_str += ' <nickname><text>' + \
actor['preferredUsername'] + '</text></nickname>\n'
preferred_username + '</text></nickname>\n'
vcard_str += ' <note><text>' + \
remove_html(actor['summary']) + '</text></note>\n'
email_address = get_email_address(actor)
@ -1021,7 +1025,7 @@ def actor_to_vcard_xml(actor: {}, domain: str, translate: {}) -> str:
vcard_str += ' <email><text>' + email_address + '</text></email>\n'
vcard_str += ' <impp>' + \
'<parameters><type><text>fediverse</text></type></parameters>' + \
'<text>' + actor['preferredUsername'] + '@' + domain + \
'<text>' + preferred_username + '@' + domain + \
'</text></impp>\n'
if actor.get('vcard:bday'):
birthday_str = actor['vcard:bday']

View File

@ -5227,6 +5227,7 @@ def _novel_fields_for_person(nickname: str, domain: str,
'name',
'outbox',
'preferredUsername',
'preferredUsernameMap',
'publicKey',
'summary',
'tag',

View File

@ -4343,3 +4343,16 @@ def is_private_browser(ua_str: str) -> bool:
('librewolf', 'privacy', 'private')):
return True
return False
def get_preferred_username(actor: {}, system_language: str) -> str:
"""Returns the preferred username from the given actor
"""
if 'preferredUsernameMap' in actor:
if isinstance(actor['preferredUsernameMap'], dict):
if actor['preferredUsernameMap'].get(system_language):
username: str = \
actor['preferredUsernameMap'][system_language]
if isinstance(username, str):
return username
return actor['preferredUsername']

View File

@ -11,6 +11,7 @@ from flags import is_system_account
from utils import get_mutuals_of_person
from utils import get_domain_from_actor
from utils import get_config_param
from utils import get_preferred_username
from timeFunctions import get_account_timezone
from person import person_box_json
from webapp_utils import html_header_with_external_style
@ -161,7 +162,7 @@ def html_front_screen(signing_priv_key_pem: str,
"""Show the news instance front screen
"""
bold_reading: bool = False
nickname = profile_json['preferredUsername']
nickname: str = get_preferred_username(profile_json, system_language)
if not nickname:
return ""
if not is_system_account(nickname):
@ -169,7 +170,7 @@ def html_front_screen(signing_priv_key_pem: str,
domain, port = get_domain_from_actor(profile_json['id'])
if not domain:
return ""
domain_full = domain
domain_full: str = domain
if port:
domain_full = domain + ':' + str(port)

View File

@ -22,6 +22,7 @@ from textmode import text_mode_removals
from unicodetext import uninvert_text
from unicodetext import standardize_text
from occupation import get_occupation_name
from utils import get_preferred_username
from utils import is_private_browser
from utils import replace_embedded_map_with_link
from utils import is_yggdrasil_address
@ -1198,7 +1199,7 @@ def html_profile(signing_priv_key_pem: str,
if is_a_file(moved_accounts_filename):
show_moved_accounts = True
nickname: str = profile_json['preferredUsername']
nickname: str = get_preferred_username(profile_json, system_language)
if not nickname:
return ""
if is_system_account(nickname):

View File

@ -15,6 +15,7 @@ from session import get_json_valid
from flags import is_float
from flags import is_moderator
from formats import media_file_mime_type
from utils import get_preferred_username
from utils import replace_embedded_map_with_link
from utils import chatbot_nicknames
from utils import replace_strings
@ -901,7 +902,8 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
description = remove_html(actor_json['summary'])
name_str: str = remove_html(actor_json['name'])
domain_full: str = actor_json['id'].split('://')[1].split('/')[0]
handle: str = actor_json['preferredUsername'] + '@' + domain_full
handle: str = \
get_preferred_username(actor_json, lang) + '@' + domain_full
url_str: str = get_url_from_post(actor_json['icon']['url'])
icon_url: str = remove_html(url_str)