diff --git a/daemon.py b/daemon.py index df9a05c83..391d0cca1 100644 --- a/daemon.py +++ b/daemon.py @@ -176,6 +176,7 @@ from webapp_podcast import html_podcast_episode from webapp_theme_designer import html_theme_designer from webapp_minimalbutton import set_minimal from webapp_minimalbutton import is_minimal +from webapp_utils import get_default_path from webapp_utils import get_avatar_image_url from webapp_utils import html_hashtag_blocked from webapp_utils import html_following_list @@ -272,6 +273,7 @@ from languages import set_actor_languages from languages import get_understood_languages from like import update_likes_collection from reaction import update_reaction_collection +from utils import acct_handle_dir from utils import load_reverse_timeline from utils import save_reverse_timeline from utils import load_min_images_for_accounts @@ -18225,16 +18227,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain, nickname) set_minimal(self.server.base_dir, self.server.domain, nickname, not_min) - if not (self.server.media_instance or - self.server.blogs_instance): - self.path = '/users/' + nickname + '/inbox' - else: - if self.server.blogs_instance: - self.path = '/users/' + nickname + '/tlblogs' - elif self.server.media_instance: - self.path = '/users/' + nickname + '/tlmedia' - else: - self.path = '/users/' + nickname + '/tlfeatures' + self.path = get_default_path(self.server.media_instance, + self.server.blogs_instance, + nickname) # search for a fediverse address, shared item or emoji # from the web interface by selecting search icon @@ -21254,7 +21249,7 @@ class PubServer(BaseHTTPRequestHandler): if not handle: return False if isinstance(handle, str): - person_dir = self.server.base_dir + '/accounts/' + handle + person_dir = acct_handle_dir(self.server.base_dir, handle) if not os.path.isdir(person_dir + '/devices'): return False devices_list = [] @@ -22310,7 +22305,7 @@ def load_tokens(base_dir: str, tokens_dict: {}, tokens_lookup: {}) -> None: for _, dirs, _ in os.walk(base_dir + '/accounts'): for handle in dirs: if '@' in handle: - token_filename = base_dir + '/accounts/' + handle + '/.token' + token_filename = acct_handle_dir(base_dir, handle) + '/.token' if not os.path.isfile(token_filename): continue nickname = handle.split('@')[0] diff --git a/follow.py b/follow.py index 7c9ba3151..db4d59ce2 100644 --- a/follow.py +++ b/follow.py @@ -9,6 +9,7 @@ __module_group__ = "ActivityPub" from pprint import pprint import os +from utils import acct_handle_dir from utils import has_object_string_object from utils import has_object_string_type from utils import remove_domain_port @@ -304,8 +305,9 @@ def unfollow_account(base_dir: str, nickname: str, domain: str, handle_to_unfollow = '!' + handle_to_unfollow if not os.path.isdir(base_dir + '/accounts'): os.mkdir(base_dir + '/accounts') - if not os.path.isdir(base_dir + '/accounts/' + handle): - os.mkdir(base_dir + '/accounts/' + handle) + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): + os.mkdir(handle_dir) accounts_dir = acct_dir(base_dir, nickname, domain) filename = accounts_dir + '/' + follow_file diff --git a/happening.py b/happening.py index e9d460b67..1d479cfe9 100644 --- a/happening.py +++ b/happening.py @@ -13,6 +13,7 @@ from hashlib import md5 from datetime import datetime from datetime import timedelta +from utils import acct_handle_dir from utils import is_public_post from utils import load_json from utils import save_json @@ -94,10 +95,10 @@ def save_event_post(base_dir: str, handle: str, post_id: str, See https://framagit.org/framasoft/mobilizon/-/blob/ master/lib/federation/activity_stream/converter/event.ex """ - if not os.path.isdir(base_dir + '/accounts/' + handle): - print('WARN: Account does not exist at ' + - base_dir + '/accounts/' + handle) - calendar_path = base_dir + '/accounts/' + handle + '/calendar' + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): + print('WARN: Account does not exist at ' + handle_dir) + calendar_path = handle_dir + '/calendar' if not os.path.isdir(calendar_path): os.mkdir(calendar_path) @@ -121,11 +122,11 @@ def save_event_post(base_dir: str, handle: str, post_id: str, print('Mobilizon type event') # if this is a full description of an event then save it # as a separate json file - events_path = base_dir + '/accounts/' + handle + '/events' + events_path = handle_dir + '/events' if not os.path.isdir(events_path): os.mkdir(events_path) events_year_path = \ - base_dir + '/accounts/' + handle + '/events/' + str(event_year) + handle_dir + '/events/' + str(event_year) if not os.path.isdir(events_year_path): os.mkdir(events_year_path) event_id = str(event_year) + '-' + event_time.strftime("%m") + '-' + \ @@ -134,7 +135,7 @@ def save_event_post(base_dir: str, handle: str, post_id: str, save_json(event_json, event_filename) # save to the events timeline - tl_events_filename = base_dir + '/accounts/' + handle + '/events.txt' + tl_events_filename = handle_dir + '/events.txt' if os.path.isfile(tl_events_filename): _remove_event_from_timeline(event_id, tl_events_filename) @@ -180,7 +181,7 @@ def save_event_post(base_dir: str, handle: str, post_id: str, # create a file which will trigger a notification that # a new event has been added - cal_notify_filename = base_dir + '/accounts/' + handle + '/.newCalendar' + cal_notify_filename = handle_dir + '/.newCalendar' notify_str = \ '/calendar?year=' + str(event_year) + '?month=' + \ str(event_month_number) + '?day=' + str(event_day_of_month) @@ -962,7 +963,8 @@ def _dav_store_event(base_dir: str, nickname: str, domain: str, "name": location }) handle = nickname + '@' + domain - outbox_dir = base_dir + '/accounts/' + handle + '/outbox' + handle_dir = acct_handle_dir(base_dir, handle) + outbox_dir = handle_dir + '/outbox' if not os.path.isdir(outbox_dir): return False filename = outbox_dir + '/' + post_id.replace('/', '#') + '.json' diff --git a/inbox.py b/inbox.py index 56f22cff6..380290536 100644 --- a/inbox.py +++ b/inbox.py @@ -18,6 +18,7 @@ from languages import understood_post_language from like import update_likes_collection from reaction import update_reaction_collection from reaction import valid_emoji_content +from utils import acct_handle_dir from utils import is_account_dir from utils import remove_eol from utils import text_in_file @@ -800,7 +801,8 @@ def _inbox_post_recipients_add(base_dir: str, http_prefix: str, to_list: [], # get the handle for the account on this instance nickname = recipient.split(domain_match)[1] handle = nickname + '@' + domain - if os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if os.path.isdir(handle_dir): recipients_dict[handle] = None else: if debug: @@ -1518,7 +1520,8 @@ def _receive_like(recent_posts_cache: {}, print('DEBUG: "statuses" missing from object in ' + message_json['type']) return False - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('DEBUG: unknown recipient of like - ' + handle) # if this post in the outbox of the person? handle_name = handle.split('@')[0] @@ -1652,7 +1655,8 @@ def _receive_undo_like(recent_posts_cache: {}, print('DEBUG: "statuses" missing from like object in ' + message_json['type']) return False - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('DEBUG: unknown recipient of undo like - ' + handle) # if this post in the outbox of the person? handle_name = handle.split('@')[0] @@ -1785,10 +1789,10 @@ def _receive_reaction(recent_posts_cache: {}, print('DEBUG: "statuses" missing from object in ' + message_json['type']) return False - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('DEBUG: unknown recipient of emoji reaction - ' + handle) - if os.path.isfile(base_dir + '/accounts/' + handle + - '/.hideReactionButton'): + if os.path.isfile(handle_dir + '/.hideReactionButton'): print('Emoji reaction rejected by ' + handle + ' due to their settings') return True @@ -1965,10 +1969,10 @@ def _receive_zot_reaction(recent_posts_cache: {}, print('DEBUG: "statuses" missing from inReplyTo in ' + message_json['object']['type']) return False - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('DEBUG: unknown recipient of zot emoji reaction - ' + handle) - if os.path.isfile(base_dir + '/accounts/' + handle + - '/.hideReactionButton'): + if os.path.isfile(handle_dir + '/.hideReactionButton'): print('Zot emoji reaction rejected by ' + handle + ' due to their settings') return True @@ -2124,7 +2128,8 @@ def _receive_undo_reaction(recent_posts_cache: {}, print('DEBUG: "statuses" missing from reaction object in ' + message_json['type']) return False - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('DEBUG: unknown recipient of undo reaction - ' + handle) # if this post in the outbox of the person? handle_name = handle.split('@')[0] @@ -2504,7 +2509,8 @@ def _receive_delete(session, handle: str, is_group: bool, base_dir: str, if message_json['actor'] not in message_json['object']: if debug: print('DEBUG: actor is not the owner of the post to be deleted') - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('DEBUG: unknown recipient of like - ' + handle) # if this post in the outbox of the person? message_id = remove_id_ending(message_json['object']) @@ -2604,7 +2610,8 @@ def _receive_announce(recent_posts_cache: {}, if debug: print('DEBUG: announced domain is blocked') return False - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('DEBUG: unknown recipient of announce - ' + handle) # is the announce actor blocked? @@ -2825,7 +2832,8 @@ def _receive_undo_announce(recent_posts_cache: {}, print('DEBUG: "users" or "profile" missing from actor in ' + message_json['type'] + ' announce') return False - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('DEBUG: unknown recipient of undo announce - ' + handle) # if this post in the outbox of the person? handle_name = handle.split('@')[0] @@ -3176,7 +3184,7 @@ def _obtain_avatar_for_reply_post(session, base_dir: str, http_prefix: str, def _dm_notify(base_dir: str, handle: str, url: str) -> None: """Creates a notification that a new DM has arrived """ - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) if not os.path.isdir(account_dir): return dm_file = account_dir + '/.newDM' @@ -3272,7 +3280,7 @@ def _like_notify(base_dir: str, domain: str, if not i2p_domain and not onion_domain: return - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) # are like notifications enabled? notify_likes_enabled_filename = account_dir + '/.notifyLikes' @@ -3335,7 +3343,7 @@ def _reaction_notify(base_dir: str, domain: str, onion_domain: str, if '/' + onion_domain + '/users/' + nickname not in url: return - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) # are reaction notifications enabled? notify_reaction_enabled_filename = account_dir + '/.notifyReactions' @@ -3388,7 +3396,7 @@ def _notify_post_arrival(base_dir: str, handle: str, url: str) -> None: This is for followed accounts with the notify checkbox enabled on the person options screen """ - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) if not os.path.isdir(account_dir): return notify_file = account_dir + '/.newNotifiedPost' @@ -3408,7 +3416,7 @@ def _notify_post_arrival(base_dir: str, handle: str, url: str) -> None: def _reply_notify(base_dir: str, handle: str, url: str) -> None: """Creates a notification that a new reply has arrived """ - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) if not os.path.isdir(account_dir): return reply_file = account_dir + '/.newReply' @@ -3424,7 +3432,7 @@ def _git_patch_notify(base_dir: str, handle: str, subject: str, from_nickname: str, from_domain: str) -> None: """Creates a notification that a new git patch has arrived """ - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) if not os.path.isdir(account_dir): return patch_file = account_dir + '/.newPatch' @@ -3440,7 +3448,7 @@ def _git_patch_notify(base_dir: str, handle: str, subject: str, def _group_handle(base_dir: str, handle: str) -> bool: """Is the given account handle a group? """ - actor_file = base_dir + '/accounts/' + handle + '.json' + actor_file = acct_handle_dir(base_dir, handle) + '.json' if not os.path.isfile(actor_file): return False actor_json = load_json(actor_file) @@ -3478,7 +3486,7 @@ def _send_to_group_members(server, session, session_onion, session_i2p, domain_str = shared_federated_domain.strip() shared_items_federated_domains.append(domain_str) - followers_file = base_dir + '/accounts/' + handle + '/followers.txt' + followers_file = acct_handle_dir(base_dir, handle) + '/followers.txt' if not os.path.isfile(followers_file): return if not post_json_object.get('to'): @@ -3572,7 +3580,7 @@ def inbox_update_index(boxname: str, base_dir: str, handle: str, The new entry is added to the top of the file """ index_filename = \ - base_dir + '/accounts/' + handle + '/' + boxname + '.index' + acct_handle_dir(base_dir, handle) + '/' + boxname + '.index' if debug: print('DEBUG: Updating index ' + index_filename) @@ -5124,10 +5132,11 @@ def _receive_follow_request(session, session_onion, session_i2p, return True handle_to_follow = nickname_to_follow + '@' + domain_to_follow if domain_to_follow == domain: - if not os.path.isdir(base_dir + '/accounts/' + handle_to_follow): + handle_dir = acct_handle_dir(base_dir, handle_to_follow) + if not os.path.isdir(handle_dir): if debug: print('DEBUG: followed account not found - ' + - base_dir + '/accounts/' + handle_to_follow) + handle_dir) return True is_already_follower = False @@ -5891,7 +5900,7 @@ def run_inbox_queue(server, mitm = True bold_reading = False bold_reading_filename = \ - base_dir + '/accounts/' + handle + '/.boldReading' + acct_handle_dir(base_dir, handle) + '/.boldReading' if os.path.isfile(bold_reading_filename): bold_reading = True _inbox_after_initial(server, inbox_start_time, diff --git a/manualapprove.py b/manualapprove.py index 9d035ddc9..e8579a1ce 100644 --- a/manualapprove.py +++ b/manualapprove.py @@ -11,6 +11,7 @@ import os from follow import followed_account_accepts from follow import followed_account_rejects from follow import remove_from_follow_requests +from utils import acct_handle_dir from utils import load_json from utils import remove_domain_port from utils import get_port_from_domain @@ -149,7 +150,7 @@ def manual_approve_follow_request(session, session_onion, session_i2p, handle = nickname + '@' + domain print('Manual follow accept: ' + handle + ' approving follow request from ' + approve_handle) - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) approve_follows_filename = account_dir + '/followrequests.txt' if not os.path.isfile(approve_follows_filename): print('Manual follow accept: follow requests file ' + diff --git a/newswire.py b/newswire.py index 600a7624a..56e667bc4 100644 --- a/newswire.py +++ b/newswire.py @@ -20,6 +20,7 @@ from datetime import timezone from collections import OrderedDict from utils import valid_post_date from categories import set_hashtag_category +from utils import acct_handle_dir from utils import remove_eol from utils import get_domain_from_actor from utils import valid_hash_tag @@ -1538,8 +1539,8 @@ def _add_blogs_to_newswire(base_dir: str, domain: str, newswire: {}, if is_suspended(base_dir, nickname): continue - if os.path.isfile(base_dir + '/accounts/' + handle + - '/.nonewswire'): + handle_dir = acct_handle_dir(base_dir, handle) + if os.path.isfile(handle_dir + '/.nonewswire'): continue # is there a blogs timeline for this account? diff --git a/person.py b/person.py index f821f009c..df74db97c 100644 --- a/person.py +++ b/person.py @@ -38,6 +38,7 @@ from roles import set_role from roles import actor_roles_from_list from roles import get_actor_roles_list from media import process_meta_data +from utils import acct_handle_dir from utils import safe_system_string from utils import get_attachment_property_value from utils import get_nickname_from_actor @@ -117,12 +118,13 @@ def set_profile_image(base_dir: str, http_prefix: str, full_domain = get_full_domain(domain, port) handle = nickname + '@' + domain - person_filename = base_dir + '/accounts/' + handle + '.json' + person_filename = acct_handle_dir(base_dir, handle) + '.json' if not os.path.isfile(person_filename): print('person definition not found: ' + person_filename) return False - if not os.path.isdir(base_dir + '/accounts/' + handle): - print('Account not found: ' + base_dir + '/accounts/' + handle) + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): + print('Account not found: ' + handle_dir) return False icon_filename_base = 'icon' @@ -155,7 +157,7 @@ def set_profile_image(base_dir: str, http_prefix: str, elif image_filename.endswith('.svg'): media_type = 'image/svg+xml' icon_filename = icon_filename_base + '.svg' - profile_filename = base_dir + '/accounts/' + handle + '/' + icon_filename + profile_filename = acct_handle_dir(base_dir, handle) + '/' + icon_filename person_json = load_json(person_filename) if person_json: @@ -957,7 +959,7 @@ def person_lookup(domain: str, path: str, base_dir: str) -> {}: return None domain = remove_domain_port(domain) handle = nickname + '@' + domain - filename = base_dir + '/accounts/' + handle + '.json' + filename = acct_handle_dir(base_dir, handle) + '.json' if not os.path.isfile(filename): return None person_json = load_json(filename) @@ -1087,7 +1089,7 @@ def set_display_nickname(base_dir: str, nickname: str, domain: str, if len(display_name) > 32: return False handle = nickname + '@' + domain - filename = base_dir + '/accounts/' + handle + '.json' + filename = acct_handle_dir(base_dir, handle) + '.json' if not os.path.isfile(filename): return False @@ -1105,7 +1107,7 @@ def set_bio(base_dir: str, nickname: str, domain: str, bio: str) -> bool: if len(bio) > 32: return False handle = nickname + '@' + domain - filename = base_dir + '/accounts/' + handle + '.json' + filename = acct_handle_dir(base_dir, handle) + '.json' if not os.path.isfile(filename): return False @@ -1280,15 +1282,16 @@ def remove_account(base_dir: str, nickname: str, if os.path.isdir(base_dir + '/deactivated/' + handle): shutil.rmtree(base_dir + '/deactivated/' + handle, ignore_errors=False, onerror=None) - if os.path.isdir(base_dir + '/accounts/' + handle): - shutil.rmtree(base_dir + '/accounts/' + handle, + handle_dir = acct_handle_dir(base_dir, handle) + if os.path.isdir(handle_dir): + shutil.rmtree(handle_dir, ignore_errors=False, onerror=None) - if os.path.isfile(base_dir + '/accounts/' + handle + '.json'): + if os.path.isfile(handle_dir + '.json'): try: - os.remove(base_dir + '/accounts/' + handle + '.json') + os.remove(handle_dir + '.json') except OSError: print('EX: remove_account unable to delete ' + - base_dir + '/accounts/' + handle + '.json') + handle_dir + '.json') if os.path.isfile(base_dir + '/wfendpoints/' + handle + '.json'): try: os.remove(base_dir + '/wfendpoints/' + handle + '.json') @@ -1330,7 +1333,7 @@ def deactivate_account(base_dir: str, nickname: str, domain: str) -> bool: """ handle = nickname + '@' + domain - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) if not os.path.isdir(account_dir): return False deactivated_dir = base_dir + '/deactivated' @@ -1365,7 +1368,7 @@ def activate_account(base_dir: str, nickname: str, domain: str) -> None: deactivated_dir = base_dir + '/deactivated' deactivated_account_dir = deactivated_dir + '/' + handle if os.path.isdir(deactivated_account_dir): - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) if not os.path.isdir(account_dir): shutil.move(deactivated_account_dir, account_dir) diff --git a/posts.py b/posts.py index 851d0dbc7..7db8e8824 100644 --- a/posts.py +++ b/posts.py @@ -32,6 +32,7 @@ from webfinger import webfinger_handle from httpsig import create_signed_header from siteactive import site_is_active from languages import understood_post_language +from utils import acct_handle_dir from utils import is_dm from utils import remove_eol from utils import text_in_file @@ -134,7 +135,7 @@ def no_of_followers_on_domain(base_dir: str, handle: str, """Returns the number of followers of the given handle from the given domain """ - filename = base_dir + '/accounts/' + handle + '/' + follow_file + filename = acct_handle_dir(base_dir, handle) + '/' + follow_file if not os.path.isfile(filename): return 0 @@ -1022,7 +1023,7 @@ def _add_schedule_post(base_dir: str, nickname: str, domain: str, """ handle = nickname + '@' + domain schedule_index_filename = \ - base_dir + '/accounts/' + handle + '/schedule.index' + acct_handle_dir(base_dir, handle) + '/schedule.index' index_str = event_date_str + ' ' + post_id.replace('/', '#') if os.path.isfile(schedule_index_filename): @@ -2150,7 +2151,8 @@ def get_mentioned_people(base_dir: str, http_prefix: str, print('DEBUG: mentioned handle ' + handle) if '@' not in handle: handle = handle + '@' + domain - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): continue else: external_domain = handle.split('@')[1] @@ -2322,7 +2324,7 @@ def create_report_post(base_dir: str, # save a notification file so that the moderator # knows something new has appeared - new_report_file = base_dir + '/accounts/' + handle + '/.newReport' + new_report_file = acct_handle_dir(base_dir, handle) + '/.newReport' if os.path.isfile(new_report_file): continue try: @@ -2745,7 +2747,7 @@ def group_followers_by_domain(base_dir: str, nickname: str, domain: str) -> {}: """Returns a dictionary with followers grouped by domain """ handle = nickname + '@' + domain - followers_filename = base_dir + '/accounts/' + handle + '/followers.txt' + followers_filename = acct_handle_dir(base_dir, handle) + '/followers.txt' if not os.path.isfile(followers_filename): return None grouped = {} @@ -4353,18 +4355,14 @@ def archive_posts(base_dir: str, http_prefix: str, archive_dir: str, domain = handle.split('@')[1] archive_subdir = None if archive_dir: - if not os.path.isdir(archive_dir + '/accounts/' + handle): - os.mkdir(archive_dir + '/accounts/' + handle) - if not os.path.isdir(archive_dir + '/accounts/' + - handle + '/inbox'): - os.mkdir(archive_dir + '/accounts/' + - handle + '/inbox') - if not os.path.isdir(archive_dir + '/accounts/' + - handle + '/outbox'): - os.mkdir(archive_dir + '/accounts/' + - handle + '/outbox') - archive_subdir = archive_dir + '/accounts/' + \ - handle + '/inbox' + archive_handle_dir = acct_handle_dir(archive_dir, handle) + if not os.path.isdir(archive_handle_dir): + os.mkdir(archive_handle_dir) + if not os.path.isdir(archive_handle_dir + '/inbox'): + os.mkdir(archive_handle_dir + '/inbox') + if not os.path.isdir(archive_handle_dir + '/outbox'): + os.mkdir(archive_handle_dir + '/outbox') + archive_subdir = archive_handle_dir + '/inbox' archive_posts_for_person(http_prefix, nickname, domain, base_dir, 'inbox', archive_subdir, @@ -4443,7 +4441,7 @@ def get_post_expiry_keep_dms(base_dir: str, nickname: str, domain: str) -> int: keep_dms = True handle = nickname + '@' + domain expire_dms_filename = \ - base_dir + '/accounts/' + handle + '/.expire_posts_dms' + acct_handle_dir(base_dir, handle) + '/.expire_posts_dms' if os.path.isfile(expire_dms_filename): keep_dms = False return keep_dms @@ -4455,7 +4453,7 @@ def set_post_expiry_keep_dms(base_dir: str, nickname: str, domain: str, """ handle = nickname + '@' + domain expire_dms_filename = \ - base_dir + '/accounts/' + handle + '/.expire_posts_dms' + acct_handle_dir(base_dir, handle) + '/.expire_posts_dms' if keep_dms: if os.path.isfile(expire_dms_filename): try: @@ -4484,7 +4482,7 @@ def expire_posts(base_dir: str, http_prefix: str, nickname = handle.split('@')[0] domain = handle.split('@')[1] expire_posts_filename = \ - base_dir + '/accounts/' + handle + '/.expire_posts_days' + acct_handle_dir(base_dir, handle) + '/.expire_posts_days' if not os.path.isfile(expire_posts_filename): continue keep_dms = get_post_expiry_keep_dms(base_dir, nickname, domain) @@ -4519,7 +4517,7 @@ def get_post_expiry_days(base_dir: str, nickname: str, domain: str) -> int: """ handle = nickname + '@' + domain expire_posts_filename = \ - base_dir + '/accounts/' + handle + '/.expire_posts_days' + acct_handle_dir(base_dir, handle) + '/.expire_posts_days' if not os.path.isfile(expire_posts_filename): return 0 days_str = None @@ -4542,7 +4540,7 @@ def set_post_expiry_days(base_dir: str, nickname: str, domain: str, """ handle = nickname + '@' + domain expire_posts_filename = \ - base_dir + '/accounts/' + handle + '/.expire_posts_days' + acct_handle_dir(base_dir, handle) + '/.expire_posts_days' try: with open(expire_posts_filename, 'w+', encoding='utf-8') as fp_expire: fp_expire.write(str(max_age_days)) @@ -4577,7 +4575,7 @@ def archive_posts_for_person(http_prefix: str, nickname: str, domain: str, # remove entries from the index handle = nickname + '@' + domain index_filename = \ - base_dir + '/accounts/' + handle + '/' + boxname + '.index' + acct_handle_dir(base_dir, handle) + '/' + boxname + '.index' if os.path.isfile(index_filename): index_ctr = 0 # get the existing index entries as a string diff --git a/schedule.py b/schedule.py index 86a7ab0b9..04960e032 100644 --- a/schedule.py +++ b/schedule.py @@ -10,6 +10,7 @@ __module_group__ = "Calendar" import os import time import datetime +from utils import acct_handle_dir from utils import has_object_dict from utils import get_status_number from utils import load_json @@ -27,7 +28,7 @@ def _update_post_schedule(base_dir: str, handle: str, httpd, the outbox """ schedule_index_filename = \ - base_dir + '/accounts/' + handle + '/schedule.index' + acct_handle_dir(base_dir, handle) + '/schedule.index' if not os.path.isfile(schedule_index_filename): return @@ -35,7 +36,7 @@ def _update_post_schedule(base_dir: str, handle: str, httpd, curr_time = datetime.datetime.utcnow() days_since_epoch = (curr_time - datetime.datetime(1970, 1, 1)).days - schedule_dir = base_dir + '/accounts/' + handle + '/scheduled/' + schedule_dir = acct_handle_dir(base_dir, handle) + '/scheduled/' index_lines = [] delete_schedule_post = False nickname = handle.split('@')[0] @@ -168,7 +169,7 @@ def _update_post_schedule(base_dir: str, handle: str, httpd, # write the new schedule index file schedule_index_file = \ - base_dir + '/accounts/' + handle + '/schedule.index' + acct_handle_dir(base_dir, handle) + '/schedule.index' with open(schedule_index_file, 'w+', encoding='utf-8') as schedule_file: for line in index_lines: schedule_file.write(line) diff --git a/scripts/blocked b/scripts/blocked index 7dffe76b0..31cdfcde0 100755 --- a/scripts/blocked +++ b/scripts/blocked @@ -1,5 +1,5 @@ #!/bin/bash -journalctl -u epicyon | grep 'getJson Forbidden ' > .blocked_events.txt +journalctl -u epicyon | grep 'get_json Forbidden ' > .blocked_events.txt if [ ! -f .blocked_events.txt ]; then echo 'No blocking events' else diff --git a/shares.py b/shares.py index 06dff55db..2feaef84e 100644 --- a/shares.py +++ b/shares.py @@ -22,6 +22,7 @@ from posts import get_person_box from session import post_json from session import post_image from session import create_session +from utils import acct_handle_dir from utils import remove_eol from utils import has_object_string_type from utils import date_string_to_seconds @@ -275,7 +276,7 @@ def _indicate_new_share_available(base_dir: str, http_prefix: str, for handle in dirs: if not is_account_dir(handle): continue - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) if shares_file_type == 'shares': new_share_file = account_dir + '/.newShare' else: @@ -421,7 +422,7 @@ def _expire_shares_for_account(base_dir: str, nickname: str, domain: str, handle_domain = remove_domain_port(domain) handle = nickname + '@' + handle_domain shares_filename = \ - base_dir + '/accounts/' + handle + '/' + shares_file_type + '.json' + acct_handle_dir(base_dir, handle) + '/' + shares_file_type + '.json' if not os.path.isfile(shares_filename): return shares_json = load_json(shares_filename, 1, 2) diff --git a/utils.py b/utils.py index a3f4723df..a6261426b 100644 --- a/utils.py +++ b/utils.py @@ -290,6 +290,10 @@ def acct_dir(base_dir: str, nickname: str, domain: str) -> str: return base_dir + '/accounts/' + nickname + '@' + domain +def acct_handle_dir(base_dir: str, handle: str) -> str: + return base_dir + '/accounts/' + handle + + def is_featured_writer(base_dir: str, nickname: str, domain: str) -> bool: """Is the given account a featured writer, appearing in the features timeline on news instances? @@ -749,7 +753,8 @@ def get_followers_of_person(base_dir: str, followers = [] domain = remove_domain_port(domain) handle = nickname + '@' + domain - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): return followers for subdir, dirs, _ in os.walk(base_dir + '/accounts'): for account in dirs: @@ -981,9 +986,10 @@ def create_person_dir(nickname: str, domain: str, base_dir: str, """Create a directory for a person """ handle = nickname + '@' + domain - if not os.path.isdir(base_dir + '/accounts/' + handle): - os.mkdir(base_dir + '/accounts/' + handle) - box_dir = base_dir + '/accounts/' + handle + '/' + dir_name + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): + os.mkdir(handle_dir) + box_dir = acct_handle_dir(base_dir, handle) + '/' + dir_name if not os.path.isdir(box_dir): os.mkdir(box_dir) return box_dir @@ -1450,7 +1456,8 @@ def follow_person(base_dir: str, nickname: str, domain: str, else: handle = nickname + '@' + domain - if not os.path.isdir(base_dir + '/accounts/' + handle): + handle_dir = acct_handle_dir(base_dir, handle) + if not os.path.isdir(handle_dir): print('WARN: account for ' + handle + ' does not exist') return False @@ -1464,7 +1471,7 @@ def follow_person(base_dir: str, nickname: str, domain: str, handle_to_follow = '!' + handle_to_follow # was this person previously unfollowed? - unfollowed_filename = base_dir + '/accounts/' + handle + '/unfollowed.txt' + unfollowed_filename = acct_handle_dir(base_dir, handle) + '/unfollowed.txt' if os.path.isfile(unfollowed_filename): if text_in_file(handle_to_follow, unfollowed_filename): # remove them from the unfollowed file @@ -1484,7 +1491,7 @@ def follow_person(base_dir: str, nickname: str, domain: str, handle_to_follow = follow_nickname + '@' + follow_domain if group_account: handle_to_follow = '!' + handle_to_follow - filename = base_dir + '/accounts/' + handle + '/' + follow_file + filename = acct_handle_dir(base_dir, handle) + '/' + follow_file if os.path.isfile(filename): if text_in_file(handle_to_follow, filename): if debug: @@ -3816,7 +3823,7 @@ def get_account_timezone(base_dir: str, nickname: str, domain: str) -> str: """Returns the timezone for the given account """ tz_filename = \ - base_dir + '/accounts/' + nickname + '@' + domain + '/timezone.txt' + acct_dir(base_dir, nickname, domain) + '/timezone.txt' if not os.path.isfile(tz_filename): return None timezone = None @@ -3830,7 +3837,7 @@ def set_account_timezone(base_dir: str, nickname: str, domain: str, """Sets the timezone for the given account """ tz_filename = \ - base_dir + '/accounts/' + nickname + '@' + domain + '/timezone.txt' + acct_dir(base_dir, nickname, domain) + '/timezone.txt' timezone = timezone.strip() with open(tz_filename, 'w+', encoding='utf-8') as fp_timezone: fp_timezone.write(timezone) diff --git a/webapp_profile.py b/webapp_profile.py index 08b39d6fb..4a30a3749 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -2158,9 +2158,9 @@ def _html_edit_notifications(base_dir: str, nickname: str, domain: str, ntfy_topic = '' ntfy_url_file = \ - base_dir + '/accounts/' + nickname + '@' + domain + '/.ntfy_url' + acct_dir(base_dir, nickname, domain) + '/.ntfy_url' ntfy_topic_file = \ - base_dir + '/accounts/' + nickname + '@' + domain + '/.ntfy_topic' + acct_dir(base_dir, nickname, domain) + '/.ntfy_topic' if os.path.isfile(ntfy_url_file): try: with open(ntfy_url_file, 'r', encoding='utf-8') as fp_ntfy: diff --git a/webapp_search.py b/webapp_search.py index 8f94cd0b1..97be7ba07 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -11,6 +11,7 @@ import os from shutil import copyfile import urllib.parse from datetime import datetime +from utils import acct_handle_dir from utils import get_base_content_from_post from utils import is_account_dir from utils import get_config_param @@ -299,7 +300,7 @@ def html_search_shared_items(translate: {}, if not is_account_dir(handle): continue contact_nickname = handle.split('@')[0] - shares_filename = base_dir + '/accounts/' + handle + \ + shares_filename = acct_handle_dir(base_dir, handle) + \ '/' + shares_file_type + '.json' if not os.path.isfile(shares_filename): continue diff --git a/webapp_utils.py b/webapp_utils.py index c818cff63..377233fa6 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -11,6 +11,7 @@ import os from shutil import copyfile from collections import OrderedDict from session import get_json +from utils import acct_handle_dir from utils import remove_id_ending from utils import get_attachment_property_value from utils import is_account_dir @@ -464,7 +465,7 @@ def shares_timeline_json(actor: str, pageNumber: int, items_per_page: int, for handle in dirs: if not is_account_dir(handle): continue - account_dir = base_dir + '/accounts/' + handle + account_dir = acct_handle_dir(base_dir, handle) shares_filename = account_dir + '/' + shares_file_type + '.json' if not os.path.isfile(shares_filename): continue @@ -1953,3 +1954,16 @@ def language_right_to_left(language: str) -> bool: if language in rtl_languages: return True return False + + +def get_default_path(media_instance: bool, blogs_instance: bool, + nickname: str) -> str: + """Returns the default timeline + """ + if blogs_instance: + path = '/users/' + nickname + '/tlblogs' + elif media_instance: + path = '/users/' + nickname + '/tlmedia' + else: + path = '/users/' + nickname + '/inbox' + return path diff --git a/webfinger.py b/webfinger.py index 4f97ff4bb..7235ed909 100644 --- a/webfinger.py +++ b/webfinger.py @@ -12,6 +12,7 @@ import urllib.parse from session import get_json from cache import store_webfinger_in_cache from cache import get_webfinger_from_cache +from utils import acct_handle_dir from utils import get_attachment_property_value from utils import get_full_domain from utils import load_json @@ -520,7 +521,7 @@ def webfinger_update(base_dir: str, nickname: str, domain: str, if not wf_json: return - actor_filename = base_dir + '/accounts/' + handle + '.json' + actor_filename = acct_handle_dir(base_dir, handle) + '.json' actor_json = load_json(actor_filename) if not actor_json: return