Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon

main
Bob Mottram 2021-07-05 11:09:55 +01:00
commit c23bbdff2e
4 changed files with 188 additions and 138 deletions

View File

@ -26,6 +26,7 @@ from posts import getPersonBox
from utils import loadJson from utils import loadJson
from utils import saveJson from utils import saveJson
from utils import isAccountDir from utils import isAccountDir
from utils import getUserPaths
from acceptreject import createAccept from acceptreject import createAccept
from acceptreject import createReject from acceptreject import createReject
from webfinger import webfingerHandle from webfinger import webfingerHandle
@ -221,7 +222,7 @@ def isFollowerOfPerson(baseDir: str, nickname: str, domain: str,
if handle in followersStr: if handle in followersStr:
alreadyFollowing = True alreadyFollowing = True
else: else:
paths = ('/profile/', '/channel/', '/accounts/', '/u/') paths = getUserPaths()
for userPath in paths: for userPath in paths:
url = '://' + followerDomain + userPath + followerNickname url = '://' + followerDomain + userPath + followerNickname
if url in followersStr: if url in followersStr:

View File

@ -14,6 +14,7 @@ from follow import removeFromFollowRequests
from utils import loadJson from utils import loadJson
from utils import removeDomainPort from utils import removeDomainPort
from utils import getPortFromDomain from utils import getPortFromDomain
from utils import getUserPaths
def manualDenyFollowRequest(session, baseDir: str, def manualDenyFollowRequest(session, baseDir: str,
@ -111,7 +112,7 @@ def manualApproveFollowRequest(session, baseDir: str,
reqNick = approveHandle.split('@')[0] reqNick = approveHandle.split('@')[0]
reqDomain = approveHandle.split('@')[1].strip() reqDomain = approveHandle.split('@')[1].strip()
reqPrefix = httpPrefix + '://' + reqDomain reqPrefix = httpPrefix + '://' + reqDomain
paths = ('/profile/', '/channel/', '/accounts/', '/u/') paths = getUserPaths()
for userPath in paths: for userPath in paths:
if reqPrefix + userPath + reqNick in approveFollowsStr: if reqPrefix + userPath + reqNick in approveFollowsStr:
exists = True exists = True

View File

@ -50,6 +50,7 @@ from utils import getProtocolPrefixes
from utils import hasUsersPath from utils import hasUsersPath
from utils import getImageExtensions from utils import getImageExtensions
from utils import isImageFile from utils import isImageFile
from utils import getUserPaths
from session import createSession from session import createSession
from session import getJson from session import getJson
from webfinger import webfingerHandle from webfinger import webfingerHandle
@ -1211,9 +1212,7 @@ def getActorJson(hostDomain: str, handle: str, http: bool, gnunet: bool,
for prefix in prefixes: for prefix in prefixes:
handle = handle.replace(prefix, '') handle = handle.replace(prefix, '')
handle = handle.replace('/@', '/users/') handle = handle.replace('/@', '/users/')
paths = ( paths = getUserPaths()
'/users/', '/profile/', '/channel/', '/accounts/', '/u/'
)
userPathFound = False userPathFound = False
for userPath in paths: for userPath in paths:
if userPath in handle: if userPath in handle:
@ -1302,11 +1301,9 @@ def getActorJson(hostDomain: str, handle: str, http: bool, gnunet: bool,
if not personUrl: if not personUrl:
personUrl = getUserUrl(wfRequest, 0, debug) personUrl = getUserUrl(wfRequest, 0, debug)
if nickname == domain: if nickname == domain:
personUrl = personUrl.replace('/users/', '/actor/') paths = getUserPaths()
personUrl = personUrl.replace('/accounts/', '/actor/') for userPath in paths:
personUrl = personUrl.replace('/channel/', '/actor/') personUrl = personUrl.replace(userPath, '/actor/')
personUrl = personUrl.replace('/profile/', '/actor/')
personUrl = personUrl.replace('/u/', '/actor/')
if not personUrl: if not personUrl:
# try single user instance # try single user instance
personUrl = httpPrefix + '://' + domain + '/' + nickname personUrl = httpPrefix + '://' + domain + '/' + nickname

307
utils.py
View File

@ -842,7 +842,7 @@ def getNicknameFromActor(actor: str) -> str:
""" """
if actor.startswith('@'): if actor.startswith('@'):
actor = actor[1:] actor = actor[1:]
usersPaths = ('/users/', '/profile/', '/channel/', '/accounts/', '/u/') usersPaths = getUserPaths()
for possiblePath in usersPaths: for possiblePath in usersPaths:
if possiblePath in actor: if possiblePath in actor:
nickStr = actor.split(possiblePath)[1].replace('@', '') nickStr = actor.split(possiblePath)[1].replace('@', '')
@ -872,6 +872,12 @@ def getNicknameFromActor(actor: str) -> str:
return None return None
def getUserPaths() -> []:
"""Returns possible user paths
"""
return ('/users/', '/profile/', '/accounts/', '/channel/', '/u/')
def getDomainFromActor(actor: str) -> (str, int): def getDomainFromActor(actor: str) -> (str, int):
"""Returns the domain name from an actor url """Returns the domain name from an actor url
""" """
@ -879,7 +885,7 @@ def getDomainFromActor(actor: str) -> (str, int):
actor = actor[1:] actor = actor[1:]
port = None port = None
prefixes = getProtocolPrefixes() prefixes = getProtocolPrefixes()
usersPaths = ('/users/', '/profile/', '/accounts/', '/channel/', '/u/') usersPaths = getUserPaths()
for possiblePath in usersPaths: for possiblePath in usersPaths:
if possiblePath in actor: if possiblePath in actor:
domain = actor.split(possiblePath)[0] domain = actor.split(possiblePath)[0]
@ -1222,125 +1228,193 @@ def _isReplyToBlogPost(baseDir: str, nickname: str, domain: str,
return False return False
def _deletePostRemoveReplies(baseDir: str, nickname: str, domain: str,
httpPrefix: str, postFilename: str,
recentPostsCache: {}, debug: bool) -> None:
"""Removes replies when deleting a post
"""
repliesFilename = postFilename.replace('.json', '.replies')
if not os.path.isfile(repliesFilename):
return
if debug:
print('DEBUG: removing replies to ' + postFilename)
with open(repliesFilename, 'r') as f:
for replyId in f:
replyFile = locatePost(baseDir, nickname, domain, replyId)
if not replyFile:
continue
if os.path.isfile(replyFile):
deletePost(baseDir, httpPrefix,
nickname, domain, replyFile, debug,
recentPostsCache)
# remove the replies file
os.remove(repliesFilename)
def _isBookmarked(baseDir: str, nickname: str, domain: str,
postFilename: str) -> bool:
"""Returns True if the given post is bookmarked
"""
bookmarksIndexFilename = \
baseDir + '/accounts/' + nickname + '@' + domain + \
'/bookmarks.index'
if os.path.isfile(bookmarksIndexFilename):
bookmarkIndex = postFilename.split('/')[-1] + '\n'
if bookmarkIndex in open(bookmarksIndexFilename).read():
return True
return False
def removePostFromCache(postJsonObject: {}, recentPostsCache: {}) -> None:
""" if the post exists in the recent posts cache then remove it
"""
if not recentPostsCache:
return
if not postJsonObject.get('id'):
return
if not recentPostsCache.get('index'):
return
postId = postJsonObject['id']
if '#' in postId:
postId = postId.split('#', 1)[0]
postId = removeIdEnding(postId).replace('/', '#')
if postId not in recentPostsCache['index']:
return
if recentPostsCache.get('index'):
if postId in recentPostsCache['index']:
recentPostsCache['index'].remove(postId)
if recentPostsCache.get('json'):
if recentPostsCache['json'].get(postId):
del recentPostsCache['json'][postId]
if recentPostsCache.get('html'):
if recentPostsCache['html'].get(postId):
del recentPostsCache['html'][postId]
def _deleteCachedHtml(baseDir: str, nickname: str, domain: str,
postJsonObject: {}):
"""Removes cached html file for the given post
"""
cachedPostFilename = \
getCachedPostFilename(baseDir, nickname, domain, postJsonObject)
if cachedPostFilename:
if os.path.isfile(cachedPostFilename):
os.remove(cachedPostFilename)
def _deleteHashtagsOnPost(baseDir: str, postJsonObject: {}) -> None:
"""Removes hashtags when a post is deleted
"""
removeHashtagIndex = False
if hasObjectDict(postJsonObject):
if postJsonObject['object'].get('content'):
if '#' in postJsonObject['object']['content']:
removeHashtagIndex = True
if not removeHashtagIndex:
return
if not postJsonObject['object'].get('id') or \
not postJsonObject['object'].get('tag'):
return
# get the id of the post
postId = removeIdEnding(postJsonObject['object']['id'])
for tag in postJsonObject['object']['tag']:
if tag['type'] != 'Hashtag':
continue
if not tag.get('name'):
continue
# find the index file for this tag
tagIndexFilename = baseDir + '/tags/' + tag['name'][1:] + '.txt'
if not os.path.isfile(tagIndexFilename):
continue
# remove postId from the tag index file
lines = None
with open(tagIndexFilename, "r") as f:
lines = f.readlines()
if not lines:
continue
newlines = ''
for fileLine in lines:
if postId in fileLine:
# skip over the deleted post
continue
newlines += fileLine
if not newlines.strip():
# if there are no lines then remove the hashtag file
os.remove(tagIndexFilename)
else:
# write the new hashtag index without the given post in it
with open(tagIndexFilename, "w+") as f:
f.write(newlines)
def deletePost(baseDir: str, httpPrefix: str, def deletePost(baseDir: str, httpPrefix: str,
nickname: str, domain: str, postFilename: str, nickname: str, domain: str, postFilename: str,
debug: bool, recentPostsCache: {}) -> None: debug: bool, recentPostsCache: {}) -> None:
"""Recursively deletes a post and its replies and attachments """Recursively deletes a post and its replies and attachments
""" """
postJsonObject = loadJson(postFilename, 1) postJsonObject = loadJson(postFilename, 1)
if postJsonObject: if not postJsonObject:
# don't allow deletion of bookmarked posts # remove any replies
bookmarksIndexFilename = \ _deletePostRemoveReplies(baseDir, nickname, domain,
baseDir + '/accounts/' + nickname + '@' + domain + \ httpPrefix, postFilename,
'/bookmarks.index' recentPostsCache, debug)
if os.path.isfile(bookmarksIndexFilename): # finally, remove the post itself
bookmarkIndex = postFilename.split('/')[-1] + '\n' os.remove(postFilename)
if bookmarkIndex in open(bookmarksIndexFilename).read(): return
return
# don't remove replies to blog posts # don't allow deletion of bookmarked posts
if _isReplyToBlogPost(baseDir, nickname, domain, if _isBookmarked(baseDir, nickname, domain, postFilename):
postJsonObject): return
return
# remove from recent posts cache in memory # don't remove replies to blog posts
if recentPostsCache: if _isReplyToBlogPost(baseDir, nickname, domain,
postId = \ postJsonObject):
removeIdEnding(postJsonObject['id']).replace('/', '#') return
if recentPostsCache.get('index'):
if postId in recentPostsCache['index']:
recentPostsCache['index'].remove(postId)
if recentPostsCache.get('json'):
if recentPostsCache['json'].get(postId):
del recentPostsCache['json'][postId]
if recentPostsCache.get('html'):
if recentPostsCache['html'].get(postId):
del recentPostsCache['html'][postId]
# remove any attachment # remove from recent posts cache in memory
_removeAttachment(baseDir, httpPrefix, domain, postJsonObject) removePostFromCache(postJsonObject, recentPostsCache)
extensions = ('votes', 'arrived', 'muted', 'tts', 'reject') # remove any attachment
for ext in extensions: _removeAttachment(baseDir, httpPrefix, domain, postJsonObject)
extFilename = postFilename + '.' + ext
if os.path.isfile(extFilename):
os.remove(extFilename)
# remove cached html version of the post extensions = ('votes', 'arrived', 'muted', 'tts', 'reject')
cachedPostFilename = \ for ext in extensions:
getCachedPostFilename(baseDir, nickname, domain, postJsonObject) extFilename = postFilename + '.' + ext
if cachedPostFilename: if os.path.isfile(extFilename):
if os.path.isfile(cachedPostFilename): os.remove(extFilename)
os.remove(cachedPostFilename)
# removePostFromCache(postJsonObject,recentPostsCache)
hasObject = False # remove cached html version of the post
if postJsonObject.get('object'): _deleteCachedHtml(baseDir, nickname, domain, postJsonObject)
hasObject = True
# remove from moderation index file hasObject = False
if hasObject: if postJsonObject.get('object'):
if isinstance(postJsonObject['object'], dict): hasObject = True
if postJsonObject['object'].get('moderationStatus'):
if postJsonObject.get('id'):
postId = removeIdEnding(postJsonObject['id'])
removeModerationPostFromIndex(baseDir, postId, debug)
# remove any hashtags index entries # remove from moderation index file
removeHashtagIndex = False if hasObject:
if hasObject: if isinstance(postJsonObject['object'], dict):
if hasObject and isinstance(postJsonObject['object'], dict): if postJsonObject['object'].get('moderationStatus'):
if postJsonObject['object'].get('content'): if postJsonObject.get('id'):
if '#' in postJsonObject['object']['content']: postId = removeIdEnding(postJsonObject['id'])
removeHashtagIndex = True removeModerationPostFromIndex(baseDir, postId, debug)
if removeHashtagIndex:
if postJsonObject['object'].get('id') and \ # remove any hashtags index entries
postJsonObject['object'].get('tag'): if hasObject:
# get the id of the post _deleteHashtagsOnPost(baseDir, postJsonObject)
postId = removeIdEnding(postJsonObject['object']['id'])
for tag in postJsonObject['object']['tag']:
if tag['type'] != 'Hashtag':
continue
if not tag.get('name'):
continue
# find the index file for this tag
tagIndexFilename = \
baseDir + '/tags/' + tag['name'][1:] + '.txt'
if not os.path.isfile(tagIndexFilename):
continue
# remove postId from the tag index file
lines = None
with open(tagIndexFilename, "r") as f:
lines = f.readlines()
if lines:
newlines = ''
for fileLine in lines:
if postId in fileLine:
continue
newlines += fileLine
if not newlines.strip():
# if there are no lines then remove the
# hashtag file
os.remove(tagIndexFilename)
else:
with open(tagIndexFilename, "w+") as f:
f.write(newlines)
# remove any replies # remove any replies
repliesFilename = postFilename.replace('.json', '.replies') _deletePostRemoveReplies(baseDir, nickname, domain,
if os.path.isfile(repliesFilename): httpPrefix, postFilename,
if debug: recentPostsCache, debug)
print('DEBUG: removing replies to ' + postFilename)
with open(repliesFilename, 'r') as f:
for replyId in f:
replyFile = locatePost(baseDir, nickname, domain, replyId)
if replyFile:
if os.path.isfile(replyFile):
deletePost(baseDir, httpPrefix,
nickname, domain, replyFile, debug,
recentPostsCache)
# remove the replies file
os.remove(repliesFilename)
# finally, remove the post itself # finally, remove the post itself
os.remove(postFilename) os.remove(postFilename)
@ -1543,29 +1617,6 @@ def getCachedPostFilename(baseDir: str, nickname: str, domain: str,
return cachedPostFilename + '.html' return cachedPostFilename + '.html'
def removePostFromCache(postJsonObject: {}, recentPostsCache: {}):
""" if the post exists in the recent posts cache then remove it
"""
if not postJsonObject.get('id'):
return
if not recentPostsCache.get('index'):
return
postId = postJsonObject['id']
if '#' in postId:
postId = postId.split('#', 1)[0]
postId = removeIdEnding(postId).replace('/', '#')
if postId not in recentPostsCache['index']:
return
if recentPostsCache['json'].get(postId):
del recentPostsCache['json'][postId]
if recentPostsCache['html'].get(postId):
del recentPostsCache['html'][postId]
recentPostsCache['index'].remove(postId)
def updateRecentPostsCache(recentPostsCache: {}, maxRecentPosts: int, def updateRecentPostsCache(recentPostsCache: {}, maxRecentPosts: int,
postJsonObject: {}, htmlStr: str) -> None: postJsonObject: {}, htmlStr: str) -> None:
"""Store recent posts in memory so that they can be quickly recalled """Store recent posts in memory so that they can be quickly recalled