diff --git a/person.py b/person.py index 86f4e2077..82fcde93c 100644 --- a/person.py +++ b/person.py @@ -1,15 +1,13 @@ -__filename__="person.py" -__author__="Bob Mottram" -__license__="AGPL3+" -__version__="1.1.0" -__maintainer__="Bob Mottram" -__email__="bob@freedombone.net" -__status__="Production" +__filename__ = "person.py" +__author__ = "Bob Mottram" +__license__ = "AGPL3+" +__version__ = "1.1.0" +__maintainer__ = "Bob Mottram" +__email__ = "bob@freedombone.net" +__status__ = "Production" -import json import time import os -import fileinput import subprocess import shutil from random import randint @@ -37,165 +35,200 @@ from utils import validNickname from utils import noOfAccounts from utils import loadJson from utils import saveJson -from auth import createPassword from config import setConfigParam from config import getConfigParam -def generateRSAKey() -> (str,str): - key=RSA.generate(2048) - privateKeyPem=key.exportKey("PEM").decode("utf-8") - publicKeyPem=key.publickey().exportKey("PEM").decode("utf-8") - return privateKeyPem,publicKeyPem -def setProfileImage(baseDir: str,httpPrefix :str,nickname: str,domain: str, \ - port :int,imageFilename: str,imageType :str,resolution :str) -> bool: +def generateRSAKey() -> (str, str): + key = RSA.generate(2048) + privateKeyPem = key.exportKey("PEM").decode("utf-8") + publicKeyPem = key.publickey().exportKey("PEM").decode("utf-8") + return privateKeyPem, publicKeyPem + + +def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str, + port: int, imageFilename: str, imageType: str, + resolution: str) -> bool: """Saves the given image file as an avatar or background image for the given person """ - imageFilename=imageFilename.replace('\n','') - if not (imageFilename.endswith('.png') or \ - imageFilename.endswith('.jpg') or \ - imageFilename.endswith('.jpeg') or \ + imageFilename = imageFilename.replace('\n', '') + if not (imageFilename.endswith('.png') or + imageFilename.endswith('.jpg') or + imageFilename.endswith('.jpeg') or imageFilename.endswith('.gif')): print('Profile image must be png, jpg or gif format') return False if imageFilename.startswith('~/'): - imageFilename=imageFilename.replace('~/',str(Path.home())+'/') + imageFilename = imageFilename.replace('~/', str(Path.home()) + '/') if ':' in domain: - domain=domain.split(':')[0] - fullDomain=domain + domain = domain.split(':')[0] + fullDomain = domain if port: - if port!=80 and port!=443: + if port != 80 and port != 443: if ':' not in domain: - fullDomain=domain+':'+str(port) + fullDomain = domain + ':' + str(port) - handle=nickname.lower()+'@'+domain.lower() - personFilename=baseDir+'/accounts/'+handle+'.json' + handle = nickname.lower() + '@' + domain.lower() + personFilename = baseDir + '/accounts/' + handle + '.json' if not os.path.isfile(personFilename): - print('person definition not found: '+personFilename) + print('person definition not found: ' + personFilename) return False - if not os.path.isdir(baseDir+'/accounts/'+handle): - print('Account not found: '+baseDir+'/accounts/'+handle) + if not os.path.isdir(baseDir + '/accounts/' + handle): + print('Account not found: ' + baseDir + '/accounts/' + handle) return False - iconFilenameBase='icon' - if imageType=='avatar' or imageType=='icon': - iconFilenameBase='icon' + iconFilenameBase = 'icon' + if imageType == 'avatar' or imageType == 'icon': + iconFilenameBase = 'icon' else: - iconFilenameBase='image' + iconFilenameBase = 'image' - mediaType='image/png' - iconFilename=iconFilenameBase+'.png' + mediaType = 'image/png' + iconFilename = iconFilenameBase + '.png' if imageFilename.endswith('.jpg') or \ imageFilename.endswith('.jpeg'): - mediaType='image/jpeg' - iconFilename=iconFilenameBase+'.jpg' + mediaType = 'image/jpeg' + iconFilename = iconFilenameBase + '.jpg' if imageFilename.endswith('.gif'): - mediaType='image/gif' - iconFilename=iconFilenameBase+'.gif' - profileFilename=baseDir+'/accounts/'+handle+'/'+iconFilename + mediaType = 'image/gif' + iconFilename = iconFilenameBase + '.gif' + profileFilename = baseDir + '/accounts/' + handle + '/' + iconFilename - personJson=loadJson(personFilename) + personJson = loadJson(personFilename) if personJson: - personJson[iconFilenameBase]['mediaType']=mediaType - personJson[iconFilenameBase]['url']= \ - httpPrefix+'://'+fullDomain+'/users/'+nickname+'/'+iconFilename - saveJson(personJson,personFilename) + personJson[iconFilenameBase]['mediaType'] = mediaType + personJson[iconFilenameBase]['url'] = \ + httpPrefix + '://' + fullDomain + '/users/' + \ + nickname + '/'+iconFilename + saveJson(personJson, personFilename) - cmd= \ - '/usr/bin/convert '+imageFilename+' -size '+ \ - resolution+' -quality 50 '+profileFilename + cmd = \ + '/usr/bin/convert ' + imageFilename + ' -size ' + \ + resolution + ' -quality 50 ' + profileFilename subprocess.call(cmd, shell=True) - removeMetaData(profileFilename,profileFilename) + removeMetaData(profileFilename, profileFilename) return True return False -def setOrganizationScheme(baseDir: str,nickname: str,domain: str, \ + +def setOrganizationScheme(baseDir: str, nickname: str, domain: str, schema: str) -> bool: """Set the organization schema within which a person exists This will define how roles, skills and availability are assembled into organizations """ # avoid giant strings - if len(schema)>256: + if len(schema) > 256: return False - actorFilename=baseDir+'/accounts/'+nickname+'@'+domain+'.json' + actorFilename = baseDir + '/accounts/' + nickname + '@' + domain + '.json' if not os.path.isfile(actorFilename): return False - actorJson=loadJson(actorFilename) + actorJson = loadJson(actorFilename) if actorJson: - actorJson['orgSchema']=schema - saveJson(actorJson,actorFilename) + actorJson['orgSchema'] = schema + saveJson(actorJson, actorFilename) return True -def accountExists(baseDir: str,nickname: str,domain: str) -> bool: + +def accountExists(baseDir: str, nickname: str, domain: str) -> bool: """Returns true if the given account exists """ if ':' in domain: - domain=domain.split(':')[0] - return os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain) or \ - os.path.isdir(baseDir+'/deactivated/'+nickname+'@'+domain) + domain = domain.split(':')[0] + return os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain) or \ + os.path.isdir(baseDir + '/deactivated/' + nickname + '@' + domain) + def randomizeActorImages(personJson: {}) -> None: """Randomizes the filenames for avatar image and background This causes other instances to update their cached avatar image """ - personId=personJson['id'] - lastPartOfFilename=personJson['icon']['url'].split('/')[-1] - existingExtension=lastPartOfFilename.split('.')[1] - personJson['icon']['url']=personId+'/avatar'+str(randint(10000000000000,99999999999999))+'.'+existingExtension - lastPartOfFilename=personJson['image']['url'].split('/')[-1] - existingExtension=lastPartOfFilename.split('.')[1] - personJson['image']['url']=personId+'/image'+str(randint(10000000000000,99999999999999))+'.'+existingExtension + personId = personJson['id'] + lastPartOfFilename = personJson['icon']['url'].split('/')[-1] + existingExtension = lastPartOfFilename.split('.')[1] + personJson['icon']['url'] = \ + personId + '/avatar' + str(randint(10000000000000, 99999999999999)) + \ + '.' + existingExtension + lastPartOfFilename = personJson['image']['url'].split('/')[-1] + existingExtension = lastPartOfFilename.split('.')[1] + personJson['image']['url'] = \ + personId + '/image' + str(randint(10000000000000, 99999999999999)) + \ + '.' + existingExtension -def createPersonBase(baseDir: str,nickname: str,domain: str,port: int, \ - httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}): + +def createPersonBase(baseDir: str, nickname: str, domain: str, port: int, + httpPrefix: str, saveToFile: bool, + password=None) -> (str, str, {}, {}): """Returns the private key, public key, actor and webfinger endpoint """ - privateKeyPem,publicKeyPem=generateRSAKey() - webfingerEndpoint= \ - createWebfingerEndpoint(nickname,domain,port,httpPrefix,publicKeyPem) + privateKeyPem, publicKeyPem = generateRSAKey() + webfingerEndpoint = \ + createWebfingerEndpoint(nickname, domain, port, + httpPrefix, publicKeyPem) if saveToFile: - storeWebfingerEndpoint(nickname,domain,port,baseDir,webfingerEndpoint) + storeWebfingerEndpoint(nickname, domain, port, + baseDir, webfingerEndpoint) - handle=nickname.lower()+'@'+domain.lower() - originalDomain=domain + handle = nickname.lower() + '@' + domain.lower() + originalDomain = domain if port: - if port!=80 and port!=443: + if port != 80 and port != 443: if ':' not in domain: - domain=domain+':'+str(port) + domain = domain + ':' + str(port) - personType='Person' - approveFollowers=False - personName=nickname - personId=httpPrefix+'://'+domain+'/users/'+nickname - inboxStr=personId+'/inbox' - personUrl=httpPrefix+'://'+domain+'/@'+personName - if nickname=='inbox': + personType = 'Person' + approveFollowers = False + personName = nickname + personId = httpPrefix + '://' + domain + '/users/' + nickname + inboxStr = personId + '/inbox' + personUrl = httpPrefix + '://' + domain + '/@' + personName + if nickname == 'inbox': # shared inbox - inboxStr=httpPrefix+'://'+domain+'/actor/inbox' - personId=httpPrefix+'://'+domain+'/actor' - personUrl=httpPrefix+'://'+domain+'/about/more?instance_actor=true' - personName=originalDomain - approveFollowers=True - personType='Application' + inboxStr = httpPrefix + '://' + domain + '/actor/inbox' + personId = httpPrefix + '://' + domain + '/actor' + personUrl = httpPrefix + '://' + domain + \ + '/about/more?instance_actor=true' + personName = originalDomain + approveFollowers = True + personType = 'Application' - newPerson={ - '@context': ['https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - {'Emoji': 'toot:Emoji', - 'Hashtag': 'as:Hashtag', - 'IdentityProof': 'toot:IdentityProof', - 'PropertyValue': 'schema:PropertyValue', - 'alsoKnownAs': {'@id': 'as:alsoKnownAs', '@type': '@id'}, - 'focalPoint': {'@container': '@list', '@id': 'toot:focalPoint'}, - 'manuallyApprovesFollowers': 'as:manuallyApprovesFollowers', - 'movedTo': {'@id': 'as:movedTo', '@type': '@id'}, - 'schema': 'http://schema.org#', - 'value': 'schema:value'}], + imageUrl = \ + personId + '/image' + \ + str(randint(10000000000000, 99999999999999)) + '.png' + + iconUrl = \ + personId + '/avatar' + \ + str(randint(10000000000000, 99999999999999)) + '.png' + + contextDict = { + 'Emoji': 'toot:Emoji', + 'Hashtag': 'as:Hashtag', + 'IdentityProof': 'toot:IdentityProof', + 'PropertyValue': 'schema:PropertyValue', + 'alsoKnownAs': { + '@id': 'as:alsoKnownAs', '@type': '@id' + }, + 'focalPoint': { + '@container': '@list', '@id': 'toot:focalPoint' + }, + 'manuallyApprovesFollowers': 'as:manuallyApprovesFollowers', + 'movedTo': { + '@id': 'as:movedTo', '@type': '@id' + }, + 'schema': 'http://schema.org#', + 'value': 'schema:value' + } + + newPerson = { + '@context': [ + 'https://www.w3.org/ns/activitystreams', + 'https://w3id.org/security/v1', + contextDict + ], 'attachment': [], 'alsoKnownAs': [], 'discoverable': False, @@ -214,13 +247,13 @@ def createPersonBase(baseDir: str,nickname: str,domain: str,port: int, \ 'icon': { 'mediaType': 'image/png', 'type': 'Image', - 'url': personId+'/avatar'+str(randint(10000000000000,99999999999999))+'.png' + 'url': iconUrl }, 'id': personId, 'image': { 'mediaType': 'image/png', 'type': 'Image', - 'url': personId+'/image'+str(randint(10000000000000,99999999999999))+'.png' + 'url': imageUrl }, 'inbox': inboxStr, 'manuallyApprovesFollowers': approveFollowers, @@ -239,13 +272,13 @@ def createPersonBase(baseDir: str,nickname: str,domain: str,port: int, \ 'nomadicLocations': [{ 'id': personId, 'type': 'nomadicLocation', - 'locationAddress':'acct:'+nickname+'@'+domain, - 'locationPrimary':True, - 'locationDeleted':False + 'locationAddress': 'acct:' + nickname + '@' + domain, + 'locationPrimary': True, + 'locationDeleted': False }] } - if nickname=='inbox': + if nickname == 'inbox': # fields not needed by the shared inbox del newPerson['outbox'] del newPerson['icon'] @@ -261,660 +294,731 @@ def createPersonBase(baseDir: str,nickname: str,domain: str,port: int, \ if saveToFile: # save person to file - peopleSubdir='/accounts' - if not os.path.isdir(baseDir+peopleSubdir): - os.mkdir(baseDir+peopleSubdir) - if not os.path.isdir(baseDir+peopleSubdir+'/'+handle): - os.mkdir(baseDir+peopleSubdir+'/'+handle) - if not os.path.isdir(baseDir+peopleSubdir+'/'+handle+'/inbox'): - os.mkdir(baseDir+peopleSubdir+'/'+handle+'/inbox') - if not os.path.isdir(baseDir+peopleSubdir+'/'+handle+'/outbox'): - os.mkdir(baseDir+peopleSubdir+'/'+handle+'/outbox') - if not os.path.isdir(baseDir+peopleSubdir+'/'+handle+'/ocap'): - os.mkdir(baseDir+peopleSubdir+'/'+handle+'/ocap') - if not os.path.isdir(baseDir+peopleSubdir+'/'+handle+'/queue'): - os.mkdir(baseDir+peopleSubdir+'/'+handle+'/queue') - filename=baseDir+peopleSubdir+'/'+handle+'.json' - saveJson(newPerson,filename) + peopleSubdir = '/accounts' + if not os.path.isdir(baseDir + peopleSubdir): + os.mkdir(baseDir + peopleSubdir) + if not os.path.isdir(baseDir + peopleSubdir + '/' + handle): + os.mkdir(baseDir + peopleSubdir + '/' + handle) + if not os.path.isdir(baseDir + peopleSubdir + '/' + handle + '/inbox'): + os.mkdir(baseDir + peopleSubdir + '/' + handle + '/inbox') + if not os.path.isdir(baseDir + peopleSubdir + '/' + + handle + '/outbox'): + os.mkdir(baseDir + peopleSubdir + '/' + handle + '/outbox') + if not os.path.isdir(baseDir + peopleSubdir + '/' + handle + '/ocap'): + os.mkdir(baseDir + peopleSubdir + '/' + handle + '/ocap') + if not os.path.isdir(baseDir + peopleSubdir + '/' + handle + '/queue'): + os.mkdir(baseDir + peopleSubdir + '/' + handle + '/queue') + filename = baseDir + peopleSubdir + '/' + handle + '.json' + saveJson(newPerson, filename) # save to cache - if not os.path.isdir(baseDir+'/cache'): - os.mkdir(baseDir+'/cache') - if not os.path.isdir(baseDir+'/cache/actors'): - os.mkdir(baseDir+'/cache/actors') - cacheFilename=baseDir+'/cache/actors/'+newPerson['id'].replace('/','#')+'.json' - saveJson(newPerson,cacheFilename) + if not os.path.isdir(baseDir + '/cache'): + os.mkdir(baseDir + '/cache') + if not os.path.isdir(baseDir + '/cache/actors'): + os.mkdir(baseDir + '/cache/actors') + cacheFilename = baseDir + '/cache/actors/' + \ + newPerson['id'].replace('/', '#') + '.json' + saveJson(newPerson, cacheFilename) # save the private key - privateKeysSubdir='/keys/private' - if not os.path.isdir(baseDir+'/keys'): - os.mkdir(baseDir+'/keys') - if not os.path.isdir(baseDir+privateKeysSubdir): - os.mkdir(baseDir+privateKeysSubdir) - filename=baseDir+privateKeysSubdir+'/'+handle+'.key' + privateKeysSubdir = '/keys/private' + if not os.path.isdir(baseDir + '/keys'): + os.mkdir(baseDir + '/keys') + if not os.path.isdir(baseDir + privateKeysSubdir): + os.mkdir(baseDir + privateKeysSubdir) + filename = baseDir + privateKeysSubdir + '/' + handle + '.key' with open(filename, "w") as text_file: print(privateKeyPem, file=text_file) # save the public key - publicKeysSubdir='/keys/public' - if not os.path.isdir(baseDir+publicKeysSubdir): - os.mkdir(baseDir+publicKeysSubdir) - filename=baseDir+publicKeysSubdir+'/'+handle+'.pem' + publicKeysSubdir = '/keys/public' + if not os.path.isdir(baseDir + publicKeysSubdir): + os.mkdir(baseDir + publicKeysSubdir) + filename = baseDir + publicKeysSubdir + '/' + handle + '.pem' with open(filename, "w") as text_file: print(publicKeyPem, file=text_file) if password: - storeBasicCredentials(baseDir,nickname,password) + storeBasicCredentials(baseDir, nickname, password) - return privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint + return privateKeyPem, publicKeyPem, newPerson, webfingerEndpoint -def registerAccount(baseDir: str,httpPrefix: str,domain: str,port: int, \ - nickname: str,password: str) -> bool: + +def registerAccount(baseDir: str, httpPrefix: str, domain: str, port: int, + nickname: str, password: str) -> bool: """Registers a new account from the web interface """ - if accountExists(baseDir,nickname,domain): + if accountExists(baseDir, nickname, domain): return False - if not validNickname(domain,nickname): - print('REGISTER: Nickname '+nickname+' is invalid') + if not validNickname(domain, nickname): + print('REGISTER: Nickname ' + nickname + ' is invalid') return False - if len(password)<8: + if len(password) < 8: print('REGISTER: Password should be at least 8 characters') return False - privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint= \ - createPerson(baseDir,nickname,domain,port, \ - httpPrefix,True,password) + (privateKeyPem, publicKeyPem, + newPerson, webfingerEndpoint) = createPerson(baseDir, nickname, + domain, port, + httpPrefix, True, + password) if privateKeyPem: return True return False -def createGroup(baseDir: str,nickname: str,domain: str,port: int, \ - httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}): + +def createGroup(baseDir: str, nickname: str, domain: str, port: int, + httpPrefix: str, saveToFile: bool, + password=None) -> (str, str, {}, {}): """Returns a group """ - privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint= \ - createPerson(baseDir,nickname,domain,port, \ - httpPrefix,saveToFile,password) - newPerson['type']='Group' - return privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint + (privateKeyPem, publicKeyPem, + newPerson, webfingerEndpoint) = createPerson(baseDir, nickname, + domain, port, + httpPrefix, saveToFile, + password) + newPerson['type'] = 'Group' + return privateKeyPem, publicKeyPem, newPerson, webfingerEndpoint -def createPerson(baseDir: str,nickname: str,domain: str,port: int, \ - httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}): + +def createPerson(baseDir: str, nickname: str, domain: str, port: int, + httpPrefix: str, saveToFile: bool, + password=None) -> (str, str, {}, {}): """Returns the private key, public key, actor and webfinger endpoint """ - if not validNickname(domain,nickname): - return None,None,None,None + if not validNickname(domain, nickname): + return None, None, None, None # If a config.json file doesn't exist then don't decrement # remaining registrations counter - remainingConfigExists=getConfigParam(baseDir,'registrationsRemaining') + remainingConfigExists = getConfigParam(baseDir, 'registrationsRemaining') if remainingConfigExists: - registrationsRemaining=int(remainingConfigExists) - if registrationsRemaining<=0: - return None,None,None,None + registrationsRemaining = int(remainingConfigExists) + if registrationsRemaining <= 0: + return None, None, None, None - privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint= \ - createPersonBase(baseDir,nickname,domain,port,httpPrefix,saveToFile,password) - if noOfAccounts(baseDir)==1: - #print(nickname+' becomes the instance admin and a moderator') - setRole(baseDir,nickname,domain,'instance','admin') - setRole(baseDir,nickname,domain,'instance','moderator') - setRole(baseDir,nickname,domain,'instance','delegator') - setConfigParam(baseDir,'admin',nickname) + (privateKeyPem, publicKeyPem, + newPerson, webfingerEndpoint) = createPersonBase(baseDir, nickname, + domain, port, + httpPrefix, + saveToFile, password) + if noOfAccounts(baseDir) == 1: + # print(nickname+' becomes the instance admin and a moderator') + setRole(baseDir, nickname, domain, 'instance', 'admin') + setRole(baseDir, nickname, domain, 'instance', 'moderator') + setRole(baseDir, nickname, domain, 'instance', 'delegator') + setConfigParam(baseDir, 'admin', nickname) - if not os.path.isdir(baseDir+'/accounts'): - os.mkdir(baseDir+'/accounts') - if not os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain): - os.mkdir(baseDir+'/accounts/'+nickname+'@'+domain) + if not os.path.isdir(baseDir + '/accounts'): + os.mkdir(baseDir + '/accounts') + if not os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain): + os.mkdir(baseDir + '/accounts/' + nickname + '@' + domain) - if os.path.isfile(baseDir+'/img/default-avatar.png'): - copyfile(baseDir+'/img/default-avatar.png',baseDir+'/accounts/'+nickname+'@'+domain+'/avatar.png') - theme=getConfigParam(baseDir,'theme') - defaultProfileImageFilename=baseDir+'/img/image.png' + if os.path.isfile(baseDir + '/img/default-avatar.png'): + copyfile(baseDir + '/img/default-avatar.png', + baseDir + '/accounts/' + nickname + '@' + domain + + '/avatar.png') + theme = getConfigParam(baseDir, 'theme') + defaultProfileImageFilename = baseDir + '/img/image.png' if theme: - if os.path.isfile(baseDir+'/img/image_'+theme+'.png'): - defaultBannerFilename=baseDir+'/img/image_'+theme+'.png' + if os.path.isfile(baseDir + '/img/image_' + theme + '.png'): + defaultBannerFilename = baseDir + '/img/image_' + theme + '.png' if os.path.isfile(defaultProfileImageFilename): - copyfile(defaultProfileImageFilename,baseDir+'/accounts/'+nickname+'@'+domain+'/image.png') - defaultBannerFilename=baseDir+'/img/banner.png' + copyfile(defaultProfileImageFilename, baseDir + + '/accounts/' + nickname + '@' + domain + '/image.png') + defaultBannerFilename = baseDir + '/img/banner.png' if theme: - if os.path.isfile(baseDir+'/img/banner_'+theme+'.png'): - defaultBannerFilename=baseDir+'/img/banner_'+theme+'.png' + if os.path.isfile(baseDir + '/img/banner_' + theme + '.png'): + defaultBannerFilename = baseDir + '/img/banner_' + theme + '.png' if os.path.isfile(defaultBannerFilename): - copyfile(defaultBannerFilename,baseDir+'/accounts/'+nickname+'@'+domain+'/banner.png') + copyfile(defaultBannerFilename, baseDir + '/accounts/' + + nickname + '@' + domain + '/banner.png') if remainingConfigExists: - registrationsRemaining-=1 - setConfigParam(baseDir,'registrationsRemaining',str(registrationsRemaining)) - return privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint + registrationsRemaining -= 1 + setConfigParam(baseDir, 'registrationsRemaining', + str(registrationsRemaining)) + return privateKeyPem, publicKeyPem, newPerson, webfingerEndpoint -def createSharedInbox(baseDir: str,nickname: str,domain: str,port: int, \ - httpPrefix: str) -> (str,str,{},{}): + +def createSharedInbox(baseDir: str, nickname: str, domain: str, port: int, + httpPrefix: str) -> (str, str, {}, {}): """Generates the shared inbox """ - return createPersonBase(baseDir,nickname,domain,port,httpPrefix,True,None) + return createPersonBase(baseDir, nickname, domain, port, httpPrefix, + True, None) -def createCapabilitiesInbox(baseDir: str,nickname: str,domain: str,port: int, \ - httpPrefix: str) -> (str,str,{},{}): + +def createCapabilitiesInbox(baseDir: str, nickname: str, + domain: str, port: int, + httpPrefix: str) -> (str, str, {}, {}): """Generates the capabilities inbox to sign requests """ - return createPersonBase(baseDir,nickname,domain,port,httpPrefix,True,None) + return createPersonBase(baseDir, nickname, domain, port, + httpPrefix, True, None) -def personUpgradeActor(baseDir: str,personJson: {},handle: str,filename: str) -> None: + +def personUpgradeActor(baseDir: str, personJson: {}, + handle: str, filename: str) -> None: """Alter the actor to add any new properties """ - updateActor=False + updateActor = False if not os.path.isfile(filename): - print('WARN: actor file not found '+filename) + print('WARN: actor file not found ' + filename) return if not personJson: - personJson=loadJson(filename) + personJson = loadJson(filename) if not personJson.get('nomadicLocations'): - personJson['nomadicLocations']=[{ + personJson['nomadicLocations'] = [{ 'id': personJson['id'], 'type': 'nomadicLocation', 'locationAddress':'acct:'+handle, 'locationPrimary':True, 'locationDeleted':False }] - print('Nomadic locations added to to actor '+handle) - updateActor=True + print('Nomadic locations added to to actor ' + handle) + updateActor = True if updateActor: - saveJson(personJson,filename) + saveJson(personJson, filename) # also update the actor within the cache - actorCacheFilename= \ - baseDir+'/accounts/cache/actors/'+ \ - personJson['id'].replace('/','#')+'.json' + actorCacheFilename = \ + baseDir + '/accounts/cache/actors/' + \ + personJson['id'].replace('/', '#') + '.json' if os.path.isfile(actorCacheFilename): - saveJson(personJson,actorCacheFilename) + saveJson(personJson, actorCacheFilename) # update domain/@nickname in actors cache - actorCacheFilename= \ - baseDir+'/accounts/cache/actors/'+ \ - personJson['id'].replace('/users/','/@').replace('/','#')+'.json' + actorCacheFilename = \ + baseDir + '/accounts/cache/actors/' + \ + personJson['id'].replace('/users/', '/@').replace('/', '#') + \ + '.json' if os.path.isfile(actorCacheFilename): - saveJson(personJson,actorCacheFilename) + saveJson(personJson, actorCacheFilename) -def personLookup(domain: str,path: str,baseDir: str) -> {}: + +def personLookup(domain: str, path: str, baseDir: str) -> {}: """Lookup the person for an given nickname """ if path.endswith('#main-key'): - path=path.replace('#main-key','') + path = path.replace('#main-key', '') # is this a shared inbox lookup? - isSharedInbox=False - if path=='/inbox' or path=='/users/inbox' or path=='/sharedInbox': + isSharedInbox = False + if path == '/inbox' or path == '/users/inbox' or path == '/sharedInbox': # shared inbox actor on @domain@domain - path='/users/'+domain - isSharedInbox=True + path = '/users/' + domain + isSharedInbox = True else: - notPersonLookup=['/inbox','/outbox','/outboxarchive', \ - '/followers','/following','/featured', \ - '.png','.jpg','.gif','.mpv'] + notPersonLookup = ('/inbox', '/outbox', '/outboxarchive', + '/followers', '/following', '/featured', + '.png', '.jpg', '.gif', '.mpv') for ending in notPersonLookup: if path.endswith(ending): return None - nickname=None + nickname = None if path.startswith('/users/'): - nickname=path.replace('/users/','',1) + nickname = path.replace('/users/', '', 1) if path.startswith('/@'): - nickname=path.replace('/@','',1) + nickname = path.replace('/@', '', 1) if not nickname: return None - if not isSharedInbox and not validNickname(domain,nickname): + if not isSharedInbox and not validNickname(domain, nickname): return None if ':' in domain: - domain=domain.split(':')[0] - handle=nickname+'@'+domain - filename=baseDir+'/accounts/'+handle+'.json' + domain = domain.split(':')[0] + handle = nickname + '@' + domain + filename = baseDir + '/accounts/' + handle + '.json' if not os.path.isfile(filename): return None - personJson=loadJson(filename) - personUpgradeActor(baseDir,personJson,handle,filename) - #if not personJson: - # personJson={"user": "unknown"} + personJson = loadJson(filename) + personUpgradeActor(baseDir, personJson, handle, filename) + # if not personJson: + # personJson={"user": "unknown"} return personJson -def personBoxJson(recentPostsCache: {}, \ - session,baseDir: str,domain: str,port: int,path: str, \ - httpPrefix: str,noOfItems: int,boxname: str, \ - authorized: bool,ocapAlways: bool) -> {}: + +def personBoxJson(recentPostsCache: {}, + session, baseDir: str, domain: str, port: int, path: str, + httpPrefix: str, noOfItems: int, boxname: str, + authorized: bool, ocapAlways: bool) -> {}: """Obtain the inbox/outbox/moderation feed for the given person """ - if boxname!='inbox' and boxname!='dm' and \ - boxname!='tlreplies' and boxname!='tlmedia' and \ - boxname!='tlblogs' and \ - boxname!='outbox' and boxname!='moderation' and \ - boxname!='tlbookmarks': + if boxname != 'inbox' and boxname != 'dm' and \ + boxname != 'tlreplies' and boxname != 'tlmedia' and \ + boxname != 'tlblogs' and \ + boxname != 'outbox' and boxname != 'moderation' and \ + boxname != 'tlbookmarks': return None - if not '/'+boxname in path: + if not '/' + boxname in path: return None # Only show the header by default - headerOnly=True + headerOnly = True # handle page numbers - pageNumber=None + pageNumber = None if '?page=' in path: - pageNumber=path.split('?page=')[1] - if pageNumber=='true': - pageNumber=1 + pageNumber = path.split('?page=')[1] + if pageNumber == 'true': + pageNumber = 1 else: try: - pageNumber=int(pageNumber) - except: + pageNumber = int(pageNumber) + except BaseException: pass - path=path.split('?page=')[0] - headerOnly=False + path = path.split('?page=')[0] + headerOnly = False - if not path.endswith('/'+boxname): + if not path.endswith('/' + boxname): return None - nickname=None + nickname = None if path.startswith('/users/'): - nickname=path.replace('/users/','',1).replace('/'+boxname,'') + nickname = path.replace('/users/', '', 1).replace('/' + boxname, '') if path.startswith('/@'): - nickname=path.replace('/@','',1).replace('/'+boxname,'') + nickname = path.replace('/@', '', 1).replace('/' + boxname, '') if not nickname: return None - if not validNickname(domain,nickname): + if not validNickname(domain, nickname): return None - if boxname=='inbox': - return createInbox(recentPostsCache, \ - session,baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,ocapAlways,pageNumber) - elif boxname=='dm': - return createDMTimeline(session,baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,ocapAlways,pageNumber) - elif boxname=='tlbookmarks': - return createBookmarksTimeline(session,baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,ocapAlways,pageNumber) - elif boxname=='tlreplies': - return createRepliesTimeline(session,baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,ocapAlways,pageNumber) - elif boxname=='tlmedia': - return createMediaTimeline(session,baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,ocapAlways,pageNumber) - elif boxname=='tlblogs': - return createBlogsTimeline(session,baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,ocapAlways,pageNumber) - elif boxname=='outbox': - return createOutbox(session,baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,authorized,pageNumber) - elif boxname=='moderation': - return createModeration(baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,authorized,pageNumber) + if boxname == 'inbox': + return createInbox(recentPostsCache, + session, baseDir, nickname, domain, port, + httpPrefix, + noOfItems, headerOnly, ocapAlways, pageNumber) + elif boxname == 'dm': + return createDMTimeline(session, baseDir, nickname, domain, port, + httpPrefix, + noOfItems, headerOnly, ocapAlways, pageNumber) + elif boxname == 'tlbookmarks': + return createBookmarksTimeline(session, baseDir, nickname, domain, + port, httpPrefix, + noOfItems, headerOnly, ocapAlways, + pageNumber) + elif boxname == 'tlreplies': + return createRepliesTimeline(session, baseDir, nickname, domain, + port, httpPrefix, + noOfItems, headerOnly, ocapAlways, + pageNumber) + elif boxname == 'tlmedia': + return createMediaTimeline(session, baseDir, nickname, domain, port, + httpPrefix, + noOfItems, headerOnly, ocapAlways, + pageNumber) + elif boxname == 'tlblogs': + return createBlogsTimeline(session, baseDir, nickname, domain, port, + httpPrefix, + noOfItems, headerOnly, ocapAlways, + pageNumber) + elif boxname == 'outbox': + return createOutbox(session, baseDir, nickname, domain, port, + httpPrefix, + noOfItems, headerOnly, authorized, + pageNumber) + elif boxname == 'moderation': + return createModeration(baseDir, nickname, domain, port, + httpPrefix, + noOfItems, headerOnly, authorized, + pageNumber) return None -def personInboxJson(recentPostsCache: {}, \ - baseDir: str,domain: str,port: int,path: str, \ - httpPrefix: str,noOfItems: int,ocapAlways: bool) -> []: + +def personInboxJson(recentPostsCache: {}, + baseDir: str, domain: str, port: int, path: str, + httpPrefix: str, noOfItems: int, ocapAlways: bool) -> []: """Obtain the inbox feed for the given person Authentication is expected to have already happened """ - if not '/inbox' in path: + if '/inbox' not in path: return None # Only show the header by default - headerOnly=True + headerOnly = True # handle page numbers - pageNumber=None + pageNumber = None if '?page=' in path: - pageNumber=path.split('?page=')[1] - if pageNumber=='true': - pageNumber=1 + pageNumber = path.split('?page=')[1] + if pageNumber == 'true': + pageNumber = 1 else: try: - pageNumber=int(pageNumber) - except: + pageNumber = int(pageNumber) + except BaseException: pass - path=path.split('?page=')[0] - headerOnly=False + path = path.split('?page=')[0] + headerOnly = False if not path.endswith('/inbox'): return None - nickname=None + nickname = None if path.startswith('/users/'): - nickname=path.replace('/users/','',1).replace('/inbox','') + nickname = path.replace('/users/', '', 1).replace('/inbox', '') if path.startswith('/@'): - nickname=path.replace('/@','',1).replace('/inbox','') + nickname = path.replace('/@', '', 1).replace('/inbox', '') if not nickname: return None - if not validNickname(domain,nickname): + if not validNickname(domain, nickname): return None - return createInbox(recentPostsCache,baseDir,nickname,domain,port,httpPrefix, \ - noOfItems,headerOnly,ocapAlways,pageNumber) + return createInbox(recentPostsCache, baseDir, nickname, + domain, port, httpPrefix, + noOfItems, headerOnly, ocapAlways, pageNumber) -def setDisplayNickname(baseDir: str,nickname: str, domain: str, \ + +def setDisplayNickname(baseDir: str, nickname: str, domain: str, displayName: str) -> bool: - if len(displayName)>32: + if len(displayName) > 32: return False - handle=nickname.lower()+'@'+domain.lower() - filename=baseDir+'/accounts/'+handle.lower()+'.json' + handle = nickname.lower() + '@' + domain.lower() + filename = baseDir + '/accounts/' + handle.lower() + '.json' if not os.path.isfile(filename): return False - personJson=loadJson(filename) + personJson = loadJson(filename) if not personJson: return False - personJson['name']=displayName - saveJson(personJson,filename) + personJson['name'] = displayName + saveJson(personJson, filename) return True -def setBio(baseDir: str,nickname: str, domain: str, bio: str) -> bool: - if len(bio)>32: + +def setBio(baseDir: str, nickname: str, domain: str, bio: str) -> bool: + if len(bio) > 32: return False - handle=nickname.lower()+'@'+domain.lower() - filename=baseDir+'/accounts/'+handle.lower()+'.json' + handle = nickname.lower() + '@' + domain.lower() + filename = baseDir + '/accounts/' + handle.lower() + '.json' if not os.path.isfile(filename): return False - personJson=loadJson(filename) + personJson = loadJson(filename) if not personJson: return False if not personJson.get('summary'): return False - personJson['summary']=bio + personJson['summary'] = bio - saveJson(personJson,filename) + saveJson(personJson, filename) return True -def isSuspended(baseDir: str,nickname: str) -> bool: + +def isSuspended(baseDir: str, nickname: str) -> bool: """Returns true if the given nickname is suspended """ - adminNickname=getConfigParam(baseDir,'admin') - if nickname==adminNickname: + adminNickname = getConfigParam(baseDir, 'admin') + if nickname == adminNickname: return False - suspendedFilename=baseDir+'/accounts/suspended.txt' + suspendedFilename = baseDir + '/accounts/suspended.txt' if os.path.isfile(suspendedFilename): with open(suspendedFilename, "r") as f: - lines=f.readlines() - suspendedFile=open(suspendedFilename,"w+") + lines = f.readlines() for suspended in lines: - if suspended.strip('\n')==nickname: + if suspended.strip('\n') == nickname: return True return False -def unsuspendAccount(baseDir: str,nickname: str) -> None: + +def unsuspendAccount(baseDir: str, nickname: str) -> None: """Removes an account suspention """ - suspendedFilename=baseDir+'/accounts/suspended.txt' + suspendedFilename = baseDir + '/accounts/suspended.txt' if os.path.isfile(suspendedFilename): with open(suspendedFilename, "r") as f: - lines=f.readlines() - suspendedFile=open(suspendedFilename,"w+") + lines = f.readlines() + suspendedFile = open(suspendedFilename, "w+") for suspended in lines: - if suspended.strip('\n')!=nickname: + if suspended.strip('\n') != nickname: suspendedFile.write(suspended) suspendedFile.close() -def suspendAccount(baseDir: str,nickname: str,domain: str) -> None: + +def suspendAccount(baseDir: str, nickname: str, domain: str) -> None: """Suspends the given account """ # Don't suspend the admin - adminNickname=getConfigParam(baseDir,'admin') - if nickname==adminNickname: + adminNickname = getConfigParam(baseDir, 'admin') + if nickname == adminNickname: return # Don't suspend moderators - moderatorsFile=baseDir+'/accounts/moderators.txt' + moderatorsFile = baseDir + '/accounts/moderators.txt' if os.path.isfile(moderatorsFile): with open(moderatorsFile, "r") as f: - lines=f.readlines() + lines = f.readlines() for moderator in lines: - if moderator.strip('\n')==nickname: + if moderator.strip('\n') == nickname: return - saltFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/.salt' + saltFilename = baseDir + '/accounts/' + \ + nickname + '@' + domain + '/.salt' if os.path.isfile(saltFilename): os.remove(saltFilename) - tokenFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/.token' + tokenFilename = baseDir + '/accounts/' + \ + nickname + '@' + domain + '/.token' if os.path.isfile(tokenFilename): os.remove(tokenFilename) - suspendedFilename=baseDir+'/accounts/suspended.txt' + suspendedFilename = baseDir + '/accounts/suspended.txt' if os.path.isfile(suspendedFilename): with open(suspendedFilename, "r") as f: - lines=f.readlines() + lines = f.readlines() for suspended in lines: - if suspended.strip('\n')==nickname: + if suspended.strip('\n') == nickname: return - suspendedFile=open(suspendedFilename,'a+') + suspendedFile = open(suspendedFilename, 'a+') if suspendedFile: - suspendedFile.write(nickname+'\n') + suspendedFile.write(nickname + '\n') suspendedFile.close() else: - suspendedFile=open(suspendedFilename,'w+') + suspendedFile = open(suspendedFilename, 'w+') if suspendedFile: - suspendedFile.write(nickname+'\n') + suspendedFile.write(nickname + '\n') suspendedFile.close() -def canRemovePost(baseDir: str,nickname: str,domain: str,port: int,postId: str) -> bool: + +def canRemovePost(baseDir: str, nickname: str, + domain: str, port: int, postId: str) -> bool: """Returns true if the given post can be removed """ if '/statuses/' not in postId: return False - domainFull=domain + domainFull = domain if port: - if port!=80 and port!=443: + if port != 80 and port != 443: if ':' not in domain: - domainFull=domain+':'+str(port) + domainFull = domain + ':' + str(port) # is the post by the admin? - adminNickname=getConfigParam(baseDir,'admin') - if domainFull+'/users/'+adminNickname+'/' in postId: + adminNickname = getConfigParam(baseDir, 'admin') + if domainFull + '/users/' + adminNickname + '/' in postId: return False # is the post by a moderator? - moderatorsFile=baseDir+'/accounts/moderators.txt' + moderatorsFile = baseDir + '/accounts/moderators.txt' if os.path.isfile(moderatorsFile): with open(moderatorsFile, "r") as f: - lines=f.readlines() + lines = f.readlines() for moderator in lines: - if domainFull+'/users/'+moderator.strip('\n')+'/' in postId: + if domainFull + '/users/' + moderator.strip('\n') + '/' in postId: return False return True -def removeTagsForNickname(baseDir: str,nickname: str,domain: str,port: int) -> None: + +def removeTagsForNickname(baseDir: str, nickname: str, + domain: str, port: int) -> None: """Removes tags for a nickname """ - if not os.path.isdir(baseDir+'/tags'): + if not os.path.isdir(baseDir + '/tags'): return - domainFull=domain + domainFull = domain if port: - if port!=80 and port!=443: + if port != 80 and port != 443: if ':' not in domain: - domainFull=domain+':'+str(port) - matchStr=domainFull+'/users/'+nickname+'/' - directory=os.fsencode(baseDir+'/tags/') + domainFull = domain + ':' + str(port) + matchStr = domainFull + '/users/' + nickname + '/' + directory = os.fsencode(baseDir + '/tags/') for f in os.scandir(directory): - f=f.name - filename=os.fsdecode(f) + f = f.name + filename = os.fsdecode(f) if not filename.endswith(".txt"): continue - tagFilename=os.path.join(directory,filename) + tagFilename = os.path.join(directory, filename) if not os.path.isfile(tagFilename): continue if matchStr not in open(tagFilename).read(): continue with open(tagFilename, "r") as f: - lines=f.readlines() - tagFile=open(tagFilename,"w+") + lines = f.readlines() + tagFile = open(tagFilename, "w+") if tagFile: for tagline in lines: if matchStr not in tagline: tagFile.write(tagline) tagFile.close() -def removeAccount(baseDir: str,nickname: str,domain: str,port: int) -> bool: + +def removeAccount(baseDir: str, nickname: str, + domain: str, port: int) -> bool: """Removes an account """ # Don't remove the admin - adminNickname=getConfigParam(baseDir,'admin') - if nickname==adminNickname: + adminNickname = getConfigParam(baseDir, 'admin') + if nickname == adminNickname: return False # Don't remove moderators - moderatorsFile=baseDir+'/accounts/moderators.txt' + moderatorsFile = baseDir + '/accounts/moderators.txt' if os.path.isfile(moderatorsFile): with open(moderatorsFile, "r") as f: - lines=f.readlines() + lines = f.readlines() for moderator in lines: - if moderator.strip('\n')==nickname: + if moderator.strip('\n') == nickname: return False - unsuspendAccount(baseDir,nickname) - handle=nickname+'@'+domain - removePassword(baseDir,nickname) - removeTagsForNickname(baseDir,nickname,domain,port) - if os.path.isdir(baseDir+'/deactivated/'+handle): - shutil.rmtree(baseDir+'/deactivated/'+handle) - if os.path.isdir(baseDir+'/accounts/'+handle): - shutil.rmtree(baseDir+'/accounts/'+handle) - if os.path.isfile(baseDir+'/accounts/'+handle+'.json'): - os.remove(baseDir+'/accounts/'+handle+'.json') - if os.path.isfile(baseDir+'/wfendpoints/'+handle+'.json'): - os.remove(baseDir+'/wfendpoints/'+handle+'.json') - if os.path.isfile(baseDir+'/keys/private/'+handle+'.key'): - os.remove(baseDir+'/keys/private/'+handle+'.key') - if os.path.isfile(baseDir+'/keys/public/'+handle+'.pem'): - os.remove(baseDir+'/keys/public/'+handle+'.pem') - if os.path.isdir(baseDir+'/sharefiles/'+nickname): - shutil.rmtree(baseDir+'/sharefiles/'+nickname) - if os.path.isfile(baseDir+'/wfdeactivated/'+handle+'.json'): - os.remove(baseDir+'/wfdeactivated/'+handle+'.json') - if os.path.isdir(baseDir+'/sharefilesdeactivated/'+nickname): - shutil.rmtree(baseDir+'/sharefilesdeactivated/'+nickname) + unsuspendAccount(baseDir, nickname) + handle = nickname + '@' + domain + removePassword(baseDir, nickname) + removeTagsForNickname(baseDir, nickname, domain, port) + if os.path.isdir(baseDir + '/deactivated/' + handle): + shutil.rmtree(baseDir + '/deactivated/' + handle) + if os.path.isdir(baseDir + '/accounts/' + handle): + shutil.rmtree(baseDir + '/accounts/' + handle) + if os.path.isfile(baseDir + '/accounts/' + handle + '.json'): + os.remove(baseDir + '/accounts/' + handle + '.json') + if os.path.isfile(baseDir + '/wfendpoints/' + handle + '.json'): + os.remove(baseDir + '/wfendpoints/' + handle + '.json') + if os.path.isfile(baseDir + '/keys/private/' + handle + '.key'): + os.remove(baseDir + '/keys/private/' + handle + '.key') + if os.path.isfile(baseDir + '/keys/public/' + handle + '.pem'): + os.remove(baseDir + '/keys/public/' + handle + '.pem') + if os.path.isdir(baseDir + '/sharefiles/' + nickname): + shutil.rmtree(baseDir + '/sharefiles/' + nickname) + if os.path.isfile(baseDir + '/wfdeactivated/' + handle + '.json'): + os.remove(baseDir + '/wfdeactivated/' + handle + '.json') + if os.path.isdir(baseDir + '/sharefilesdeactivated/' + nickname): + shutil.rmtree(baseDir + '/sharefilesdeactivated/' + nickname) return True -def deactivateAccount(baseDir: str,nickname: str,domain: str) -> bool: + +def deactivateAccount(baseDir: str, nickname: str, domain: str) -> bool: """Makes an account temporarily unavailable """ - handle=nickname+'@'+domain + handle = nickname + '@' + domain - accountDir=baseDir+'/accounts/'+handle + accountDir = baseDir + '/accounts/' + handle if not os.path.isdir(accountDir): return False - deactivatedDir=baseDir+'/deactivated' + deactivatedDir = baseDir + '/deactivated' if not os.path.isdir(deactivatedDir): os.mkdir(deactivatedDir) - shutil.move(accountDir,deactivatedDir+'/'+handle) + shutil.move(accountDir, deactivatedDir + '/' + handle) - if os.path.isfile(baseDir+'/wfendpoints/'+handle+'.json'): - deactivatedWebfingerDir=baseDir+'/wfdeactivated' + if os.path.isfile(baseDir + '/wfendpoints/' + handle + '.json'): + deactivatedWebfingerDir = baseDir + '/wfdeactivated' if not os.path.isdir(deactivatedWebfingerDir): os.mkdir(deactivatedWebfingerDir) - shutil.move(baseDir+'/wfendpoints/'+handle+'.json',deactivatedWebfingerDir+'/'+handle+'.json') + shutil.move(baseDir + '/wfendpoints/' + handle + '.json', + deactivatedWebfingerDir + '/' + handle + '.json') - if os.path.isdir(baseDir+'/sharefiles/'+nickname): - deactivatedSharefilesDir=baseDir+'/sharefilesdeactivated' + if os.path.isdir(baseDir + '/sharefiles/' + nickname): + deactivatedSharefilesDir = baseDir + '/sharefilesdeactivated' if not os.path.isdir(deactivatedSharefilesDir): os.mkdir(deactivatedSharefilesDir) - shutil.move(baseDir+'/sharefiles/'+nickname,deactivatedSharefilesDir+'/'+nickname) - return os.path.isdir(deactivatedDir+'/'+nickname+'@'+domain) + shutil.move(baseDir + '/sharefiles/' + nickname, + deactivatedSharefilesDir + '/' + nickname) + return os.path.isdir(deactivatedDir + '/' + nickname + '@' + domain) -def activateAccount(baseDir: str,nickname: str,domain: str) -> None: + +def activateAccount(baseDir: str, nickname: str, domain: str) -> None: """Makes a deactivated account available """ - handle=nickname+'@'+domain + handle = nickname + '@' + domain - deactivatedDir=baseDir+'/deactivated' - deactivatedAccountDir=deactivatedDir+'/'+handle + deactivatedDir = baseDir + '/deactivated' + deactivatedAccountDir = deactivatedDir + '/' + handle if os.path.isdir(deactivatedAccountDir): - accountDir=baseDir+'/accounts/'+handle + accountDir = baseDir + '/accounts/' + handle if not os.path.isdir(accountDir): - shutil.move(deactivatedAccountDir,accountDir) + shutil.move(deactivatedAccountDir, accountDir) - deactivatedWebfingerDir=baseDir+'/wfdeactivated' - if os.path.isfile(deactivatedWebfingerDir+'/'+handle+'.json'): - shutil.move(deactivatedWebfingerDir+'/'+handle+'.json',baseDir+'/wfendpoints/'+handle+'.json') + deactivatedWebfingerDir = baseDir + '/wfdeactivated' + if os.path.isfile(deactivatedWebfingerDir + '/' + handle + '.json'): + shutil.move(deactivatedWebfingerDir + '/' + handle + '.json', + baseDir + '/wfendpoints/' + handle + '.json') - deactivatedSharefilesDir=baseDir+'/sharefilesdeactivated' - if os.path.isdir(deactivatedSharefilesDir+'/'+nickname): - if not os.path.isdir(baseDir+'/sharefiles/'+nickname): - shutil.move(deactivatedSharefilesDir+'/'+nickname,baseDir+'/sharefiles/'+nickname) + deactivatedSharefilesDir = baseDir + '/sharefilesdeactivated' + if os.path.isdir(deactivatedSharefilesDir + '/' + nickname): + if not os.path.isdir(baseDir + '/sharefiles/' + nickname): + shutil.move(deactivatedSharefilesDir + '/' + nickname, + baseDir + '/sharefiles/' + nickname) -def isPersonSnoozed(baseDir: str,nickname: str,domain: str,snoozeActor: str) -> bool: + +def isPersonSnoozed(baseDir: str, nickname: str, domain: str, + snoozeActor: str) -> bool: """Returns true if the given actor is snoozed """ - snoozedFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/snoozed.txt' + snoozedFilename = baseDir + '/accounts/' + \ + nickname + '@' + domain + '/snoozed.txt' if not os.path.isfile(snoozedFilename): return False - if snoozeActor+' ' not in open(snoozedFilename).read(): + if snoozeActor + ' ' not in open(snoozedFilename).read(): return False # remove the snooze entry if it has timed out - replaceStr=None + replaceStr = None with open(snoozedFilename, 'r') as snoozedFile: for line in snoozedFile: # is this the entry for the actor? - if line.startswith(snoozeActor+' '): - snoozedTimeStr=line.split(' ')[1].replace('\n','') + if line.startswith(snoozeActor + ' '): + snoozedTimeStr = line.split(' ')[1].replace('\n', '') # is there a time appended? if snoozedTimeStr.isdigit(): - snoozedTime=int(snoozedTimeStr) - currTime=int(time.time()) + snoozedTime = int(snoozedTimeStr) + currTime = int(time.time()) # has the snooze timed out? - if int(currTime-snoozedTime)>60*60*24: - replaceStr=line + if int(currTime - snoozedTime) > 60 * 60 * 24: + replaceStr = line else: - replaceStr=line + replaceStr = line break if replaceStr: - content=None + content = None with open(snoozedFilename, 'r') as snoozedFile: - content=snoozedFile.read().replace(replaceStr,'') + content = snoozedFile.read().replace(replaceStr, '') if content: - writeSnoozedFile=open(snoozedFilename, 'w') + writeSnoozedFile = open(snoozedFilename, 'w') if writeSnoozedFile: writeSnoozedFile.write(content) writeSnoozedFile.close() - if snoozeActor+' ' in open(snoozedFilename).read(): + if snoozeActor + ' ' in open(snoozedFilename).read(): return True return False -def personSnooze(baseDir: str,nickname: str,domain: str,snoozeActor: str) -> None: + +def personSnooze(baseDir: str, nickname: str, domain: str, + snoozeActor: str) -> None: """Temporarily ignores the given actor """ - accountDir=baseDir+'/accounts/'+nickname+'@'+domain + accountDir = baseDir + '/accounts/' + nickname + '@' + domain if not os.path.isdir(accountDir): - print('ERROR: unknown account '+accountDir) + print('ERROR: unknown account ' + accountDir) return - snoozedFilename=accountDir+'/snoozed.txt' + snoozedFilename = accountDir + '/snoozed.txt' if os.path.isfile(snoozedFilename): - if snoozeActor+' ' in open(snoozedFilename).read(): + if snoozeActor + ' ' in open(snoozedFilename).read(): return - snoozedFile=open(snoozedFilename, "a+") + snoozedFile = open(snoozedFilename, "a+") if snoozedFile: - snoozedFile.write(snoozeActor+' '+str(int(time.time()))+'\n') + snoozedFile.write(snoozeActor + ' ' + + str(int(time.time())) + '\n') snoozedFile.close() -def personUnsnooze(baseDir: str,nickname: str,domain: str,snoozeActor: str) -> None: + +def personUnsnooze(baseDir: str, nickname: str, domain: str, + snoozeActor: str) -> None: """Undoes a temporarily ignore of the given actor """ - accountDir=baseDir+'/accounts/'+nickname+'@'+domain + accountDir = baseDir + '/accounts/' + nickname + '@' + domain if not os.path.isdir(accountDir): - print('ERROR: unknown account '+accountDir) + print('ERROR: unknown account ' + accountDir) return - snoozedFilename=accountDir+'/snoozed.txt' + snoozedFilename = accountDir + '/snoozed.txt' if not os.path.isfile(snoozedFilename): return - if snoozeActor+' ' not in open(snoozedFilename).read(): + if snoozeActor + ' ' not in open(snoozedFilename).read(): return - replaceStr=None + replaceStr = None with open(snoozedFilename, 'r') as snoozedFile: for line in snoozedFile: - if line.startswith(snoozeActor+' '): - replaceStr=line + if line.startswith(snoozeActor + ' '): + replaceStr = line break if replaceStr: - content=None + content = None with open(snoozedFilename, 'r') as snoozedFile: - content=snoozedFile.read().replace(replaceStr,'') + content = snoozedFile.read().replace(replaceStr, '') if content: - writeSnoozedFile=open(snoozedFilename, 'w') + writeSnoozedFile = open(snoozedFilename, 'w') if writeSnoozedFile: writeSnoozedFile.write(content) writeSnoozedFile.close()