mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of gitlab.com:bashrc2/epicyon
commit
9fae915dd1
188
daemon.py
188
daemon.py
|
|
@ -415,6 +415,8 @@ from crawlers import load_known_web_bots
|
||||||
from qrcode import save_domain_qrcode
|
from qrcode import save_domain_qrcode
|
||||||
from importFollowing import run_import_following_watchdog
|
from importFollowing import run_import_following_watchdog
|
||||||
from maps import map_format_from_tagmaps_path
|
from maps import map_format_from_tagmaps_path
|
||||||
|
from relationships import get_moved_feed
|
||||||
|
from relationships import update_moved_actors
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3005,6 +3007,11 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
if '&' in options_actor:
|
if '&' in options_actor:
|
||||||
options_actor = options_actor.split('&')[0]
|
options_actor = options_actor.split('&')[0]
|
||||||
|
|
||||||
|
# actor for the movedTo
|
||||||
|
options_actor_moved = options_confirm_params.split('movedToActor=')[1]
|
||||||
|
if '&' in options_actor_moved:
|
||||||
|
options_actor_moved = options_actor_moved.split('&')[0]
|
||||||
|
|
||||||
# url of the avatar
|
# url of the avatar
|
||||||
options_avatar_url = options_confirm_params.split('avatarUrl=')[1]
|
options_avatar_url = options_confirm_params.split('avatarUrl=')[1]
|
||||||
if '&' in options_avatar_url:
|
if '&' in options_avatar_url:
|
||||||
|
|
@ -3412,6 +3419,25 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.postreq_busy = False
|
self.server.postreq_busy = False
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# person options screen, move button
|
||||||
|
# See html_person_options followStr
|
||||||
|
if '&submitMove=' in options_confirm_params:
|
||||||
|
if debug:
|
||||||
|
print('Moving ' + options_actor_moved)
|
||||||
|
msg = \
|
||||||
|
html_confirm_follow(self.server.translate,
|
||||||
|
base_dir,
|
||||||
|
users_path,
|
||||||
|
options_actor_moved,
|
||||||
|
options_avatar_url).encode('utf-8')
|
||||||
|
if msg:
|
||||||
|
msglen = len(msg)
|
||||||
|
self._set_headers('text/html', msglen,
|
||||||
|
cookie, calling_domain, False)
|
||||||
|
self._write(msg)
|
||||||
|
self.server.postreq_busy = False
|
||||||
|
return
|
||||||
|
|
||||||
# person options screen, unfollow button
|
# person options screen, unfollow button
|
||||||
# See html_person_options followStr
|
# See html_person_options followStr
|
||||||
if '&submitUnfollow=' in options_confirm_params or \
|
if '&submitUnfollow=' in options_confirm_params or \
|
||||||
|
|
@ -8383,7 +8409,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.news_instance,
|
self.server.news_instance,
|
||||||
authorized,
|
authorized,
|
||||||
access_keys, is_group,
|
access_keys, is_group,
|
||||||
self.server.theme_name)
|
self.server.theme_name,
|
||||||
|
self.server.blocked_cache)
|
||||||
if msg:
|
if msg:
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
|
|
@ -14363,6 +14390,142 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
return True
|
return True
|
||||||
return False
|
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_moved_feed(base_dir, domain, port, path,
|
||||||
|
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,
|
def _show_followers_feed(self, authorized: bool,
|
||||||
calling_domain: str, referer_domain: str,
|
calling_domain: str, referer_domain: str,
|
||||||
path: str, base_dir: str, http_prefix: str,
|
path: str, base_dir: str, http_prefix: str,
|
||||||
|
|
@ -19147,6 +19310,24 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
'_GET', 'show profile 3 done',
|
'_GET', 'show profile 3 done',
|
||||||
self.server.debug)
|
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,
|
if self._show_followers_feed(authorized,
|
||||||
calling_domain, referer_domain,
|
calling_domain, referer_domain,
|
||||||
self.path,
|
self.path,
|
||||||
|
|
@ -19162,7 +19343,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
return
|
return
|
||||||
|
|
||||||
fitness_performance(getreq_start_time, self.server.fitness,
|
fitness_performance(getreq_start_time, self.server.fitness,
|
||||||
'_GET', 'show profile 4 done',
|
'_GET', 'show profile 5 done',
|
||||||
self.server.debug)
|
self.server.debug)
|
||||||
|
|
||||||
# look up a person
|
# look up a person
|
||||||
|
|
@ -21922,6 +22103,8 @@ def run_daemon(max_hashtags: int,
|
||||||
print('Invalid domain: ' + domain)
|
print('Invalid domain: ' + domain)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
update_moved_actors(base_dir, debug)
|
||||||
|
|
||||||
if unit_test:
|
if unit_test:
|
||||||
server_address = (domain, proxy_port)
|
server_address = (domain, proxy_port)
|
||||||
pub_handler = partial(PubServerUnitTest)
|
pub_handler = partial(PubServerUnitTest)
|
||||||
|
|
@ -22018,6 +22201,7 @@ def run_daemon(max_hashtags: int,
|
||||||
'Page down': '.',
|
'Page down': '.',
|
||||||
'submitButton': 'y',
|
'submitButton': 'y',
|
||||||
'followButton': 'f',
|
'followButton': 'f',
|
||||||
|
'moveButton': 'm',
|
||||||
'blockButton': 'b',
|
'blockButton': 'b',
|
||||||
'infoButton': 'i',
|
'infoButton': 'i',
|
||||||
'snoozeButton': 's',
|
'snoozeButton': 's',
|
||||||
|
|
|
||||||
43
epicyon.py
43
epicyon.py
|
|
@ -111,6 +111,7 @@ from desktop_client import run_desktop_client
|
||||||
from happening import dav_month_via_server
|
from happening import dav_month_via_server
|
||||||
from happening import dav_day_via_server
|
from happening import dav_day_via_server
|
||||||
from content import import_emoji
|
from content import import_emoji
|
||||||
|
from relationships import get_moved_accounts
|
||||||
|
|
||||||
|
|
||||||
def str2bool(value_str) -> bool:
|
def str2bool(value_str) -> bool:
|
||||||
|
|
@ -343,6 +344,9 @@ def _command_options() -> None:
|
||||||
parser.add_argument('--posts', dest='posts', type=str,
|
parser.add_argument('--posts', dest='posts', type=str,
|
||||||
default=None,
|
default=None,
|
||||||
help='Show posts for the given handle')
|
help='Show posts for the given handle')
|
||||||
|
parser.add_argument('--moved', dest='moved', type=str,
|
||||||
|
default=None,
|
||||||
|
help='Show moved accounts for the given handle')
|
||||||
parser.add_argument('--postDomains', dest='postDomains', type=str,
|
parser.add_argument('--postDomains', dest='postDomains', type=str,
|
||||||
default=None,
|
default=None,
|
||||||
help='Show domains referenced in public '
|
help='Show domains referenced in public '
|
||||||
|
|
@ -860,6 +864,45 @@ def _command_options() -> None:
|
||||||
signing_priv_key_pem, origin_domain)
|
signing_priv_key_pem, origin_domain)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
if argb.moved:
|
||||||
|
if not argb.domain:
|
||||||
|
origin_domain = get_config_param(base_dir, 'domain')
|
||||||
|
else:
|
||||||
|
origin_domain = argb.domain
|
||||||
|
if debug:
|
||||||
|
print('origin_domain: ' + str(origin_domain))
|
||||||
|
if '@' not in argb.moved:
|
||||||
|
if '/users/' in argb.moved:
|
||||||
|
moved_nickname = get_nickname_from_actor(argb.moved)
|
||||||
|
moved_domain, moved_port = get_domain_from_actor(argb.moved)
|
||||||
|
argb.moved = \
|
||||||
|
get_full_domain(moved_nickname + '@' + moved_domain,
|
||||||
|
moved_port)
|
||||||
|
else:
|
||||||
|
print('Syntax: --moved nickname@domain')
|
||||||
|
sys.exit()
|
||||||
|
if not argb.http:
|
||||||
|
argb.port = 443
|
||||||
|
nickname = argb.moved.split('@')[0]
|
||||||
|
domain = argb.moved.split('@')[1]
|
||||||
|
proxy_type = None
|
||||||
|
if argb.tor or domain.endswith('.onion'):
|
||||||
|
proxy_type = 'tor'
|
||||||
|
if domain.endswith('.onion'):
|
||||||
|
argb.port = 80
|
||||||
|
elif argb.i2p or domain.endswith('.i2p'):
|
||||||
|
proxy_type = 'i2p'
|
||||||
|
if domain.endswith('.i2p'):
|
||||||
|
argb.port = 80
|
||||||
|
elif argb.gnunet:
|
||||||
|
proxy_type = 'gnunet'
|
||||||
|
if not argb.language:
|
||||||
|
argb.language = 'en'
|
||||||
|
moved_dict = \
|
||||||
|
get_moved_accounts(base_dir, nickname, domain, 'following.txt')
|
||||||
|
pprint(moved_dict)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
if argb.postDomains:
|
if argb.postDomains:
|
||||||
if '@' not in argb.postDomains:
|
if '@' not in argb.postDomains:
|
||||||
if '/users/' in argb.postDomains:
|
if '/users/' in argb.postDomains:
|
||||||
|
|
|
||||||
33
inbox.py
33
inbox.py
|
|
@ -1088,6 +1088,39 @@ def _person_receive_update(base_dir: str,
|
||||||
if debug:
|
if debug:
|
||||||
print('actor updated for ' + person_json['id'])
|
print('actor updated for ' + person_json['id'])
|
||||||
|
|
||||||
|
if person_json.get('movedTo'):
|
||||||
|
prev_domain, prev_port = get_domain_from_actor(person_json['id'])
|
||||||
|
prev_domain_full = get_full_domain(prev_domain, prev_port)
|
||||||
|
prev_nickname = get_nickname_from_actor(person_json['id'])
|
||||||
|
new_domain, new_port = get_domain_from_actor(person_json['movedTo'])
|
||||||
|
new_domain_full = get_full_domain(new_domain, new_port)
|
||||||
|
new_nickname = get_nickname_from_actor(person_json['movedTo'])
|
||||||
|
|
||||||
|
new_actor = prev_nickname + '@' + prev_domain_full + ' ' + \
|
||||||
|
new_nickname + '@' + new_domain_full
|
||||||
|
refollow_str = ''
|
||||||
|
refollow_filename = base_dir + '/accounts/actors_moved.txt'
|
||||||
|
refollow_file_exists = False
|
||||||
|
if os.path.isfile(refollow_filename):
|
||||||
|
try:
|
||||||
|
with open(refollow_filename, 'r',
|
||||||
|
encoding='utf-8') as fp_refollow:
|
||||||
|
refollow_str = fp_refollow.read()
|
||||||
|
refollow_file_exists = True
|
||||||
|
except OSError:
|
||||||
|
print('EX: unable to read ' + refollow_filename)
|
||||||
|
if new_actor not in refollow_str:
|
||||||
|
refollow_type = 'w+'
|
||||||
|
if refollow_file_exists:
|
||||||
|
refollow_type = 'a+'
|
||||||
|
try:
|
||||||
|
with open(refollow_filename, refollow_type,
|
||||||
|
encoding='utf-8') as fp_refollow:
|
||||||
|
fp_refollow.write(new_actor + '\n')
|
||||||
|
except OSError:
|
||||||
|
print('EX: unable to write to ' +
|
||||||
|
refollow_filename)
|
||||||
|
|
||||||
# remove avatar if it exists so that it will be refreshed later
|
# remove avatar if it exists so that it will be refreshed later
|
||||||
# when a timeline is constructed
|
# when a timeline is constructed
|
||||||
actor_str = person_json['id'].replace('/', '-')
|
actor_str = person_json['id'].replace('/', '-')
|
||||||
|
|
|
||||||
80
migrate.py
80
migrate.py
|
|
@ -129,59 +129,61 @@ def _update_moved_handle(base_dir: str, nickname: str, domain: str,
|
||||||
following_filename = \
|
following_filename = \
|
||||||
acct_dir(base_dir, nickname, domain) + '/following.txt'
|
acct_dir(base_dir, nickname, domain) + '/following.txt'
|
||||||
if os.path.isfile(following_filename):
|
if os.path.isfile(following_filename):
|
||||||
|
following_handles = []
|
||||||
with open(following_filename, 'r', encoding='utf-8') as foll1:
|
with open(following_filename, 'r', encoding='utf-8') as foll1:
|
||||||
following_handles = foll1.readlines()
|
following_handles = foll1.readlines()
|
||||||
|
|
||||||
moved_to_handle = moved_to_nickname + '@' + moved_to_domain_full
|
moved_to_handle = moved_to_nickname + '@' + moved_to_domain_full
|
||||||
handle_lower = handle.lower()
|
handle_lower = handle.lower()
|
||||||
|
|
||||||
refollow_filename = \
|
refollow_filename = \
|
||||||
acct_dir(base_dir, nickname, domain) + '/refollow.txt'
|
acct_dir(base_dir, nickname, domain) + '/refollow.txt'
|
||||||
|
|
||||||
# unfollow the old handle
|
# unfollow the old handle
|
||||||
with open(following_filename, 'w+', encoding='utf-8') as foll2:
|
with open(following_filename, 'w+', encoding='utf-8') as foll2:
|
||||||
for follow_handle in following_handles:
|
for follow_handle in following_handles:
|
||||||
if follow_handle.strip("\n").strip("\r").lower() != \
|
if follow_handle.strip("\n").strip("\r").lower() != \
|
||||||
handle_lower:
|
handle_lower:
|
||||||
foll2.write(follow_handle)
|
foll2.write(follow_handle)
|
||||||
|
else:
|
||||||
|
handle_nickname = handle.split('@')[0]
|
||||||
|
handle_domain = handle.split('@')[1]
|
||||||
|
unfollow_account(base_dir, nickname, domain,
|
||||||
|
handle_nickname,
|
||||||
|
handle_domain,
|
||||||
|
debug, group_account, 'following.txt')
|
||||||
|
ctr += 1
|
||||||
|
print('Unfollowed ' + handle + ' who has moved to ' +
|
||||||
|
moved_to_handle)
|
||||||
|
|
||||||
|
# save the new handles to the refollow list
|
||||||
|
if os.path.isfile(refollow_filename):
|
||||||
|
with open(refollow_filename, 'a+',
|
||||||
|
encoding='utf-8') as refoll:
|
||||||
|
refoll.write(moved_to_handle + '\n')
|
||||||
else:
|
else:
|
||||||
handle_nickname = handle.split('@')[0]
|
with open(refollow_filename, 'w+',
|
||||||
handle_domain = handle.split('@')[1]
|
encoding='utf-8') as refoll:
|
||||||
unfollow_account(base_dir, nickname, domain,
|
refoll.write(moved_to_handle + '\n')
|
||||||
handle_nickname,
|
|
||||||
handle_domain,
|
|
||||||
debug, group_account, 'following.txt')
|
|
||||||
ctr += 1
|
|
||||||
print('Unfollowed ' + handle + ' who has moved to ' +
|
|
||||||
moved_to_handle)
|
|
||||||
|
|
||||||
# save the new handles to the refollow list
|
|
||||||
if os.path.isfile(refollow_filename):
|
|
||||||
with open(refollow_filename, 'a+',
|
|
||||||
encoding='utf-8') as refoll:
|
|
||||||
refoll.write(moved_to_handle + '\n')
|
|
||||||
else:
|
|
||||||
with open(refollow_filename, 'w+',
|
|
||||||
encoding='utf-8') as refoll:
|
|
||||||
refoll.write(moved_to_handle + '\n')
|
|
||||||
|
|
||||||
followers_filename = \
|
followers_filename = \
|
||||||
acct_dir(base_dir, nickname, domain) + '/followers.txt'
|
acct_dir(base_dir, nickname, domain) + '/followers.txt'
|
||||||
if os.path.isfile(followers_filename):
|
if os.path.isfile(followers_filename):
|
||||||
|
follower_handles = []
|
||||||
with open(followers_filename, 'r', encoding='utf-8') as foll3:
|
with open(followers_filename, 'r', encoding='utf-8') as foll3:
|
||||||
follower_handles = foll3.readlines()
|
follower_handles = foll3.readlines()
|
||||||
|
|
||||||
handle_lower = handle.lower()
|
handle_lower = handle.lower()
|
||||||
|
|
||||||
# remove followers who have moved
|
# remove followers who have moved
|
||||||
with open(followers_filename, 'w+', encoding='utf-8') as foll4:
|
with open(followers_filename, 'w+', encoding='utf-8') as foll4:
|
||||||
for follower_handle in follower_handles:
|
for follower_handle in follower_handles:
|
||||||
if follower_handle.strip("\n").strip("\r").lower() != \
|
if follower_handle.strip("\n").strip("\r").lower() != \
|
||||||
handle_lower:
|
handle_lower:
|
||||||
foll4.write(follower_handle)
|
foll4.write(follower_handle)
|
||||||
else:
|
else:
|
||||||
ctr += 1
|
ctr += 1
|
||||||
print('Removed follower who has moved ' + handle)
|
print('Removed follower who has moved ' + handle)
|
||||||
|
|
||||||
return ctr
|
return ctr
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,292 @@
|
||||||
|
__filename__ = "relationships.py"
|
||||||
|
__author__ = "Bob Mottram"
|
||||||
|
__license__ = "AGPL3+"
|
||||||
|
__version__ = "1.3.0"
|
||||||
|
__maintainer__ = "Bob Mottram"
|
||||||
|
__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
|
||||||
|
from utils import is_account_dir
|
||||||
|
from utils import get_nickname_from_actor
|
||||||
|
from utils import get_domain_from_actor
|
||||||
|
from utils import load_json
|
||||||
|
|
||||||
|
|
||||||
|
def get_moved_accounts(base_dir: str, nickname: str, domain: str,
|
||||||
|
filename: str = 'following.txt') -> {}:
|
||||||
|
"""returns a dict of moved accounts
|
||||||
|
"""
|
||||||
|
moved_accounts_filename = base_dir + '/accounts/actors_moved.txt'
|
||||||
|
if not os.path.isfile(moved_accounts_filename):
|
||||||
|
return {}
|
||||||
|
refollow_str = ''
|
||||||
|
try:
|
||||||
|
with open(moved_accounts_filename, 'r',
|
||||||
|
encoding='utf-8') as fp_refollow:
|
||||||
|
refollow_str = fp_refollow.read()
|
||||||
|
except OSError:
|
||||||
|
print('EX: get_moved_accounts unable to read ' +
|
||||||
|
moved_accounts_filename)
|
||||||
|
refollow_list = refollow_str.split('\n')
|
||||||
|
refollow_dict = {}
|
||||||
|
|
||||||
|
follow_filename = \
|
||||||
|
acct_dir(base_dir, nickname, domain) + '/' + filename
|
||||||
|
follow_str = ''
|
||||||
|
try:
|
||||||
|
with open(follow_filename, 'r',
|
||||||
|
encoding='utf-8') as fp_follow:
|
||||||
|
follow_str = fp_follow.read()
|
||||||
|
except OSError:
|
||||||
|
print('EX: get_moved_accounts unable to read ' +
|
||||||
|
follow_filename)
|
||||||
|
follow_list = follow_str.split('\n')
|
||||||
|
|
||||||
|
ctr = 0
|
||||||
|
for line in refollow_list:
|
||||||
|
if ' ' not in line:
|
||||||
|
continue
|
||||||
|
prev_handle = line.split(' ')[0]
|
||||||
|
new_handle = line.split(' ')[1]
|
||||||
|
refollow_dict[prev_handle] = new_handle
|
||||||
|
ctr = ctr + 1
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
for handle in follow_list:
|
||||||
|
if refollow_dict.get(handle):
|
||||||
|
if refollow_dict[handle] not in follow_list:
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
# Don't show moved accounts to non-authorized viewers
|
||||||
|
if not authorized:
|
||||||
|
follows_per_page = 0
|
||||||
|
|
||||||
|
if '/moved' not in path:
|
||||||
|
return None
|
||||||
|
if '?page=' not in path:
|
||||||
|
path = path.replace('/moved', '/moved?page=true')
|
||||||
|
# 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,
|
||||||
|
'orderedItems': [],
|
||||||
|
'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)
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
def update_moved_actors(base_dir: str, debug: bool) -> None:
|
||||||
|
"""Updates the file containing moved actors
|
||||||
|
"""
|
||||||
|
actors_cache_dir = base_dir + '/cache/actors'
|
||||||
|
if not os.path.isdir(actors_cache_dir):
|
||||||
|
if debug:
|
||||||
|
print('No cached actors')
|
||||||
|
return
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
print('Updating moved actors')
|
||||||
|
actors_dict = {}
|
||||||
|
ctr = 0
|
||||||
|
for _, _, files in os.walk(actors_cache_dir):
|
||||||
|
for actor_str in files:
|
||||||
|
if not actor_str.endswith('.json'):
|
||||||
|
continue
|
||||||
|
orig_str = actor_str
|
||||||
|
actor_str = actor_str.replace('.json', '').replace('#', '/')
|
||||||
|
nickname = get_nickname_from_actor(actor_str)
|
||||||
|
domain, port = get_domain_from_actor(actor_str)
|
||||||
|
domain_full = get_full_domain(domain, port)
|
||||||
|
handle = nickname + '@' + domain_full
|
||||||
|
actors_dict[handle] = orig_str
|
||||||
|
ctr += 1
|
||||||
|
break
|
||||||
|
|
||||||
|
if actors_dict:
|
||||||
|
print('Actors dict created ' + str(ctr))
|
||||||
|
else:
|
||||||
|
print('No cached actors found')
|
||||||
|
|
||||||
|
# get the handles to be checked for movedTo attribute
|
||||||
|
handles_to_check = []
|
||||||
|
for _, dirs, _ in os.walk(base_dir + '/accounts'):
|
||||||
|
for account in dirs:
|
||||||
|
if not is_account_dir(account):
|
||||||
|
continue
|
||||||
|
following_filename = \
|
||||||
|
base_dir + '/accounts/' + account + '/following.txt'
|
||||||
|
if not os.path.isfile(following_filename):
|
||||||
|
continue
|
||||||
|
following_str = ''
|
||||||
|
try:
|
||||||
|
with open(following_filename, 'r',
|
||||||
|
encoding='utf-8') as fp_foll:
|
||||||
|
following_str = fp_foll.read()
|
||||||
|
except OSError:
|
||||||
|
print('EX: update_moved_actors unable to read ' +
|
||||||
|
following_filename)
|
||||||
|
continue
|
||||||
|
following_list = following_str.split('\n')
|
||||||
|
for handle in following_list:
|
||||||
|
if handle not in handles_to_check:
|
||||||
|
handles_to_check.append(handle)
|
||||||
|
break
|
||||||
|
|
||||||
|
if handles_to_check:
|
||||||
|
print('All accounts handles list generated ' +
|
||||||
|
str(len(handles_to_check)))
|
||||||
|
else:
|
||||||
|
print('No accounts are following')
|
||||||
|
|
||||||
|
moved_str = ''
|
||||||
|
ctr = 0
|
||||||
|
for handle in handles_to_check:
|
||||||
|
if not actors_dict.get(handle):
|
||||||
|
continue
|
||||||
|
actor_filename = base_dir + '/cache/actors/' + actors_dict[handle]
|
||||||
|
if not os.path.isfile(actor_filename):
|
||||||
|
continue
|
||||||
|
actor_json = load_json(actor_filename, 1, 1)
|
||||||
|
if not actor_json:
|
||||||
|
continue
|
||||||
|
if not actor_json.get('movedTo'):
|
||||||
|
continue
|
||||||
|
nickname = get_nickname_from_actor(actor_json['movedTo'])
|
||||||
|
domain, port = get_domain_from_actor(actor_json['movedTo'])
|
||||||
|
domain_full = get_full_domain(domain, port)
|
||||||
|
new_handle = nickname + '@' + domain_full
|
||||||
|
moved_str += handle + ' ' + new_handle + '\n'
|
||||||
|
ctr = ctr + 1
|
||||||
|
|
||||||
|
if moved_str:
|
||||||
|
print('Moved accounts detected ' + str(ctr))
|
||||||
|
else:
|
||||||
|
print('No moved accounts detected')
|
||||||
|
|
||||||
|
moved_accounts_filename = base_dir + '/accounts/actors_moved.txt'
|
||||||
|
if not moved_str:
|
||||||
|
if os.path.isfile(moved_accounts_filename):
|
||||||
|
try:
|
||||||
|
os.remove(moved_accounts_filename)
|
||||||
|
except OSError:
|
||||||
|
print('EX: update_moved_actors unable to remove ' +
|
||||||
|
moved_accounts_filename)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(moved_accounts_filename, 'w+',
|
||||||
|
encoding='utf-8') as fp_moved:
|
||||||
|
fp_moved.write(moved_str)
|
||||||
|
except OSError:
|
||||||
|
print('EX: update_moved_actors unable to save ' +
|
||||||
|
moved_accounts_filename)
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "تصغير كل الصور",
|
"Minimize all images": "تصغير كل الصور",
|
||||||
"Edit post": "تعديل المنشور",
|
"Edit post": "تعديل المنشور",
|
||||||
"Preview posts on profile screen": "معاينة المشاركات على شاشة الملف الشخصي",
|
"Preview posts on profile screen": "معاينة المشاركات على شاشة الملف الشخصي",
|
||||||
"Reverse timelines": "عكس الجداول الزمنية"
|
"Reverse timelines": "عكس الجداول الزمنية",
|
||||||
|
"Moved": "انتقل",
|
||||||
|
"Move": "يتحرك"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "সমস্ত ছবি ছোট করুন",
|
"Minimize all images": "সমস্ত ছবি ছোট করুন",
|
||||||
"Edit post": "পোস্ট সম্পাদনা করুন",
|
"Edit post": "পোস্ট সম্পাদনা করুন",
|
||||||
"Preview posts on profile screen": "প্রোফাইল স্ক্রিনে পোস্টের পূর্বরূপ দেখুন",
|
"Preview posts on profile screen": "প্রোফাইল স্ক্রিনে পোস্টের পূর্বরূপ দেখুন",
|
||||||
"Reverse timelines": "বিপরীত সময়রেখা"
|
"Reverse timelines": "বিপরীত সময়রেখা",
|
||||||
|
"Moved": "সরানো হয়েছে",
|
||||||
|
"Move": "সরান"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Minimitzar totes les imatges",
|
"Minimize all images": "Minimitzar totes les imatges",
|
||||||
"Edit post": "Edita la publicació",
|
"Edit post": "Edita la publicació",
|
||||||
"Preview posts on profile screen": "Previsualitza les publicacions a la pantalla del perfil",
|
"Preview posts on profile screen": "Previsualitza les publicacions a la pantalla del perfil",
|
||||||
"Reverse timelines": "Cronologia inversa"
|
"Reverse timelines": "Cronologia inversa",
|
||||||
|
"Moved": "Mogut",
|
||||||
|
"Move": "Moure's"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Lleihau pob delwedd",
|
"Minimize all images": "Lleihau pob delwedd",
|
||||||
"Edit post": "Golygu post",
|
"Edit post": "Golygu post",
|
||||||
"Preview posts on profile screen": "Rhagolwg postiadau ar sgrin proffil",
|
"Preview posts on profile screen": "Rhagolwg postiadau ar sgrin proffil",
|
||||||
"Reverse timelines": "Gwrthdroi llinellau amser"
|
"Reverse timelines": "Gwrthdroi llinellau amser",
|
||||||
|
"Moved": "Wedi symud",
|
||||||
|
"Move": "Symud"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Alle Bilder minimieren",
|
"Minimize all images": "Alle Bilder minimieren",
|
||||||
"Edit post": "Beitrag bearbeiten",
|
"Edit post": "Beitrag bearbeiten",
|
||||||
"Preview posts on profile screen": "Vorschau von Beiträgen auf dem Profilbildschirm",
|
"Preview posts on profile screen": "Vorschau von Beiträgen auf dem Profilbildschirm",
|
||||||
"Reverse timelines": "Umgekehrte Zeitlinien"
|
"Reverse timelines": "Umgekehrte Zeitlinien",
|
||||||
|
"Moved": "Gerührt",
|
||||||
|
"Move": "Bewegen"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Ελαχιστοποίηση όλων των εικόνων",
|
"Minimize all images": "Ελαχιστοποίηση όλων των εικόνων",
|
||||||
"Edit post": "Επεξεργασία ανάρτησης",
|
"Edit post": "Επεξεργασία ανάρτησης",
|
||||||
"Preview posts on profile screen": "Προεπισκόπηση αναρτήσεων στην οθόνη προφίλ",
|
"Preview posts on profile screen": "Προεπισκόπηση αναρτήσεων στην οθόνη προφίλ",
|
||||||
"Reverse timelines": "Αντίστροφα χρονοδιαγράμματα"
|
"Reverse timelines": "Αντίστροφα χρονοδιαγράμματα",
|
||||||
|
"Moved": "Μετακινήθηκε",
|
||||||
|
"Move": "Κίνηση"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Minimize all images",
|
"Minimize all images": "Minimize all images",
|
||||||
"Edit post": "Edit post",
|
"Edit post": "Edit post",
|
||||||
"Preview posts on profile screen": "Preview posts on profile screen",
|
"Preview posts on profile screen": "Preview posts on profile screen",
|
||||||
"Reverse timelines": "Reverse timelines"
|
"Reverse timelines": "Reverse timelines",
|
||||||
|
"Moved": "Moved",
|
||||||
|
"Move": "Move"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Minimizar todas las imágenes",
|
"Minimize all images": "Minimizar todas las imágenes",
|
||||||
"Edit post": "Editar post",
|
"Edit post": "Editar post",
|
||||||
"Preview posts on profile screen": "Vista previa de publicaciones en la pantalla de perfil",
|
"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",
|
||||||
|
"Move": "Muevete"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "تمام تصاویر را به حداقل برسانید",
|
"Minimize all images": "تمام تصاویر را به حداقل برسانید",
|
||||||
"Edit post": "ویرایش پست",
|
"Edit post": "ویرایش پست",
|
||||||
"Preview posts on profile screen": "پیش نمایش پست ها در صفحه نمایه",
|
"Preview posts on profile screen": "پیش نمایش پست ها در صفحه نمایه",
|
||||||
"Reverse timelines": "جدول های زمانی معکوس"
|
"Reverse timelines": "جدول های زمانی معکوس",
|
||||||
|
"Moved": "منتقل شد",
|
||||||
|
"Move": "حرکت"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Réduire toutes les images",
|
"Minimize all images": "Réduire toutes les images",
|
||||||
"Edit post": "Modifier le message",
|
"Edit post": "Modifier le message",
|
||||||
"Preview posts on profile screen": "Prévisualiser les messages sur l'écran de profil",
|
"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",
|
||||||
|
"Move": "Déplacer"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Íoslaghdaigh gach íomhá",
|
"Minimize all images": "Íoslaghdaigh gach íomhá",
|
||||||
"Edit post": "Cuir postáil in eagar",
|
"Edit post": "Cuir postáil in eagar",
|
||||||
"Preview posts on profile screen": "Réamhamhairc postálacha ar an scáileán próifíle",
|
"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",
|
||||||
|
"Move": "Bog"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "सभी छवियों को छोटा करें",
|
"Minimize all images": "सभी छवियों को छोटा करें",
|
||||||
"Edit post": "संपादित पोस्ट",
|
"Edit post": "संपादित पोस्ट",
|
||||||
"Preview posts on profile screen": "प्रोफ़ाइल स्क्रीन पर पोस्ट का पूर्वावलोकन करें",
|
"Preview posts on profile screen": "प्रोफ़ाइल स्क्रीन पर पोस्ट का पूर्वावलोकन करें",
|
||||||
"Reverse timelines": "रिवर्स टाइमलाइन"
|
"Reverse timelines": "रिवर्स टाइमलाइन",
|
||||||
|
"Moved": "ले जाया गया",
|
||||||
|
"Move": "कदम"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Riduci a icona tutte le immagini",
|
"Minimize all images": "Riduci a icona tutte le immagini",
|
||||||
"Edit post": "Modifica post",
|
"Edit post": "Modifica post",
|
||||||
"Preview posts on profile screen": "Visualizza l'anteprima dei post nella schermata del profilo",
|
"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",
|
||||||
|
"Move": "Spostare"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "すべての画像を最小化",
|
"Minimize all images": "すべての画像を最小化",
|
||||||
"Edit post": "投稿を編集",
|
"Edit post": "投稿を編集",
|
||||||
"Preview posts on profile screen": "プロフィール画面で投稿をプレビュー",
|
"Preview posts on profile screen": "プロフィール画面で投稿をプレビュー",
|
||||||
"Reverse timelines": "逆タイムライン"
|
"Reverse timelines": "逆タイムライン",
|
||||||
|
"Moved": "移動しました",
|
||||||
|
"Move": "動く"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "모든 이미지 최소화",
|
"Minimize all images": "모든 이미지 최소화",
|
||||||
"Edit post": "게시물 수정",
|
"Edit post": "게시물 수정",
|
||||||
"Preview posts on profile screen": "프로필 화면에서 게시물 미리보기",
|
"Preview posts on profile screen": "프로필 화면에서 게시물 미리보기",
|
||||||
"Reverse timelines": "역방향 타임라인"
|
"Reverse timelines": "역방향 타임라인",
|
||||||
|
"Moved": "움직이는",
|
||||||
|
"Move": "이동하다"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Hemî wêneyan kêm bikin",
|
"Minimize all images": "Hemî wêneyan kêm bikin",
|
||||||
"Edit post": "Biguherîne post",
|
"Edit post": "Biguherîne post",
|
||||||
"Preview posts on profile screen": "Mesajên li ser ekrana profîlê pêşdîtin",
|
"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",
|
||||||
|
"Move": "Barkirin"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Alle afbeeldingen minimaliseren",
|
"Minimize all images": "Alle afbeeldingen minimaliseren",
|
||||||
"Edit post": "Bericht bewerken",
|
"Edit post": "Bericht bewerken",
|
||||||
"Preview posts on profile screen": "Bekijk berichten op het profielscherm",
|
"Preview posts on profile screen": "Bekijk berichten op het profielscherm",
|
||||||
"Reverse timelines": "Omgekeerde tijdlijnen"
|
"Reverse timelines": "Omgekeerde tijdlijnen",
|
||||||
|
"Moved": "Verhuisd",
|
||||||
|
"Move": "Beweging"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -598,5 +598,7 @@
|
||||||
"Minimize all images": "Minimize all images",
|
"Minimize all images": "Minimize all images",
|
||||||
"Edit post": "Edit post",
|
"Edit post": "Edit post",
|
||||||
"Preview posts on profile screen": "Preview posts on profile screen",
|
"Preview posts on profile screen": "Preview posts on profile screen",
|
||||||
"Reverse timelines": "Reverse timelines"
|
"Reverse timelines": "Reverse timelines",
|
||||||
|
"Moved": "Moved",
|
||||||
|
"Move": "Move"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Zminimalizuj wszystkie obrazy",
|
"Minimize all images": "Zminimalizuj wszystkie obrazy",
|
||||||
"Edit post": "Edytuj post",
|
"Edit post": "Edytuj post",
|
||||||
"Preview posts on profile screen": "Podgląd postów na ekranie profilu",
|
"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ł",
|
||||||
|
"Move": "Przenosić"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Minimize todas as imagens",
|
"Minimize all images": "Minimize todas as imagens",
|
||||||
"Edit post": "Editar post",
|
"Edit post": "Editar post",
|
||||||
"Preview posts on profile screen": "Visualizar postagens na tela do perfil",
|
"Preview posts on profile screen": "Visualizar postagens na tela do perfil",
|
||||||
"Reverse timelines": "Cronogramas reversos"
|
"Reverse timelines": "Cronogramas reversos",
|
||||||
|
"Moved": "Mudou-se",
|
||||||
|
"Move": "Jogada"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Свернуть все изображения",
|
"Minimize all images": "Свернуть все изображения",
|
||||||
"Edit post": "Редактировать сообщение",
|
"Edit post": "Редактировать сообщение",
|
||||||
"Preview posts on profile screen": "Предварительный просмотр сообщений на экране профиля",
|
"Preview posts on profile screen": "Предварительный просмотр сообщений на экране профиля",
|
||||||
"Reverse timelines": "Обратные сроки"
|
"Reverse timelines": "Обратные сроки",
|
||||||
|
"Moved": "Взолнованный",
|
||||||
|
"Move": "Шаг"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Punguza picha zote",
|
"Minimize all images": "Punguza picha zote",
|
||||||
"Edit post": "Badilisha chapisho",
|
"Edit post": "Badilisha chapisho",
|
||||||
"Preview posts on profile screen": "Hakiki machapisho kwenye skrini ya wasifu",
|
"Preview posts on profile screen": "Hakiki machapisho kwenye skrini ya wasifu",
|
||||||
"Reverse timelines": "Обратные сроки"
|
"Reverse timelines": "Обратные сроки",
|
||||||
|
"Moved": "Imehamishwa",
|
||||||
|
"Move": "Sogeza"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Tüm görüntüleri simge durumuna küçült",
|
"Minimize all images": "Tüm görüntüleri simge durumuna küçült",
|
||||||
"Edit post": "Gönderiyi düzenle",
|
"Edit post": "Gönderiyi düzenle",
|
||||||
"Preview posts on profile screen": "Gönderileri profil ekranında önizleyin",
|
"Preview posts on profile screen": "Gönderileri profil ekranında önizleyin",
|
||||||
"Reverse timelines": "Обратные сроки"
|
"Reverse timelines": "Обратные сроки",
|
||||||
|
"Moved": "Etkilenmiş",
|
||||||
|
"Move": "Hareket"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "Згорнути всі зображення",
|
"Minimize all images": "Згорнути всі зображення",
|
||||||
"Edit post": "Редагувати пост",
|
"Edit post": "Редагувати пост",
|
||||||
"Preview posts on profile screen": "Попередній перегляд дописів на екрані профілю",
|
"Preview posts on profile screen": "Попередній перегляд дописів на екрані профілю",
|
||||||
"Reverse timelines": "Обратные сроки"
|
"Reverse timelines": "Обратные сроки",
|
||||||
|
"Moved": "Переїхав",
|
||||||
|
"Move": "рухатися"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "מינאַמייז אַלע בילדער",
|
"Minimize all images": "מינאַמייז אַלע בילדער",
|
||||||
"Edit post": "רעדאַגירן פּאָסטן",
|
"Edit post": "רעדאַגירן פּאָסטן",
|
||||||
"Preview posts on profile screen": "פאָרויסיקע ווייַזונג אַרטיקלען אויף פּראָפיל פאַרשטעלן",
|
"Preview posts on profile screen": "פאָרויסיקע ווייַזונג אַרטיקלען אויף פּראָפיל פאַרשטעלן",
|
||||||
"Reverse timelines": "פאַרקערט טיימליינז"
|
"Reverse timelines": "פאַרקערט טיימליינז",
|
||||||
|
"Moved": "אריבערגעפארן",
|
||||||
|
"Move": "מאַך"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -602,5 +602,7 @@
|
||||||
"Minimize all images": "最小化所有图像",
|
"Minimize all images": "最小化所有图像",
|
||||||
"Edit post": "编辑帖子",
|
"Edit post": "编辑帖子",
|
||||||
"Preview posts on profile screen": "在个人资料屏幕上预览帖子",
|
"Preview posts on profile screen": "在个人资料屏幕上预览帖子",
|
||||||
"Reverse timelines": "倒转时间线"
|
"Reverse timelines": "倒转时间线",
|
||||||
|
"Moved": "אריבערגעפארן",
|
||||||
|
"Move": "移动"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
utils.py
2
utils.py
|
|
@ -2240,7 +2240,7 @@ def _get_reserved_words() -> str:
|
||||||
'minimal', 'search', 'eventdelete',
|
'minimal', 'search', 'eventdelete',
|
||||||
'searchemoji', 'catalog', 'conversationId',
|
'searchemoji', 'catalog', 'conversationId',
|
||||||
'mention', 'http', 'https', 'ipfs', 'ipns',
|
'mention', 'http', 'https', 'ipfs', 'ipns',
|
||||||
'ontologies', 'data', 'postedit')
|
'ontologies', 'data', 'postedit', 'moved')
|
||||||
|
|
||||||
|
|
||||||
def get_nickname_validation_pattern() -> str:
|
def get_nickname_validation_pattern() -> str:
|
||||||
|
|
|
||||||
|
|
@ -163,9 +163,11 @@ def html_person_options(default_timeline: str,
|
||||||
authorized: bool,
|
authorized: bool,
|
||||||
access_keys: {},
|
access_keys: {},
|
||||||
is_group: bool,
|
is_group: bool,
|
||||||
theme: str) -> str:
|
theme: str,
|
||||||
|
blocked_cache: []) -> str:
|
||||||
"""Show options for a person: view/follow/block/report
|
"""Show options for a person: view/follow/block/report
|
||||||
"""
|
"""
|
||||||
|
options_link_str = ''
|
||||||
options_domain, options_port = get_domain_from_actor(options_actor)
|
options_domain, options_port = get_domain_from_actor(options_actor)
|
||||||
if not options_domain:
|
if not options_domain:
|
||||||
return None
|
return None
|
||||||
|
|
@ -211,9 +213,8 @@ def html_person_options(default_timeline: str,
|
||||||
options_nickname, options_domain_full):
|
options_nickname, options_domain_full):
|
||||||
block_str = 'Block'
|
block_str = 'Block'
|
||||||
|
|
||||||
options_link_str = ''
|
|
||||||
if options_link:
|
if options_link:
|
||||||
options_link_str = \
|
options_link_str += \
|
||||||
' <input type="hidden" name="postUrl" value="' + \
|
' <input type="hidden" name="postUrl" value="' + \
|
||||||
options_link + '">\n'
|
options_link + '">\n'
|
||||||
css_filename = base_dir + '/epicyon-options.css'
|
css_filename = base_dir + '/epicyon-options.css'
|
||||||
|
|
@ -295,15 +296,32 @@ def html_person_options(default_timeline: str,
|
||||||
if follows_you and authorized:
|
if follows_you and authorized:
|
||||||
options_str += \
|
options_str += \
|
||||||
' <p class="optionsText">' + translate['Follows you'] + '</p>\n'
|
' <p class="optionsText">' + translate['Follows you'] + '</p>\n'
|
||||||
|
options_str += ' <form method="POST" action="' + \
|
||||||
|
origin_path_str + '/personoptions">\n'
|
||||||
if moved_to:
|
if moved_to:
|
||||||
new_nickname = get_nickname_from_actor(moved_to)
|
new_nickname = get_nickname_from_actor(moved_to)
|
||||||
new_domain, _ = get_domain_from_actor(moved_to)
|
new_domain, _ = get_domain_from_actor(moved_to)
|
||||||
if new_nickname and new_domain:
|
if new_nickname and new_domain:
|
||||||
new_handle = new_nickname + '@' + new_domain
|
new_handle = new_nickname + '@' + new_domain
|
||||||
|
blocked_icon_str = ''
|
||||||
|
if is_blocked(base_dir, nickname, domain,
|
||||||
|
new_nickname, new_domain, blocked_cache):
|
||||||
|
blocked_icon_str = '❌'
|
||||||
options_str += \
|
options_str += \
|
||||||
' <p class="optionsText">' + \
|
' <p class="optionsText">' + \
|
||||||
translate['New account'] + \
|
translate['New account'] + \
|
||||||
': <a href="' + moved_to + '">@' + new_handle + '</a></p>\n'
|
': <a href="' + moved_to + '">@' + new_handle + '</a>' + \
|
||||||
|
blocked_icon_str
|
||||||
|
if follow_str == 'Unfollow' and not blocked_icon_str:
|
||||||
|
options_str += \
|
||||||
|
' <input type="hidden" name="movedToActor" value="' + \
|
||||||
|
moved_to + '">\n'
|
||||||
|
options_str += \
|
||||||
|
'<button type="submit" ' + \
|
||||||
|
'class="button" name="submitMove' + \
|
||||||
|
'" accesskey="' + access_keys['moveButton'] + '">' + \
|
||||||
|
translate['Move'] + '</button>'
|
||||||
|
options_str += '</p>\n'
|
||||||
elif also_known_as:
|
elif also_known_as:
|
||||||
other_accounts_html = \
|
other_accounts_html = \
|
||||||
' <p class="optionsText">' + \
|
' <p class="optionsText">' + \
|
||||||
|
|
@ -332,7 +350,7 @@ def html_person_options(default_timeline: str,
|
||||||
|
|
||||||
if email_address:
|
if email_address:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">' + translate['Email'] + \
|
' <p class="imText">' + translate['Email'] + \
|
||||||
': <a href="mailto:' + \
|
': <a href="mailto:' + \
|
||||||
email_address + '">' + remove_html(email_address) + '</a></p>\n'
|
email_address + '">' + remove_html(email_address) + '</a></p>\n'
|
||||||
if web_address:
|
if web_address:
|
||||||
|
|
@ -340,50 +358,51 @@ def html_person_options(default_timeline: str,
|
||||||
if '://' not in web_str:
|
if '://' not in web_str:
|
||||||
web_str = 'https://' + web_str
|
web_str = 'https://' + web_str
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">🌐 <a href="' + web_str + '">' + \
|
' <p class="imText">🌐 <a href="' + web_str + '">' + \
|
||||||
web_address + '</a></p>\n'
|
web_address + '</a></p>\n'
|
||||||
if gemini_link:
|
if gemini_link:
|
||||||
gemini_str = remove_html(gemini_link)
|
gemini_str = remove_html(gemini_link)
|
||||||
if '://' not in gemini_str:
|
if '://' not in gemini_str:
|
||||||
gemini_str = 'gemini://' + gemini_str
|
gemini_str = 'gemini://' + gemini_str
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">♊ <a href="' + gemini_str + '">' + \
|
' <p class="imText">♊ <a href="' + gemini_str + '">' + \
|
||||||
gemini_link + '</a></p>\n'
|
gemini_link + '</a></p>\n'
|
||||||
if xmpp_address:
|
if xmpp_address:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">' + translate['XMPP'] + \
|
' <p class="imText">' + translate['XMPP'] + \
|
||||||
': <a href="xmpp:' + remove_html(xmpp_address) + '">' + \
|
': <a href="xmpp:' + remove_html(xmpp_address) + '">' + \
|
||||||
xmpp_address + '</a></p>\n'
|
xmpp_address + '</a></p>\n'
|
||||||
if matrix_address:
|
if matrix_address:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">' + translate['Matrix'] + ': ' + \
|
' <p class="imText">' + translate['Matrix'] + ': ' + \
|
||||||
remove_html(matrix_address) + '</p>\n'
|
remove_html(matrix_address) + '</p>\n'
|
||||||
if ssb_address:
|
if ssb_address:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">SSB: ' + remove_html(ssb_address) + '</p>\n'
|
' <p class="imText">SSB: ' + remove_html(ssb_address) + '</p>\n'
|
||||||
if blog_address:
|
if blog_address:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">Blog: <a href="' + \
|
' <p class="imText">Blog: <a href="' + \
|
||||||
remove_html(blog_address) + '">' + \
|
remove_html(blog_address) + '">' + \
|
||||||
remove_html(blog_address) + '</a></p>\n'
|
remove_html(blog_address) + '</a></p>\n'
|
||||||
if tox_address:
|
if tox_address:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">Tox: ' + remove_html(tox_address) + '</p>\n'
|
' <p class="imText">Tox: ' + remove_html(tox_address) + '</p>\n'
|
||||||
if briar_address:
|
if briar_address:
|
||||||
if briar_address.startswith('briar://'):
|
if briar_address.startswith('briar://'):
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">' + \
|
' <p class="imText">' + \
|
||||||
remove_html(briar_address) + '</p>\n'
|
remove_html(briar_address) + '</p>\n'
|
||||||
else:
|
else:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">briar://' + \
|
' <p class="imText">briar://' + \
|
||||||
remove_html(briar_address) + '</p>\n'
|
remove_html(briar_address) + '</p>\n'
|
||||||
if cwtch_address:
|
if cwtch_address:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">Cwtch: ' + remove_html(cwtch_address) + '</p>\n'
|
' <p class="imText">Cwtch: ' + \
|
||||||
|
remove_html(cwtch_address) + '</p>\n'
|
||||||
if enigma_pub_key:
|
if enigma_pub_key:
|
||||||
options_str += \
|
options_str += \
|
||||||
'<p class="imText">Enigma: ' + \
|
' <p class="imText">Enigma: ' + \
|
||||||
remove_html(enigma_pub_key) + '</p>\n'
|
remove_html(enigma_pub_key) + '</p>\n'
|
||||||
if pgp_fingerprint:
|
if pgp_fingerprint:
|
||||||
options_str += '<p class="pgp">PGP: ' + \
|
options_str += '<p class="pgp">PGP: ' + \
|
||||||
|
|
@ -391,8 +410,6 @@ def html_person_options(default_timeline: str,
|
||||||
if pgp_pub_key:
|
if pgp_pub_key:
|
||||||
options_str += '<p class="pgp">' + \
|
options_str += '<p class="pgp">' + \
|
||||||
remove_html(pgp_pub_key).replace('\n', '<br>') + '</p>\n'
|
remove_html(pgp_pub_key).replace('\n', '<br>') + '</p>\n'
|
||||||
options_str += ' <form method="POST" action="' + \
|
|
||||||
origin_path_str + '/personoptions">\n'
|
|
||||||
options_str += ' <input type="hidden" name="pageNumber" value="' + \
|
options_str += ' <input type="hidden" name="pageNumber" value="' + \
|
||||||
str(page_number) + '">\n'
|
str(page_number) + '">\n'
|
||||||
options_str += ' <input type="hidden" name="actor" value="' + \
|
options_str += ' <input type="hidden" name="actor" value="' + \
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ __module_group__ = "Web Interface"
|
||||||
import os
|
import os
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from webfinger import webfinger_handle
|
from webfinger import webfinger_handle
|
||||||
|
from utils import remove_id_ending
|
||||||
from utils import standardize_text
|
from utils import standardize_text
|
||||||
from utils import get_display_name
|
from utils import get_display_name
|
||||||
from utils import is_group_account
|
from utils import is_group_account
|
||||||
|
|
@ -638,6 +639,12 @@ def html_profile(signing_priv_key_pem: str,
|
||||||
timezone: str, bold_reading: bool) -> str:
|
timezone: str, bold_reading: bool) -> str:
|
||||||
"""Show the profile page as html
|
"""Show the profile page as html
|
||||||
"""
|
"""
|
||||||
|
show_moved_accounts = False
|
||||||
|
if authorized:
|
||||||
|
moved_accounts_filename = base_dir + '/accounts/actors_moved.txt'
|
||||||
|
if os.path.isfile(moved_accounts_filename):
|
||||||
|
show_moved_accounts = True
|
||||||
|
|
||||||
nickname = profile_json['preferredUsername']
|
nickname = profile_json['preferredUsername']
|
||||||
if not nickname:
|
if not nickname:
|
||||||
return ""
|
return ""
|
||||||
|
|
@ -679,6 +686,8 @@ def html_profile(signing_priv_key_pem: str,
|
||||||
profile_description = standardize_text(profile_description)
|
profile_description = standardize_text(profile_description)
|
||||||
posts_button = 'button'
|
posts_button = 'button'
|
||||||
following_button = 'button'
|
following_button = 'button'
|
||||||
|
moved_button = 'button'
|
||||||
|
moved_button = 'button'
|
||||||
followers_button = 'button'
|
followers_button = 'button'
|
||||||
roles_button = 'button'
|
roles_button = 'button'
|
||||||
skills_button = 'button'
|
skills_button = 'button'
|
||||||
|
|
@ -688,6 +697,8 @@ def html_profile(signing_priv_key_pem: str,
|
||||||
posts_button = 'buttonselected'
|
posts_button = 'buttonselected'
|
||||||
elif selected == 'following':
|
elif selected == 'following':
|
||||||
following_button = 'buttonselected'
|
following_button = 'buttonselected'
|
||||||
|
elif selected == 'moved':
|
||||||
|
moved_button = 'buttonselected'
|
||||||
elif selected == 'followers':
|
elif selected == 'followers':
|
||||||
followers_button = 'buttonselected'
|
followers_button = 'buttonselected'
|
||||||
elif selected == 'roles':
|
elif selected == 'roles':
|
||||||
|
|
@ -979,14 +990,26 @@ def html_profile(signing_priv_key_pem: str,
|
||||||
html_hide_from_screen_reader('✍') + ' ' + translate['Edit']
|
html_hide_from_screen_reader('✍') + ' ' + translate['Edit']
|
||||||
menu_followers = \
|
menu_followers = \
|
||||||
html_hide_from_screen_reader('👪') + ' ' + followers_str
|
html_hide_from_screen_reader('👪') + ' ' + followers_str
|
||||||
|
if show_moved_accounts:
|
||||||
|
menu_moved = \
|
||||||
|
html_hide_from_screen_reader('⌂') + ' ' + translate['Moved']
|
||||||
menu_logout = \
|
menu_logout = \
|
||||||
html_hide_from_screen_reader('❎') + ' ' + translate['Logout']
|
html_hide_from_screen_reader('❎') + ' ' + translate['Logout']
|
||||||
nav_links = {
|
if not show_moved_accounts:
|
||||||
menu_timeline: user_path_str + '/' + deft,
|
nav_links = {
|
||||||
menu_edit: user_path_str + '/editprofile',
|
menu_timeline: user_path_str + '/' + deft,
|
||||||
menu_followers: user_path_str + '/followers#timeline',
|
menu_edit: user_path_str + '/editprofile',
|
||||||
menu_logout: '/logout'
|
menu_followers: user_path_str + '/followers#timeline',
|
||||||
}
|
menu_logout: '/logout'
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
nav_links = {
|
||||||
|
menu_timeline: user_path_str + '/' + deft,
|
||||||
|
menu_edit: user_path_str + '/editprofile',
|
||||||
|
menu_followers: user_path_str + '/followers#timeline',
|
||||||
|
menu_moved: user_path_str + '/moved#timeline',
|
||||||
|
menu_logout: '/logout'
|
||||||
|
}
|
||||||
if not is_group:
|
if not is_group:
|
||||||
menu_following = \
|
menu_following = \
|
||||||
html_hide_from_screen_reader('👥') + ' ' + translate['Following']
|
html_hide_from_screen_reader('👥') + ' ' + translate['Following']
|
||||||
|
|
@ -1031,6 +1054,12 @@ def html_profile(signing_priv_key_pem: str,
|
||||||
'<button class="' + followers_button + \
|
'<button class="' + followers_button + \
|
||||||
'"><span>' + followers_str + ' </span></button></a>'
|
'"><span>' + followers_str + ' </span></button></a>'
|
||||||
if not is_group:
|
if not is_group:
|
||||||
|
if show_moved_accounts:
|
||||||
|
profile_str += \
|
||||||
|
' <a href="' + users_path + \
|
||||||
|
'/moved#buttonheader" tabindex="2">' + \
|
||||||
|
'<button class="' + moved_button + '"><span>' + \
|
||||||
|
translate['Moved'] + ' </span></button></a>'
|
||||||
profile_str += \
|
profile_str += \
|
||||||
' <a href="' + users_path + \
|
' <a href="' + users_path + \
|
||||||
'/roles#buttonheader" tabindex="2">' + \
|
'/roles#buttonheader" tabindex="2">' + \
|
||||||
|
|
@ -1108,6 +1137,19 @@ def html_profile(signing_priv_key_pem: str,
|
||||||
max_items_per_page,
|
max_items_per_page,
|
||||||
dormant_months, debug,
|
dormant_months, debug,
|
||||||
signing_priv_key_pem)
|
signing_priv_key_pem)
|
||||||
|
if show_moved_accounts 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, ["moveAccount"],
|
||||||
|
selected,
|
||||||
|
users_path, page_number,
|
||||||
|
max_items_per_page,
|
||||||
|
dormant_months, debug,
|
||||||
|
signing_priv_key_pem)
|
||||||
if selected == 'followers':
|
if selected == 'followers':
|
||||||
profile_str += \
|
profile_str += \
|
||||||
_html_profile_following(translate, base_dir, http_prefix,
|
_html_profile_following(translate, base_dir, http_prefix,
|
||||||
|
|
@ -1199,9 +1241,10 @@ def _html_profile_posts(recent_posts_cache: {}, max_recent_posts: int,
|
||||||
break
|
break
|
||||||
shown_items = []
|
shown_items = []
|
||||||
for item in outbox_feed['orderedItems']:
|
for item in outbox_feed['orderedItems']:
|
||||||
if not item.get('id'):
|
|
||||||
continue
|
|
||||||
if item['type'] == 'Create':
|
if item['type'] == 'Create':
|
||||||
|
if not item['object'].get('id'):
|
||||||
|
continue
|
||||||
|
item_id = remove_id_ending(item['object']['id'])
|
||||||
post_str = \
|
post_str = \
|
||||||
individual_post_as_html(signing_priv_key_pem,
|
individual_post_as_html(signing_priv_key_pem,
|
||||||
True, recent_posts_cache,
|
True, recent_posts_cache,
|
||||||
|
|
@ -1227,9 +1270,9 @@ def _html_profile_posts(recent_posts_cache: {}, max_recent_posts: int,
|
||||||
timezone, False,
|
timezone, False,
|
||||||
bold_reading, dogwhistles,
|
bold_reading, dogwhistles,
|
||||||
minimize_all_images)
|
minimize_all_images)
|
||||||
if post_str and item['id'] not in shown_items:
|
if post_str and item_id not in shown_items:
|
||||||
profile_str += post_str + separator_str
|
profile_str += post_str + separator_str
|
||||||
shown_items.append(item['id'])
|
shown_items.append(item_id)
|
||||||
ctr += 1
|
ctr += 1
|
||||||
if ctr >= max_items:
|
if ctr >= max_items:
|
||||||
break
|
break
|
||||||
|
|
@ -2743,6 +2786,13 @@ def _individual_follow_as_html(signing_priv_key_pem: str,
|
||||||
';1;' + avatar_url + \
|
';1;' + avatar_url + \
|
||||||
'"><button class="buttonunfollow">' + \
|
'"><button class="buttonunfollow">' + \
|
||||||
translate[unfollow_str] + '</button></a>\n'
|
translate[unfollow_str] + '</button></a>\n'
|
||||||
|
elif btn == 'moveAccount':
|
||||||
|
buttons_str += \
|
||||||
|
'<a href="/users/' + actor_nickname + \
|
||||||
|
'?options=' + follow_url + \
|
||||||
|
';1;' + avatar_url + \
|
||||||
|
'"><button class="buttonunfollow">' + \
|
||||||
|
translate['Move'] + '</button></a>\n'
|
||||||
|
|
||||||
result_str = '<div class="container">\n'
|
result_str = '<div class="container">\n'
|
||||||
result_str += \
|
result_str += \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue