From d0884fa04d3b1e62900d028f1802790a8fe85ac8 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 22 Mar 2020 20:36:19 +0000 Subject: [PATCH] Tidying --- acceptreject.py | 16 +-- announce.py | 58 ++++++----- auth.py | 44 ++++---- availability.py | 37 ++++--- blocking.py | 51 ++++----- blog.py | 24 ++--- blurhash.py | 125 ++++++++++++----------- bookmarks.py | 58 ++++++----- cache.py | 14 +-- capabilities.py | 20 ++-- config.py | 16 +-- content.py | 23 +++-- daemon.py | 138 ++++++++++++------------- delete.py | 47 +++++---- donate.py | 14 +-- epicyon.py | 88 +++++++++------- filters.py | 14 +-- follow.py | 94 +++++++++-------- happening.py | 16 +-- httpsig.py | 65 +++++++----- inbox.py | 38 +++---- like.py | 57 ++++++----- manualapprove.py | 18 ++-- matrix.py | 14 +-- media.py | 14 +-- metadata.py | 57 ++++++----- migrate.py | 14 +-- outbox.py | 14 +-- person.py | 162 +++++++++++++++-------------- pgp.py | 14 +-- posts.py | 261 ++++++++++++++++++++++++++--------------------- question.py | 18 ++-- roles.py | 47 +++++---- schedule.py | 16 +-- session.py | 31 +++--- shares.py | 78 +++++++------- skills.py | 36 ++++--- ssb.py | 14 +-- tests.py | 137 +++++++++++++++---------- theme.py | 14 +-- threads.py | 28 ++--- tox.py | 14 +-- utils.py | 42 ++++---- webfinger.py | 50 ++++----- webinterface.py | 252 ++++++++++++++++++++++++--------------------- xmpp.py | 14 +-- 46 files changed, 1290 insertions(+), 1126 deletions(-) diff --git a/acceptreject.py b/acceptreject.py index cf487d799..d7abadd4d 100644 --- a/acceptreject.py +++ b/acceptreject.py @@ -1,10 +1,10 @@ -__filename__ = "acceptreject.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="acceptreject.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import json @@ -39,7 +39,7 @@ def createAcceptReject(baseDir: str,federationList: [], \ if ':' not in domain: domain=domain+':'+str(port) - newAccept = { + newAccept={ "@context": "https://www.w3.org/ns/activitystreams", 'type': acceptType, 'actor': httpPrefix+'://'+domain+'/users/'+nickname, diff --git a/announce.py b/announce.py index 89222bbdd..6b28206c6 100644 --- a/announce.py +++ b/announce.py @@ -1,10 +1,10 @@ -__filename__ = "announce.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="announce.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import time @@ -162,7 +162,7 @@ def updateAnnounceCollection(recentPostsCache: {}, \ if debug: print('DEBUG: Adding initial shares (announcements) to '+ \ postUrl) - announcementsJson = { + announcementsJson={ "@context": "https://www.w3.org/ns/activitystreams", 'id': postUrl, 'type': 'Collection', @@ -236,10 +236,10 @@ def createAnnounce(session,baseDir: str,federationList: [], \ if ':' not in domain: fullDomain=domain+':'+str(port) - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() newAnnounceId= \ httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber - newAnnounce = { + newAnnounce={ "@context": "https://www.w3.org/ns/activitystreams", 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, 'atomUri': httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber, @@ -254,7 +254,7 @@ def createAnnounce(session,baseDir: str,federationList: [], \ if len(ccUrl)>0: newAnnounce['cc']=[ccUrl] if saveToFile: - outboxDir = createOutboxDir(nickname,domain,baseDir) + outboxDir=createOutboxDir(nickname,domain,baseDir) filename=outboxDir+'/'+newAnnounceId.replace('/','#')+'.json' saveJson(newAnnounce,filename) @@ -291,8 +291,8 @@ def announcePublic(session,baseDir: str,federationList: [], \ if ':' not in domain: fromDomain=domain+':'+str(port) - toUrl = 'https://www.w3.org/ns/activitystreams#Public' - ccUrl = httpPrefix + '://'+fromDomain+'/users/'+nickname+'/followers' + toUrl='https://www.w3.org/ns/activitystreams#Public' + ccUrl=httpPrefix+'://'+fromDomain+'/users/'+nickname+'/followers' return createAnnounce(session,baseDir,federationList, \ nickname,domain,port, \ toUrl,ccUrl,httpPrefix, \ @@ -317,7 +317,7 @@ def repeatPost(session,baseDir: str,federationList: [], \ if ':' not in announcedDomain: announcedDomain=announcedDomain+':'+str(announcePort) - objectUrl = announceHttpsPrefix + '://'+announcedDomain+'/users/'+ \ + objectUrl=announceHttpsPrefix+'://'+announcedDomain+'/users/'+ \ announceNickname+'/statuses/'+str(announceStatusNumber) return announcePublic(session,baseDir,federationList, \ @@ -352,7 +352,7 @@ def undoAnnounce(session,baseDir: str,federationList: [], \ if ':' not in domain: fullDomain=domain+':'+str(port) - newUndoAnnounce = { + newUndoAnnounce={ "@context": "https://www.w3.org/ns/activitystreams", 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, 'type': 'Undo', @@ -403,8 +403,8 @@ def undoAnnouncePublic(session,baseDir: str,federationList: [], \ if ':' not in domain: fromDomain=domain+':'+str(port) - toUrl = 'https://www.w3.org/ns/activitystreams#Public' - ccUrl = httpPrefix + '://'+fromDomain+'/users/'+nickname+'/followers' + toUrl='https://www.w3.org/ns/activitystreams#Public' + ccUrl=httpPrefix+'://'+fromDomain+'/users/'+nickname+'/followers' return undoAnnounce(session,baseDir,federationList, \ nickname,domain,port, \ toUrl,ccUrl,httpPrefix, \ @@ -429,7 +429,7 @@ def undoRepeatPost(session,baseDir: str,federationList: [], \ if ':' not in announcedDomain: announcedDomain=announcedDomain+':'+str(announcePort) - objectUrl = announceHttpsPrefix + '://'+announcedDomain+'/users/'+ \ + objectUrl=announceHttpsPrefix+'://'+announcedDomain+'/users/'+ \ announceNickname+'/statuses/'+str(announceStatusNumber) return undoAnnouncePublic(session,baseDir,federationList, \ @@ -459,14 +459,14 @@ def sendAnnounceViaServer(baseDir: str,session, \ if ':' not in fromDomain: fromDomainFull=fromDomain+':'+str(fromPort) - toUrl = 'https://www.w3.org/ns/activitystreams#Public' - ccUrl = httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers' + toUrl='https://www.w3.org/ns/activitystreams#Public' + ccUrl=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers' - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() newAnnounceId= \ httpPrefix+'://'+fromDomainFull+'/users/'+ \ fromNickname+'/statuses/'+statusNumber - newAnnounceJson = { + newAnnounceJson={ "@context": "https://www.w3.org/ns/activitystreams", 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, 'atomUri': newAnnounceId, @@ -481,7 +481,7 @@ def sendAnnounceViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = \ + wfRequest= \ webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ fromDomain,projectVersion) if not wfRequest: @@ -492,7 +492,7 @@ def sendAnnounceViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname,fromDomain,postToBox) @@ -507,10 +507,12 @@ def sendAnnounceViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newAnnounceJson,[],inboxUrl,headers,"inbox:write") if debug: diff --git a/auth.py b/auth.py index 61e1e6beb..1172343ab 100644 --- a/auth.py +++ b/auth.py @@ -1,10 +1,10 @@ -__filename__ = "auth.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="auth.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import base64 import hashlib @@ -16,24 +16,24 @@ import random def hashPassword(password: str) -> str: """Hash a password for storing """ - salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii') - pwdhash = hashlib.pbkdf2_hmac('sha512', \ + salt=hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii') + pwdhash=hashlib.pbkdf2_hmac('sha512', \ password.encode('utf-8'), \ salt, 100000) - pwdhash = binascii.hexlify(pwdhash) - return (salt + pwdhash).decode('ascii') + pwdhash=binascii.hexlify(pwdhash) + return (salt+pwdhash).decode('ascii') def verifyPassword(storedPassword: str,providedPassword: str) -> bool: """Verify a stored password against one provided by user """ - salt = storedPassword[:64] - storedPassword = storedPassword[64:] - pwdhash = hashlib.pbkdf2_hmac('sha512', \ + salt=storedPassword[:64] + storedPassword=storedPassword[64:] + pwdhash=hashlib.pbkdf2_hmac('sha512', \ providedPassword.encode('utf-8'), \ salt.encode('ascii'), \ 100000) - pwdhash = binascii.hexlify(pwdhash).decode('ascii') - return pwdhash == storedPassword + pwdhash=binascii.hexlify(pwdhash).decode('ascii') + return pwdhash==storedPassword def createBasicAuthHeader(nickname: str,password: str) -> str: """This is only used by tests @@ -60,13 +60,13 @@ def authorizeBasic(baseDir: str,path: str,authHeader: str,debug: bool) -> bool: print('DEBUG: This is not a users endpoint') return False nicknameFromPath=pathUsersSection.split('/')[0] - base64Str = authHeader.split(' ')[1].replace('\n','') - plain = base64.b64decode(base64Str).decode('utf-8') + base64Str=authHeader.split(' ')[1].replace('\n','') + plain=base64.b64decode(base64Str).decode('utf-8') if ':' not in plain: if debug: print('DEBUG: Basic Auth header does not contain a ":" separator for username:password') return False - nickname = plain.split(':')[0] + nickname=plain.split(':')[0] if nickname!=nicknameFromPath: if debug: print('DEBUG: Nickname given in the path ('+nicknameFromPath+ \ @@ -78,12 +78,12 @@ def authorizeBasic(baseDir: str,path: str,authHeader: str,debug: bool) -> bool: if debug: print('DEBUG: passwords file missing') return False - providedPassword = plain.split(':')[1] - passfile = open(passwordFile, "r") + providedPassword=plain.split(':')[1] + passfile=open(passwordFile, "r") for line in passfile: if line.startswith(nickname+':'): storedPassword=line.split(':')[1].replace('\n','') - success = verifyPassword(storedPassword,providedPassword) + success=verifyPassword(storedPassword,providedPassword) if not success: if debug: print('DEBUG: Password check failed for '+nickname) diff --git a/availability.py b/availability.py index 6fb243607..e45720d49 100644 --- a/availability.py +++ b/availability.py @@ -1,10 +1,10 @@ -__filename__ = "availability.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="availability.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import time @@ -89,10 +89,10 @@ def sendAvailabilityViaServer(baseDir: str,session, \ if ':' not in domain: domainFull=domain+':'+str(port) - toUrl = httpPrefix+'://'+domainFull+'/users/'+nickname - ccUrl = httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers' + toUrl=httpPrefix+'://'+domainFull+'/users/'+nickname + ccUrl=httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers' - newAvailabilityJson = { + newAvailabilityJson={ 'type': 'Availability', 'actor': httpPrefix+'://'+domainFull+'/users/'+nickname, 'object': '"'+status+'"', @@ -103,8 +103,9 @@ def sendAvailabilityViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+domainFull+'/@'+nickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - domain,projectVersion) + wfRequest= \ + webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + domain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -113,7 +114,7 @@ def sendAvailabilityViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,nickname,domain,postToBox) @@ -128,10 +129,12 @@ def sendAvailabilityViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(Nickname,password) - headers = {'host': domain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': domain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newAvailabilityJson,[],inboxUrl,headers,"inbox:write") if debug: diff --git a/blocking.py b/blocking.py index eda5e872b..56cd37a27 100644 --- a/blocking.py +++ b/blocking.py @@ -1,10 +1,10 @@ -__filename__ = "blocking.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="blocking.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os from utils import isEvil @@ -174,10 +174,10 @@ def sendBlockViaServer(baseDir: str,session, \ toUrl= 'https://www.w3.org/ns/activitystreams#Public' ccUrl= \ - httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers' + httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers' blockActor=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname - newBlockJson = { + newBlockJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Block', 'actor': blockActor, @@ -189,8 +189,9 @@ def sendBlockViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - fromDomain,projectVersion) + wfRequest= \ + webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + fromDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -199,7 +200,7 @@ def sendBlockViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -215,10 +216,12 @@ def sendBlockViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newBlockJson,[],inboxUrl,headers,"inbox:write") if debug: @@ -246,10 +249,10 @@ def sendUndoBlockViaServer(baseDir: str,session, \ toUrl= 'https://www.w3.org/ns/activitystreams#Public' ccUrl= \ - httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers' + httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers' blockActor=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname - newBlockJson = { + newBlockJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Undo', 'actor': blockActor, @@ -276,7 +279,7 @@ def sendUndoBlockViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -292,10 +295,12 @@ def sendUndoBlockViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newBlockJson,[],inboxUrl,headers,"inbox:write") if debug: diff --git a/blog.py b/blog.py index 74274f06e..7a7f6e408 100644 --- a/blog.py +++ b/blog.py @@ -1,10 +1,10 @@ -__filename__ = "blog.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="blog.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import time @@ -63,12 +63,12 @@ def noOfBlogReplies(baseDir: str,httpPrefix: str,translate: {}, \ replies=0 with open(postFilename, "r") as f: - lines = f.readlines() + lines=f.readlines() for replyPostId in lines: replyPostId= \ replyPostId.replace('\n','').replace('.json','').replace('.replies','') replies+= \ - 1 + \ + 1+ \ noOfBlogReplies(baseDir,httpPrefix,translate, \ nickname,domain,domainFull, \ replyPostId,depth+1) @@ -111,7 +111,7 @@ def getBlogReplies(baseDir: str,httpPrefix: str,translate: {}, \ return '' with open(postFilename, "r") as f: - lines = f.readlines() + lines=f.readlines() repliesStr='' for replyPostId in lines: replyPostId= \ @@ -556,13 +556,13 @@ def htmlEditBlog(mediaInstance: bool,translate: {}, \ if os.path.isfile(baseDir+'/accounts/newpost.txt'): with open(baseDir+'/accounts/newpost.txt', 'r') as file: - editBlogText = '

'+file.read()+'

' + editBlogText='

'+file.read()+'

' cssFilename=baseDir+'/epicyon-profile.css' if os.path.isfile(baseDir+'/epicyon.css'): cssFilename=baseDir+'/epicyon.css' with open(cssFilename, 'r') as cssFile: - editBlogCSS = cssFile.read() + editBlogCSS=cssFile.read() if httpPrefix!='https': editBlogCSS=editBlogCSS.replace('https://',httpPrefix+'://') diff --git a/blurhash.py b/blurhash.py index 3ed47e739..6e13d2bdd 100644 --- a/blurhash.py +++ b/blurhash.py @@ -32,16 +32,16 @@ Very close port of the original Swift implementation by Dag Ă…gren. import math # Alphabet for base 83 -alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~" -alphabet_values = dict(zip(alphabet, range(len(alphabet)))) +alphabet="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~" +alphabet_values=dict(zip(alphabet,range(len(alphabet)))) def base83_decode(base83_str): """ Decodes a base83 string, as used in blurhash, to an integer. """ - value = 0 + value=0 for base83_char in base83_str: - value = value * 83 + alphabet_values[base83_char] + value=value*83+alphabet_values[base83_char] return value def base83_encode(value, length): @@ -54,9 +54,9 @@ def base83_encode(value, length): if int(value) // (83 ** (length)) != 0: raise ValueError("Specified length is too short to encode given value.") - result = "" - for i in range(1, length + 1): - digit = int(value) // (83 ** (length - i)) % 83 + result="" + for i in range(1,length+1): + digit=int(value) // (83 ** (length - i)) % 83 result += alphabet[int(digit)] return result @@ -64,10 +64,10 @@ def srgb_to_linear(value): """ srgb 0-255 integer to linear 0.0-1.0 floating point conversion. """ - value = float(value) / 255.0 + value=float(value) / 255.0 if value <= 0.04045: return value / 12.92 - return math.pow((value + 0.055) / 1.055, 2.4) + return math.pow((value+0.055) / 1.055, 2.4) def sign_pow(value, exp): """ @@ -79,10 +79,10 @@ def linear_to_srgb(value): """ linear 0.0-1.0 floating point to srgb 0-255 integer conversion. """ - value = max(0.0, min(1.0, value)) + value=max(0.0, min(1.0, value)) if value <= 0.0031308: - return int(value * 12.92 * 255 + 0.5) - return int((1.055 * math.pow(value, 1 / 2.4) - 0.055) * 255 + 0.5) + return int(value*12.92*255+0.5) + return int((1.055*math.pow(value, 1 / 2.4)-0.055)*255+0.5) def blurhash_components(blurhash): """ @@ -92,13 +92,13 @@ def blurhash_components(blurhash): raise ValueError("BlurHash must be at least 6 characters long.") # Decode metadata - size_info = base83_decode(blurhash[0]) - size_y = int(size_info / 9) + 1 - size_x = (size_info % 9) + 1 + size_info=base83_decode(blurhash[0]) + size_y=int(size_info / 9)+1 + size_x=(size_info % 9)+1 return size_x, size_y -def blurhash_decode(blurhash, width, height, punch = 1.0, linear = False): +def blurhash_decode(blurhash,width,height,punch=1.0,linear=False): """ Decodes the given blurhash to an image of the specified size. @@ -117,20 +117,20 @@ def blurhash_decode(blurhash, width, height, punch = 1.0, linear = False): raise ValueError("BlurHash must be at least 6 characters long.") # Decode metadata - size_info = base83_decode(blurhash[0]) - size_y = int(size_info / 9) + 1 - size_x = (size_info % 9) + 1 + size_info=base83_decode(blurhash[0]) + size_y=int(size_info / 9)+1 + size_x=(size_info % 9)+1 - quant_max_value = base83_decode(blurhash[1]) - real_max_value = (float(quant_max_value + 1) / 166.0) * punch + quant_max_value=base83_decode(blurhash[1]) + real_max_value=(float(quant_max_value+1)/166.0)*punch # Make sure we at least have the right number of characters - if len(blurhash) != 4 + 2 * size_x * size_y: + if len(blurhash) != 4+2*size_x*size_y: raise ValueError("Invalid BlurHash length.") # Decode DC component - dc_value = base83_decode(blurhash[2:6]) - colours = [( + dc_value=base83_decode(blurhash[2:6]) + colours=[( srgb_to_linear(dc_value >> 16), srgb_to_linear((dc_value >> 8) & 255), srgb_to_linear(dc_value & 255) @@ -138,7 +138,7 @@ def blurhash_decode(blurhash, width, height, punch = 1.0, linear = False): # Decode AC components for component in range(1, size_x * size_y): - ac_value = base83_decode(blurhash[4+component*2:4+(component+1)*2]) + ac_value=base83_decode(blurhash[4+component*2:4+(component+1)*2]) colours.append(( sign_pow((float(int(ac_value / (19 * 19))) - 9.0) / 9.0, 2.0) * real_max_value, sign_pow((float(int(ac_value / 19) % 19) - 9.0) / 9.0, 2.0) * real_max_value, @@ -147,20 +147,21 @@ def blurhash_decode(blurhash, width, height, punch = 1.0, linear = False): # Return image RGB values, as a list of lists of lists, # consumable by something like numpy or PIL. - pixels = [] + pixels=[] for y in range(height): - pixel_row = [] + pixel_row=[] for x in range(width): - pixel = [0.0, 0.0, 0.0] + pixel=[0.0, 0.0, 0.0] for j in range(size_y): for i in range(size_x): - basis = math.cos(math.pi * float(x) * float(i) / float(width)) * \ - math.cos(math.pi * float(y) * float(j) / float(height)) - colour = colours[i + j * size_x] - pixel[0] += colour[0] * basis - pixel[1] += colour[1] * basis - pixel[2] += colour[2] * basis + basis= \ + math.cos(math.pi*float(x)*float(i)/float(width))* \ + math.cos(math.pi*float(y)*float(j)/float(height)) + colour=colours[i+j*size_x] + pixel[0] += colour[0]*basis + pixel[1] += colour[1]*basis + pixel[2] += colour[2]*basis if linear == False: pixel_row.append([ linear_to_srgb(pixel[0]), @@ -172,7 +173,7 @@ def blurhash_decode(blurhash, width, height, punch = 1.0, linear = False): pixels.append(pixel_row) return pixels -def blurhash_encode(image, components_x = 4, components_y = 4, linear = False): +def blurhash_encode(image,components_x=4,components_y=4,linear=False): """ Calculates the blurhash for an image using the given x and y component counts. @@ -186,14 +187,14 @@ def blurhash_encode(image, components_x = 4, components_y = 4, linear = False): """ if components_x < 1 or components_x > 9 or components_y < 1 or components_y > 9: raise ValueError("x and y component counts must be between 1 and 9 inclusive.") - height = float(len(image)) - width = float(len(image[0])) + height=float(len(image)) + width=float(len(image[0])) # Convert to linear if neeeded - image_linear = [] - if linear == False: + image_linear=[] + if linear==False: for y in range(int(height)): - image_linear_line = [] + image_linear_line=[] for x in range(int(width)): image_linear_line.append([ srgb_to_linear(image[y][x][0]), @@ -202,19 +203,20 @@ def blurhash_encode(image, components_x = 4, components_y = 4, linear = False): ]) image_linear.append(image_linear_line) else: - image_linear = image + image_linear=image # Calculate components - components = [] - max_ac_component = 0.0 + components=[] + max_ac_component=0.0 for j in range(components_y): for i in range(components_x): - norm_factor = 1.0 if (i == 0 and j == 0) else 2.0 - component = [0.0, 0.0, 0.0] + norm_factor=1.0 if (i==0 and j==0) else 2.0 + component=[0.0,0.0,0.0] for y in range(int(height)): for x in range(int(width)): - basis = norm_factor * math.cos(math.pi * float(i) * float(x) / width) * \ - math.cos(math.pi * float(j) * float(y) / height) + basis= \ + norm_factor * math.cos(math.pi * float(i) * float(x) / width) * \ + math.cos(math.pi * float(j) * float(y) / height) component[0] += basis * image_linear[y][x][0] component[1] += basis * image_linear[y][x][1] component[2] += basis * image_linear[y][x][2] @@ -224,27 +226,32 @@ def blurhash_encode(image, components_x = 4, components_y = 4, linear = False): component[2] /= (width * height) components.append(component) - if not (i == 0 and j == 0): - max_ac_component = max(max_ac_component, abs(component[0]), abs(component[1]), abs(component[2])) + if not (i==0 and j==0): + max_ac_component= \ + max(max_ac_component,abs(component[0]), \ + abs(component[1]),abs(component[2])) # Encode components - dc_value = (linear_to_srgb(components[0][0]) << 16) + \ - (linear_to_srgb(components[0][1]) << 8) + \ - linear_to_srgb(components[0][2]) + dc_value= \ + (linear_to_srgb(components[0][0]) << 16)+ \ + (linear_to_srgb(components[0][1]) << 8)+ \ + linear_to_srgb(components[0][2]) - quant_max_ac_component = int(max(0, min(82, math.floor(max_ac_component * 166 - 0.5)))) - ac_component_norm_factor = float(quant_max_ac_component + 1) / 166.0 + quant_max_ac_component= \ + int(max(0, min(82, math.floor(max_ac_component * 166 - 0.5)))) + ac_component_norm_factor= \ + float(quant_max_ac_component+1) / 166.0 - ac_values = [] + ac_values=[] for r, g, b in components[1:]: ac_values.append( - int(max(0.0, min(18.0, math.floor(sign_pow(r / ac_component_norm_factor, 0.5) * 9.0 + 9.5)))) * 19 * 19 + \ - int(max(0.0, min(18.0, math.floor(sign_pow(g / ac_component_norm_factor, 0.5) * 9.0 + 9.5)))) * 19 + \ - int(max(0.0, min(18.0, math.floor(sign_pow(b / ac_component_norm_factor, 0.5) * 9.0 + 9.5)))) + int(max(0.0,min(18.0,math.floor(sign_pow(r / ac_component_norm_factor, 0.5) * 9.0 + 9.5)))) * 19 * 19 + \ + int(max(0.0,min(18.0, math.floor(sign_pow(g / ac_component_norm_factor, 0.5) * 9.0 + 9.5)))) * 19 + \ + int(max(0.0,min(18.0, math.floor(sign_pow(b / ac_component_norm_factor, 0.5) * 9.0 + 9.5)))) ) # Build final blurhash - blurhash = "" + blurhash="" blurhash += base83_encode((components_x - 1) + (components_y - 1) * 9, 1) blurhash += base83_encode(quant_max_ac_component, 1) blurhash += base83_encode(dc_value, 4) diff --git a/bookmarks.py b/bookmarks.py index eab665b32..ab00318d9 100644 --- a/bookmarks.py +++ b/bookmarks.py @@ -1,10 +1,10 @@ -__filename__ = "bookmarks.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="bookmarks.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import json @@ -159,7 +159,7 @@ def updateBookmarksCollection(recentPostsCache: {}, \ if not postJsonObject['object'].get('bookmarks'): if debug: print('DEBUG: Adding initial bookmarks to '+objectUrl) - bookmarksJson = { + bookmarksJson={ "@context": "https://www.w3.org/ns/activitystreams", 'id': objectUrl, 'type': 'Collection', @@ -198,7 +198,7 @@ def updateBookmarksCollection(recentPostsCache: {}, \ if bookmarkIndex not in open(bookmarksIndexFilename).read(): try: with open(bookmarksIndexFilename, 'r+') as bookmarksIndexFile: - content = bookmarksIndexFile.read() + content=bookmarksIndexFile.read() bookmarksIndexFile.seek(0, 0) bookmarksIndexFile.write(bookmarkIndex+'\n'+content) if debug: @@ -239,7 +239,7 @@ def bookmark(recentPostsCache: {}, \ if '/statuses/' in objectUrl: bookmarkTo=[objectUrl.split('/statuses/')[0]] - newBookmarkJson = { + newBookmarkJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Bookmark', 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, @@ -348,7 +348,7 @@ def undoBookmark(recentPostsCache: {}, \ if '/statuses/' in objectUrl: bookmarkTo=[objectUrl.split('/statuses/')[0]] - newUndoBookmarkJson = { + newUndoBookmarkJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Undo', 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, @@ -414,8 +414,8 @@ def undoBookmarkPost(session,baseDir: str,federationList: [], \ if ':' not in bookmarkedomain: bookmarkedomain=bookmarkedomain+':'+str(bookmarkPort) - objectUrl = \ - httpPrefix + '://'+bookmarkedomain+'/users/'+bookmarkNickname+ \ + objectUrl= \ + httpPrefix+'://'+bookmarkedomain+'/users/'+bookmarkNickname+ \ '/statuses/'+str(bookmarkStatusNumber) ccUrl=httpPrefix+'://'+bookmarkedomain+'/users/'+bookmarkNickname @@ -454,7 +454,7 @@ def sendBookmarkViaServer(baseDir: str,session, \ if '/statuses/' in bookmarkUrl: toUrl=[bookmarkUrl.split('/statuses/')[0]] - newBookmarkJson = { + newBookmarkJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Bookmark', 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, @@ -474,7 +474,7 @@ def sendBookmarkViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -490,10 +490,12 @@ def sendBookmarkViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newBookmarkJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: @@ -529,7 +531,7 @@ def sendUndoBookmarkViaServer(baseDir: str,session, \ if '/statuses/' in bookmarkUrl: toUrl=[bookmarkUrl.split('/statuses/')[0]] - newUndoBookmarkJson = { + newUndoBookmarkJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Undo', 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, @@ -543,8 +545,8 @@ def sendUndoBookmarkViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - fromDomain,projectVersion) + wfRequest=webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + fromDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -553,7 +555,7 @@ def sendUndoBookmarkViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -569,10 +571,12 @@ def sendUndoBookmarkViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newUndoBookmarkJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: diff --git a/cache.py b/cache.py index 15b3268df..d41554c70 100644 --- a/cache.py +++ b/cache.py @@ -1,10 +1,10 @@ -__filename__ = "cache.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="cache.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import time diff --git a/capabilities.py b/capabilities.py index 983758262..315d241a5 100644 --- a/capabilities.py +++ b/capabilities.py @@ -1,10 +1,10 @@ -__filename__ = "capabilities.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="capabilities.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import datetime @@ -94,7 +94,7 @@ def capabilitiesRequest(baseDir: str,httpPrefix: str,domain: str, \ # which could be instance wide or for a particular person # This could also be added to a follow activity ocapId=createPassword(32) - ocapRequest = { + ocapRequest={ "@context": "https://www.w3.org/ns/activitystreams", "id": httpPrefix+"://"+requestedDomain+"/caps/request/"+ocapId, "type": "Request", @@ -140,7 +140,7 @@ def capabilitiesAccept(baseDir: str,httpPrefix: str, \ ocapId=acceptedActorNickname+'@'+acceptedActorDomain+':'+str(acceptedActorPort)+'#'+createPassword(32) else: ocapId=acceptedActorNickname+'@'+acceptedActorDomain+'#'+createPassword(32) - ocapAccept = { + ocapAccept={ "@context": "https://www.w3.org/ns/activitystreams", "id": httpPrefix+"://"+fullDomain+"/caps/"+ocapId, "type": "Capability", @@ -196,7 +196,7 @@ def capabilitiesUpdate(baseDir: str,httpPrefix: str, \ return None # create an update activity - ocapUpdate = { + ocapUpdate={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Update', 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, diff --git a/config.py b/config.py index 3eda05446..fecf674e2 100644 --- a/config.py +++ b/config.py @@ -1,10 +1,10 @@ -__filename__ = "config.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="config.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import time @@ -18,7 +18,7 @@ def createConfig(baseDir: str) -> None: configFilename=baseDir+'/config.json' if os.path.isfile(configFilename): return - configJson = { + configJson={ } saveJson(configJson,configFilename) diff --git a/content.py b/content.py index d770d8ff9..cc0a89afa 100644 --- a/content.py +++ b/content.py @@ -1,10 +1,10 @@ -__filename__ = "content.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="content.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import time @@ -158,7 +158,8 @@ def addWebLinks(content: str) -> str: def validHashTag(hashtag: str) -> bool: """Returns true if the give hashtag contains valid characters """ - validChars = set('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') + validChars= \ + set('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') if set(hashtag).issubset(validChars): return True return False @@ -417,7 +418,7 @@ def addHtmlTags(baseDir: str,httpPrefix: str, \ if '@' in words: if os.path.isfile(followingFilename): with open(followingFilename, "r") as f: - following = f.readlines() + following=f.readlines() # extract mentions and tags from words longWordsList=[] @@ -569,7 +570,7 @@ def saveMediaInFormPOST(mediaBytes,debug: bool, \ if os.path.isfile(possibleOtherFormat): os.remove(possibleOtherFormat) - fd = open(filename, 'wb') + fd=open(filename, 'wb') fd.write(mediaBytes[startPos:]) fd.close() @@ -579,7 +580,7 @@ def extractTextFieldsInPOST(postBytes,boundary,debug: bool) -> {}: """Returns a dictionary containing the text fields of a http form POST The boundary argument comes from the http header """ - msg = email.parser.BytesParser().parsebytes(postBytes) + msg=email.parser.BytesParser().parsebytes(postBytes) if debug: print('DEBUG: POST arriving '+msg.get_payload(decode=True).decode('utf-8')) messageFields=msg.get_payload(decode=True).decode('utf-8').split(boundary) diff --git a/daemon.py b/daemon.py index c845e39ca..160f6e9d0 100644 --- a/daemon.py +++ b/daemon.py @@ -1,10 +1,10 @@ -__filename__ = "daemon.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="daemon.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" from http.server import BaseHTTPRequestHandler,ThreadingHTTPServer #import socketserver @@ -218,17 +218,17 @@ def readFollowList(filename: str) -> None: followlist=[] if not os.path.isfile(filename): return followlist - followUsers = open(filename, "r") + followUsers=open(filename, "r") for u in followUsers: if u not in followlist: - nickname,domain = parseHandle(u) + nickname,domain=parseHandle(u) if nickname: followlist.append(nickname+'@'+domain) followUsers.close() return followlist class PubServer(BaseHTTPRequestHandler): - protocol_version = 'HTTP/1.1' + protocol_version='HTTP/1.1' def _sendReplyToQuestion(self,nickname: str,messageId: str,answer: str) -> None: """Sends a reply to a question @@ -451,7 +451,7 @@ class PubServer(BaseHTTPRequestHandler): if os.path.isfile(mediaFilename+'.etag'): try: with open(mediaFilename+'.etag', 'r') as etagFile: - etag = etagFile.read() + etag=etagFile.read() except: pass if not etag: @@ -771,7 +771,7 @@ class PubServer(BaseHTTPRequestHandler): beginSaveTime=time.time() # save the json for later queue processing - queueFilename = \ + queueFilename= \ savePostToInboxQueue(self.server.baseDir, self.server.httpPrefix, nickname, @@ -962,7 +962,7 @@ class PubServer(BaseHTTPRequestHandler): self._benchmarkGETtimings(GETstartTime,GETtimings,4) # check authorization - authorized = self._isAuthorized() + authorized=self._isAuthorized() if self.server.debug: if authorized: print('GET Authorization granted') @@ -1270,7 +1270,7 @@ class PubServer(BaseHTTPRequestHandler): while tries<5: try: with open('epicyon-profile.css', 'r') as cssfile: - css = cssfile.read() + css=cssfile.read() break except Exception as e: print(e) @@ -1299,7 +1299,7 @@ class PubServer(BaseHTTPRequestHandler): while tries<5: try: with open(mediaFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() break except Exception as e: print(e) @@ -1324,7 +1324,7 @@ class PubServer(BaseHTTPRequestHandler): while tries<5: try: with open(mediaFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() break except Exception as e: print(e) @@ -1349,7 +1349,7 @@ class PubServer(BaseHTTPRequestHandler): while tries<5: try: with open(mediaFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() break except Exception as e: print(e) @@ -1383,7 +1383,7 @@ class PubServer(BaseHTTPRequestHandler): else: mediaImageType='gif' with open(emojiFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() self._set_headers('image/'+mediaImageType,len(mediaBinary),cookie) self._write(mediaBinary) return @@ -1439,7 +1439,7 @@ class PubServer(BaseHTTPRequestHandler): currEtag='' try: with open(mediaFilename, 'r') as etagFile: - currEtag = etagFile.read() + currEtag=etagFile.read() except: pass if oldEtag==currEtag: @@ -1447,7 +1447,7 @@ class PubServer(BaseHTTPRequestHandler): self._304() return with open(mediaFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() self._set_headers_etag(mediaFilename,mediaFileType,mediaBinary,cookie) self._write(mediaBinary) return @@ -1477,7 +1477,7 @@ class PubServer(BaseHTTPRequestHandler): else: mediaFileType='gif' with open(mediaFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() self._set_headers('image/'+mediaFileType,len(mediaBinary),cookie) self._write(mediaBinary) return @@ -1501,7 +1501,7 @@ class PubServer(BaseHTTPRequestHandler): else: if os.path.isfile(mediaFilename): with open(mediaFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() self._set_headers('image/png',len(mediaBinary),cookie) self._write(mediaBinary) self.server.iconsCache[mediaStr]=mediaBinary @@ -1518,7 +1518,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.baseDir+'/cache/'+self.path if os.path.isfile(mediaFilename): with open(mediaFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() if mediaFilename.endswith('.png'): self._set_headers('image/png',len(mediaBinary),cookie) elif mediaFilename.endswith('.jpg'): @@ -1568,7 +1568,7 @@ class PubServer(BaseHTTPRequestHandler): else: mediaImageType='webp' with open(avatarFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() self._set_headers('image/'+mediaImageType, \ len(mediaBinary),cookie) self._write(mediaBinary) @@ -1861,7 +1861,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.httpPrefix+'://'+self.server.domainFull+ \ '/users/'+self.postToNickname unRepeatToStr='https://www.w3.org/ns/activitystreams#Public' - newUndoAnnounce = { + newUndoAnnounce={ "@context": "https://www.w3.org/ns/activitystreams", 'actor': undoAnnounceActor, 'type': 'Undo', @@ -2534,7 +2534,7 @@ class PubServer(BaseHTTPRequestHandler): nickname+'#statuses#'+statusNumber+'.replies' if not os.path.isfile(postRepliesFilename): # There are no replies, so show empty collection - repliesJson = { + repliesJson={ '@context': 'https://www.w3.org/ns/activitystreams', 'first': self.server.httpPrefix+'://'+self.server.domainFull+'/users/'+nickname+'/statuses/'+statusNumber+'/replies?page=true', 'id': self.server.httpPrefix+'://'+self.server.domainFull+'/users/'+nickname+'/statuses/'+statusNumber+'/replies', @@ -2574,7 +2574,7 @@ class PubServer(BaseHTTPRequestHandler): return else: # replies exist. Itterate through the text file containing message ids - repliesJson = { + repliesJson={ '@context': 'https://www.w3.org/ns/activitystreams', 'id': self.server.httpPrefix+'://'+self.server.domainFull+'/users/'+nickname+'/statuses/'+statusNumber+'?page=true', 'orderedItems': [ @@ -2637,7 +2637,7 @@ class PubServer(BaseHTTPRequestHandler): if actorJson: if actorJson.get('roles'): if self._requestHTTP(): - getPerson = \ + getPerson= \ personLookup(self.server.domain, \ self.path.replace('/roles',''), \ self.server.baseDir) @@ -2683,7 +2683,7 @@ class PubServer(BaseHTTPRequestHandler): if actorJson: if actorJson.get('skills'): if self._requestHTTP(): - getPerson = \ + getPerson= \ personLookup(self.server.domain, \ self.path.replace('/skills',''), \ self.server.baseDir) @@ -3525,7 +3525,7 @@ class PubServer(BaseHTTPRequestHandler): if pageNumberStr.isdigit(): pageNumber=int(pageNumberStr) searchPath=self.path.split('?page=')[0] - getPerson = \ + getPerson= \ personLookup(self.server.domain, \ searchPath.replace('/following',''), \ self.server.baseDir) @@ -3629,7 +3629,7 @@ class PubServer(BaseHTTPRequestHandler): self._benchmarkGETtimings(GETstartTime,GETtimings,52) # look up a person - getPerson = \ + getPerson= \ personLookup(self.server.domain,self.path, \ self.server.baseDir) if getPerson: @@ -3687,7 +3687,7 @@ class PubServer(BaseHTTPRequestHandler): filename=self.server.baseDir+self.path if os.path.isfile(filename): with open(filename, 'r', encoding='utf-8') as File: - content = File.read() + content=File.read() contentJson=json.loads(content) msg=json.dumps(contentJson,ensure_ascii=False).encode('utf-8') self._set_headers('application/json',len(msg),None) @@ -3723,12 +3723,12 @@ class PubServer(BaseHTTPRequestHandler): if os.path.isfile(mediaFilename+'.etag'): try: with open(mediaFilename+'.etag', 'r') as etagFile: - etag = etagFile.read() + etag=etagFile.read() except: pass else: with open(mediaFilename, 'rb') as avFile: - mediaBinary = avFile.read() + mediaBinary=avFile.read() etag=sha1(mediaBinary).hexdigest() try: with open(mediaFilename+'.etag', 'w') as etagFile: @@ -3760,10 +3760,10 @@ class PubServer(BaseHTTPRequestHandler): postType: str,path: str,headers: {}, length: int,postBytes,boundary: str) -> int: # Note: this needs to happen synchronously - # 0 = this is not a new post - # 1 = new post success - # -1 = new post failed - # 2 = new post canceled + # 0=this is not a new post + # 1=new post success + # -1=new post failed + # 2=new post canceled if self.server.debug: print('DEBUG: receiving POST') @@ -3776,7 +3776,7 @@ class PubServer(BaseHTTPRequestHandler): nickname=nicknameStr.split('/')[0] else: return -1 - length = int(headers['Content-Length']) + length=int(headers['Content-Length']) if length>self.server.maxPostLength: print('POST size too large') return -1 @@ -4229,7 +4229,7 @@ class PubServer(BaseHTTPRequestHandler): headersWithoutCookie[dictEntryName]=headerLine print('New post headers: '+str(headersWithoutCookie)) - length = int(headers['Content-Length']) + length=int(headers['Content-Length']) if length>self.server.maxPostLength: print('POST size too large') return None @@ -4304,7 +4304,7 @@ class PubServer(BaseHTTPRequestHandler): cookie=self.headers['Cookie'] # check authorization - authorized = self._isAuthorized() + authorized=self._isAuthorized() if self.server.debug: if authorized: print('POST Authorization granted') @@ -4320,7 +4320,7 @@ class PubServer(BaseHTTPRequestHandler): if self.path.startswith('/login'): # get the contents of POST containing login credentials - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) if length>512: print('Login failed - credentials too long') self.send_response(401) @@ -4368,7 +4368,7 @@ class PubServer(BaseHTTPRequestHandler): if os.path.isfile(saltFilename): try: with open(saltFilename, 'r') as fp: - salt = fp.read() + salt=fp.read() except Exception as e: print('WARN: Unable to read salt for '+ \ loginNickname+' '+str(e)) @@ -4430,7 +4430,7 @@ class PubServer(BaseHTTPRequestHandler): self._redirect_headers(actorStr,cookie) self.server.POSTbusy=False return - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) if length>self.server.maxPostLength: print('Maximum profile data length exceeded '+str(length)) self._redirect_headers(actorStr,cookie) @@ -4855,7 +4855,7 @@ class PubServer(BaseHTTPRequestHandler): actorStr= \ self.server.httpPrefix+'://'+self.server.domainFull+ \ self.path.replace('/moderationaction','') - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) moderationParams=self.rfile.read(length).decode('utf-8') print('moderationParams: '+moderationParams) if '&' in moderationParams: @@ -4995,7 +4995,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.POSTbusy=False return # get the parameters - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) questionParams=self.rfile.read(length).decode('utf-8') questionParams= \ questionParams.replace('+',' ').replace('%40','@').replace('%3A',':').replace('%23','#').replace('%2F','/').replace('%3F','').strip() @@ -5034,7 +5034,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.httpPrefix+'://'+ \ self.server.domainFull+ \ self.path.replace('/searchhandle','') - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) searchParams=self.rfile.read(length).decode('utf-8') if 'submitBack=' in searchParams: # go back on search screen @@ -5165,7 +5165,7 @@ class PubServer(BaseHTTPRequestHandler): originPathStr= \ self.server.httpPrefix+'://'+self.server.domainFull+ \ self.path.split('/rmshare')[0] - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) removeShareConfirmParams=self.rfile.read(length).decode('utf-8') if '&submitYes=' in removeShareConfirmParams: removeShareConfirmParams= \ @@ -5193,7 +5193,7 @@ class PubServer(BaseHTTPRequestHandler): originPathStr= \ self.server.httpPrefix+'://'+self.server.domainFull+ \ self.path.split('/rmpost')[0] - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) removePostConfirmParams=self.rfile.read(length).decode('utf-8') if '&submitYes=' in removePostConfirmParams: removePostConfirmParams= \ @@ -5255,7 +5255,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.httpPrefix+'://'+self.server.domainFull+ \ self.path.split('/followconfirm')[0] followerNickname=getNicknameFromActor(originPathStr) - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) followConfirmParams=self.rfile.read(length).decode('utf-8') if '&submitView=' in followConfirmParams: followingActor= \ @@ -5308,7 +5308,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.httpPrefix+'://'+self.server.domainFull+ \ self.path.split('/unfollowconfirm')[0] followerNickname=getNicknameFromActor(originPathStr) - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) followConfirmParams=self.rfile.read(length).decode('utf-8') if '&submitYes=' in followConfirmParams: followingActor= \ @@ -5329,9 +5329,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.httpPrefix+'://'+ \ self.server.domainFull+ \ '/users/'+followerNickname - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() followId=followActor+'/statuses/'+str(statusNumber) - unfollowJson = { + unfollowJson={ '@context': 'https://www.w3.org/ns/activitystreams', 'id': followId+'/undo', 'type': 'Undo', @@ -5363,7 +5363,7 @@ class PubServer(BaseHTTPRequestHandler): self._redirect_headers(originPathStr,cookie) self.server.POSTbusy=False return - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) blockConfirmParams=self.rfile.read(length).decode('utf-8') if '&submitYes=' in blockConfirmParams: blockingActor= \ @@ -5410,7 +5410,7 @@ class PubServer(BaseHTTPRequestHandler): self._redirect_headers(originPathStr,cookie) self.server.POSTbusy=False return - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) blockConfirmParams=self.rfile.read(length).decode('utf-8') if '&submitYes=' in blockConfirmParams: blockingActor= \ @@ -5462,7 +5462,7 @@ class PubServer(BaseHTTPRequestHandler): self._redirect_headers(originPathStr,cookie) self.server.POSTbusy=False return - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) optionsConfirmParams= \ self.rfile.read(length).decode('utf-8').replace('%3A',':').replace('%2F','/') # page number to return to @@ -5671,7 +5671,7 @@ class PubServer(BaseHTTPRequestHandler): self._benchmarkPOSTtimings(POSTstartTime,POSTtimings,17) # read the message and convert it into a python dictionary - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) if self.server.debug: print('DEBUG: content-length: '+str(length)) if not self.headers['Content-type'].startswith('image/') and \ @@ -5740,7 +5740,7 @@ class PubServer(BaseHTTPRequestHandler): print("POST is not json: "+self.headers['Content-type']) if self.server.debug: print(str(self.headers)) - length = int(self.headers['Content-length']) + length=int(self.headers['Content-length']) if length10240: print('WARN: post to shared inbox is too long '+str(length)+' bytes') self._400() @@ -5897,7 +5897,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.POSTbusy=False class PubServerUnitTest(PubServer): - protocol_version = 'HTTP/1.0' + protocol_version='HTTP/1.0' def runPostsQueue(baseDir: str,sendThreads: [],debug: bool) -> None: """Manages the threads used to send posts @@ -5952,7 +5952,7 @@ def loadTokens(baseDir: str,tokensDict: {},tokensLookup: {}) -> None: token=None try: with open(tokenFilename, 'r') as fp: - token = fp.read() + token=fp.read() except Exception as e: print('WARN: Unable to read token for '+nickname+' '+str(e)) if not token: @@ -5984,14 +5984,14 @@ def runDaemon(blogsInstance: bool,mediaInstance: bool, \ return if unitTest: - serverAddress = (domain, proxyPort) - pubHandler = partial(PubServerUnitTest) + serverAddress=(domain, proxyPort) + pubHandler=partial(PubServerUnitTest) else: - serverAddress = ('', proxyPort) - pubHandler = partial(PubServer) + serverAddress=('', proxyPort) + pubHandler=partial(PubServer) try: - httpd = ThreadingHTTPServer(serverAddress, pubHandler) + httpd=ThreadingHTTPServer(serverAddress, pubHandler) except Exception as e: if e.errno==98: print('ERROR: HTTP server address is already in use. '+str(serverAddress)) @@ -6068,7 +6068,7 @@ def runDaemon(blogsInstance: bool,mediaInstance: bool, \ httpd.personCache={} httpd.cachedWebfingers={} httpd.useTor=useTor - httpd.session = None + httpd.session=None httpd.sessionLastUpdate=0 httpd.lastGET=0 httpd.lastPOST=0 diff --git a/delete.py b/delete.py index 627f7c88d..64e3a95b9 100644 --- a/delete.py +++ b/delete.py @@ -1,10 +1,10 @@ -__filename__ = "delete.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="delete.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import json @@ -46,10 +46,10 @@ def createDelete(session,baseDir: str,federationList: [], \ if ':' not in domain: fullDomain=domain+':'+str(port) - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() newDeleteId= \ httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber - newDelete = { + newDelete={ "@context": "https://www.w3.org/ns/activitystreams", 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, 'atomUri': httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber, @@ -101,10 +101,10 @@ def sendDeleteViaServer(baseDir: str,session, \ if ':' not in fromDomain: fromDomainFull=fromDomain+':'+str(fromPort) - toUrl = 'https://www.w3.org/ns/activitystreams#Public' - ccUrl = httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers' + toUrl='https://www.w3.org/ns/activitystreams#Public' + ccUrl=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers' - newDeleteJson = { + newDeleteJson={ "@context": "https://www.w3.org/ns/activitystreams", 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, 'cc': [ccUrl], @@ -116,8 +116,9 @@ def sendDeleteViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - fromDomain,projectVersion) + wfRequest= \ + webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + fromDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -126,7 +127,7 @@ def sendDeleteViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -142,10 +143,12 @@ def sendDeleteViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newDeleteJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: @@ -171,8 +174,8 @@ def deletePublic(session,baseDir: str,federationList: [], \ if ':' not in domain: fromDomain=domain+':'+str(port) - toUrl = 'https://www.w3.org/ns/activitystreams#Public' - ccUrl = httpPrefix + '://'+fromDomain+'/users/'+nickname+'/followers' + toUrl='https://www.w3.org/ns/activitystreams#Public' + ccUrl=httpPrefix+'://'+fromDomain+'/users/'+nickname+'/followers' return createDelete(session,baseDir,federationList, \ nickname,domain,port, \ toUrl,ccUrl,httpPrefix, \ @@ -197,7 +200,7 @@ def deletePostPub(session,baseDir: str,federationList: [], \ if ':' not in deletedDomain: deletedDomain=deletedDomain+':'+str(deletePort) - objectUrl = \ + objectUrl= \ deleteHttpsPrefix + '://'+deletedDomain+'/users/'+ \ deleteNickname+'/statuses/'+str(deleteStatusNumber) diff --git a/donate.py b/donate.py index fd53936fe..884d5f006 100644 --- a/donate.py +++ b/donate.py @@ -1,10 +1,10 @@ -__filename__ = "donate.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="donate.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json diff --git a/epicyon.py b/epicyon.py index 10a65c46a..28e63e9f8 100644 --- a/epicyon.py +++ b/epicyon.py @@ -1,10 +1,10 @@ -__filename__ = "epicyon.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="epicyon.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" from person import createPerson from person import createGroup @@ -93,7 +93,7 @@ def str2bool(v): else: raise argparse.ArgumentTypeError('Boolean value expected.') -parser = argparse.ArgumentParser(description='ActivityPub Server') +parser=argparse.ArgumentParser(description='ActivityPub Server') parser.add_argument('-n','--nickname', dest='nickname', type=str,default=None, \ help='Nickname of the account to use') parser.add_argument('--fol','--follow', dest='follow', type=str,default=None, \ @@ -311,7 +311,7 @@ parser.add_argument('--maxregistrations', dest='maxRegistrations', type=int,defa parser.add_argument("--resetregistrations", type=str2bool, nargs='?', \ const=True, default=False, \ help="Reset the number of remaining registrations") -args = parser.parse_args() +args=parser.parse_args() debug=False if args.debug: @@ -365,9 +365,11 @@ if args.postsraw: sys.exit() if args.json: - session = createSession(False) - asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} - testJson = getJson(session,args.json,asHeader,None,__version__,httpPrefix,None) + session=createSession(False) + asHeader={ + 'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } + testJson=getJson(session,args.json,asHeader,None,__version__,httpPrefix,None) pprint(testJson) sys.exit() @@ -533,7 +535,7 @@ if args.approve: if '@' not in args.approve: print('syntax: --approve nick@domain') sys.exit() - session = createSession(useTor) + session=createSession(useTor) sendThreads=[] postLog=[] cachedWebfingers={} @@ -557,7 +559,7 @@ if args.deny: if '@' not in args.deny: print('syntax: --deny nick@domain') sys.exit() - session = createSession(useTor) + session=createSession(useTor) sendThreads=[] postLog=[] cachedWebfingers={} @@ -599,7 +601,7 @@ if args.message: print('Specify a password with the --password option') sys.exit() - session = createSession(useTor) + session=createSession(useTor) if not args.sendto: print('Specify an account to sent to: --sendto [nickname@domain]') sys.exit() @@ -634,8 +636,8 @@ if args.message: clientToServer=args.client attachedImageDescription=args.imageDescription useBlurhash=args.blurhash - sendThreads = [] - postLog = [] + sendThreads=[] + postLog=[] personCache={} cachedWebfingers={} subject=args.subject @@ -671,7 +673,7 @@ if args.announce: print('Specify a password with the --password option') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending announce/repeat of '+args.announce) @@ -715,7 +717,7 @@ if args.itemName: print('Specify a duration to share the object with the --duration option') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending shared item: '+args.itemName) @@ -747,7 +749,7 @@ if args.undoItemName: print('Specify a nickname with the --nickname option') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending undo of shared item: '+args.undoItemName) @@ -773,7 +775,7 @@ if args.like: print('Specify a password with the --password option') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending like of '+args.like) @@ -798,7 +800,7 @@ if args.undolike: print('Specify a password with the --password option') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending undo like of '+args.undolike) @@ -823,7 +825,7 @@ if args.delete: print('Specify a password with the --password option') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending delete request of '+args.delete) @@ -857,7 +859,7 @@ if args.follow: sys.exit() followDomain,followPort=getDomainFromActor(args.follow) - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} followHttpPrefix=httpPrefix @@ -895,7 +897,7 @@ if args.unfollow: sys.exit() followDomain,followPort=getDomainFromActor(args.unfollow) - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} followHttpPrefix=httpPrefix @@ -994,24 +996,34 @@ if args.actor: else: sys.exit() - asHeader = {'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"'} + asHeader={ + 'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"' + } if not personUrl: - personUrl = getUserUrl(wfRequest) + personUrl=getUserUrl(wfRequest) if nickname==domain: personUrl=personUrl.replace('/users/','/actor/').replace('/channel/','/actor/').replace('/profile/','/actor/') if not personUrl: # try single user instance personUrl=httpPrefix+'://'+domain - asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} + asHeader={ + 'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } if '/channel/' in personUrl: - asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} + asHeader={ + 'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } - personJson = getJson(session,personUrl,asHeader,None,__version__,httpPrefix,None) + personJson= \ + getJson(session,personUrl,asHeader,None,__version__,httpPrefix,None) if personJson: pprint(personJson) else: - asHeader = {'Accept': 'application/jrd+json; profile="https://www.w3.org/ns/activitystreams"'} - personJson = getJson(session,personUrl,asHeader,None,__version__,httpPrefix,None) + asHeader={ + 'Accept': 'application/jrd+json; profile="https://www.w3.org/ns/activitystreams"' + } + personJson= \ + getJson(session,personUrl,asHeader,None,__version__,httpPrefix,None) if personJson: pprint(personJson) else: @@ -1237,7 +1249,7 @@ if args.skill: print('Skill level should be a percentage in the range 0-100') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending '+args.skill+' skill level '+str(args.skillLevelPercent)+' for '+nickname) @@ -1263,7 +1275,7 @@ if args.availability: print('Specify a password with the --password option') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending availability status of '+nickname+' as '+args.availability) @@ -1308,7 +1320,7 @@ if args.block: print(args.block+' does not look like an actor url') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending block of '+args.block) @@ -1344,7 +1356,7 @@ if args.delegate: delegatedNickname=args.delegate.split('@')[0] args.delegate=blockedActor - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending delegation for '+args.delegate+' with role '+args.role+' in project '+args.project) @@ -1378,7 +1390,7 @@ if args.undelegate: delegatedNickname=args.undelegate.split('@')[0] args.undelegate=blockedActor - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending delegation removal for '+args.undelegate+' from role '+args.role+' in project '+args.project) @@ -1414,7 +1426,7 @@ if args.unblock: print(args.unblock+' does not look like an actor url') sys.exit() - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} print('Sending undo block of '+args.unblock) diff --git a/filters.py b/filters.py index 0d843b720..d14f21aea 100644 --- a/filters.py +++ b/filters.py @@ -1,10 +1,10 @@ -__filename__ = "filters.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="filters.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os diff --git a/follow.py b/follow.py index 22eaafbf5..07bb40afb 100644 --- a/follow.py +++ b/follow.py @@ -1,10 +1,10 @@ -__filename__ = "follow.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="follow.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import time @@ -56,7 +56,7 @@ def removeFromFollowBase(baseDir: str, \ return if acceptOrDenyHandle not in open(approveFollowsFilename).read(): return - approvefilenew = open(approveFollowsFilename+'.new', 'w+') + approvefilenew=open(approveFollowsFilename+'.new', 'w+') with open(approveFollowsFilename, 'r') as approvefile: for approveHandle in approvefile: if not approveHandle.startswith(acceptOrDenyHandle): @@ -137,8 +137,8 @@ def getFollowersOfPerson(baseDir: str, \ return followers for subdir, dirs, files in os.walk(baseDir+'/accounts'): for account in dirs: - filename = os.path.join(subdir, account)+'/'+followFile - if account == handle or account.startswith('inbox@'): + filename=os.path.join(subdir, account)+'/'+followFile + if account==handle or account.startswith('inbox@'): continue if not os.path.isfile(filename): continue @@ -195,7 +195,7 @@ def unfollowPerson(baseDir: str,nickname: str, domain: str, \ print('DEBUG: handle to unfollow '+handleToUnfollow+' is not in '+filename) return with open(filename, "r") as f: - lines = f.readlines() + lines=f.readlines() with open(filename, "w") as f: for line in lines: if line.strip("\n") != handleToUnfollow: @@ -254,9 +254,9 @@ def getNoOfFollows(baseDir: str,nickname: str,domain: str, \ filename=baseDir+'/accounts/'+handle+'/'+followFile if not os.path.isfile(filename): return 0 - ctr = 0 + ctr=0 with open(filename, "r") as f: - lines = f.readlines() + lines=f.readlines() for line in lines: if '#' not in line: if '@' in line and '.' in line and not line.startswith('http'): @@ -315,25 +315,27 @@ def getFollowingFeed(baseDir: str,domain: str,port: int,path: str, \ domain=domain+':'+str(port) if headerOnly: - following = { + following={ '@context': 'https://www.w3.org/ns/activitystreams', 'first': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page=1', 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile, 'totalItems': getNoOfFollows(baseDir,nickname,domain,authenticated), - 'type': 'OrderedCollection'} + 'type': 'OrderedCollection' + } return following if not pageNumber: pageNumber=1 nextPageNumber=int(pageNumber+1) - following = { + following={ '@context': 'https://www.w3.org/ns/activitystreams', 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page='+str(pageNumber), 'orderedItems': [], 'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile, 'totalItems': 0, - 'type': 'OrderedCollectionPage'} + 'type': 'OrderedCollectionPage' + } handleDomain=domain if ':' in handleDomain: @@ -346,15 +348,15 @@ def getFollowingFeed(baseDir: str,domain: str,port: int,path: str, \ pageCtr=0 totalCtr=0 with open(filename, "r") as f: - lines = f.readlines() + lines=f.readlines() for line in lines: if '#' not in line: if '@' in line and not line.startswith('http'): pageCtr += 1 totalCtr += 1 if currPage==pageNumber: - url = httpPrefix + '://' + line.lower().replace('\n','').split('@')[1] + \ - '/users/' + line.lower().replace('\n','').split('@')[0] + url=httpPrefix+'://' + line.lower().replace('\n','').split('@')[1] + \ + '/users/'+line.lower().replace('\n','').split('@')[0] following['orderedItems'].append(url) elif (line.startswith('http') or line.startswith('dat')) and '/users/' in line: pageCtr += 1 @@ -411,7 +413,7 @@ def noOfFollowRequests(baseDir: str, \ return 0 ctr=0 with open(approveFollowsFilename, "r") as f: - lines = f.readlines() + lines=f.readlines() if followType != "onion": return len(lines) for l in lines: @@ -590,7 +592,7 @@ def receiveFollowRequest(session,baseDir: str,httpPrefix: str, \ if approveHandle not in open(followersFilename).read(): try: with open(followersFilename, 'r+') as followersFile: - content = followersFile.read() + content=followersFile.read() followersFile.seek(0, 0) followersFile.write(approveHandle+'\n'+content) except Exception as e: @@ -746,7 +748,7 @@ def sendFollowRequest(session,baseDir: str, \ if ':' not in followDomain: requestDomain=followDomain+':'+str(followPort) - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() if followNickname: followedId=followHttpPrefix+'://'+requestDomain+'/users/'+followNickname @@ -758,7 +760,7 @@ def sendFollowRequest(session,baseDir: str, \ singleUserNickname='dev' followHandle=singleUserNickname+'@'+requestDomain - newFollowJson = { + newFollowJson={ '@context': 'https://www.w3.org/ns/activitystreams', 'id': followActor+'/statuses/'+str(statusNumber), 'type': 'Follow', @@ -813,8 +815,8 @@ def sendFollowRequestViaServer(baseDir: str,session, \ followActor=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname followedId=httpPrefix+'://'+followDomainFull+'/users/'+followNickname - statusNumber,published = getStatusNumber() - newFollowJson = { + statusNumber,published=getStatusNumber() + newFollowJson={ '@context': 'https://www.w3.org/ns/activitystreams', 'id': followActor+'/statuses/'+str(statusNumber), 'type': 'Follow', @@ -825,8 +827,9 @@ def sendFollowRequestViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - fromDomain,projectVersion) + wfRequest= \ + webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + fromDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -835,7 +838,7 @@ def sendFollowRequestViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -851,10 +854,12 @@ def sendFollowRequestViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newFollowJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: @@ -892,9 +897,9 @@ def sendUnfollowRequestViaServer(baseDir: str,session, \ followActor=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname followedId=httpPrefix+'://'+followDomainFull+'/users/'+followNickname - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() - unfollowJson = { + unfollowJson={ '@context': 'https://www.w3.org/ns/activitystreams', 'id': followActor+'/statuses/'+str(statusNumber)+'/undo', 'type': 'Undo', @@ -910,8 +915,9 @@ def sendUnfollowRequestViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - fromDomain,projectVersion) + wfRequest= \ + webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + fromDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -920,7 +926,7 @@ def sendUnfollowRequestViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -936,10 +942,12 @@ def sendUnfollowRequestViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,unfollowJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: @@ -980,7 +988,7 @@ def getFollowersOfActor(baseDir :str,actor :str,debug: bool) -> {}: for subdir, dirs, files in os.walk(baseDir+'/accounts'): for account in dirs: if '@' in account and not account.startswith('inbox@'): - followingFilename = os.path.join(subdir, account)+'/following.txt' + followingFilename=os.path.join(subdir, account)+'/following.txt' if debug: print('DEBUG: examining follows of '+account) print(followingFilename) diff --git a/happening.py b/happening.py index f03866645..940f8bd60 100644 --- a/happening.py +++ b/happening.py @@ -1,10 +1,10 @@ -__filename__ = "happening.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="happening.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import time @@ -380,7 +380,7 @@ def removeCalendarEvent(baseDir: str,nickname: str,domain: str, \ return lines=None with open(calendarFilename, "r") as f: - lines = f.readlines() + lines=f.readlines() if not lines: return with open(calendarFilename, "w+") as f: diff --git a/httpsig.py b/httpsig.py index 202169bb4..94a3d0129 100644 --- a/httpsig.py +++ b/httpsig.py @@ -1,11 +1,11 @@ -__filename__ = "posts.py" -__author__ = "Bob Mottram" -__credits__ = ['lamia'] -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="posts.py" +__author__="Bob Mottram" +__credits__=['lamia'] +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" # see https://tools.ietf.org/html/draft-cavage-http-signatures-06 @@ -63,27 +63,27 @@ def signPostHeaders(dateStr: str,privateKeyPem: str, \ # '(request-target)': f'post {path}', #}) # build a digest for signing - signedHeaderKeys = headers.keys() - signedHeaderText = '' + signedHeaderKeys=headers.keys() + signedHeaderText='' for headerKey in signedHeaderKeys: signedHeaderText += f'{headerKey}: {headers[headerKey]}\n' #print(f'*********************signing: headerKey: {headerKey}: {headers[headerKey]}') - signedHeaderText = signedHeaderText.strip() + signedHeaderText=signedHeaderText.strip() #print('******************************Send: signedHeaderText: '+signedHeaderText) - headerDigest = SHA256.new(signedHeaderText.encode('ascii')) + headerDigest=SHA256.new(signedHeaderText.encode('ascii')) # Sign the digest - rawSignature = pkcs1_15.new(privateKeyPem).sign(headerDigest) - signature = base64.b64encode(rawSignature).decode('ascii') + rawSignature=pkcs1_15.new(privateKeyPem).sign(headerDigest) + signature=base64.b64encode(rawSignature).decode('ascii') # Put it into a valid HTTP signature format - signatureDict = { + signatureDict={ 'keyId': keyID, 'algorithm': 'rsa-sha256', 'headers': ' '.join(signedHeaderKeys), 'signature': signature } - signatureHeader = ','.join( + signatureHeader=','.join( [f'{k}="{v}"' for k, v in signatureDict.items()]) return signatureHeader @@ -104,8 +104,10 @@ def createSignedHeader(privateKeyPem: str,nickname: str, \ dateStr=strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime()) if not withDigest: - headers = {'(request-target)': f'post {path}','host': headerDomain,'date': dateStr} - signatureHeader = \ + headers={ + '(request-target)': f'post {path}','host': headerDomain,'date': dateStr + } + signatureHeader= \ signPostHeaders(dateStr,privateKeyPem,nickname, \ domain,port,toDomain,toPort, \ path,httpPrefix,None) @@ -119,13 +121,20 @@ def createSignedHeader(privateKeyPem: str,nickname: str, \ #print('***************************Send Content-type: '+contentType) #print('***************************Send Content-Length: '+str(len(messageBodyJsonStr))) #print('***************************Send messageBodyJsonStr: '+messageBodyJsonStr) - headers = {'(request-target)': f'post {path}','host': headerDomain,'date': dateStr,'digest': f'SHA-256={bodyDigest}','content-length': str(contentLength),'content-type': contentType} - signatureHeader = \ + headers={ + '(request-target)': f'post {path}', + 'host': headerDomain, + 'date': dateStr, + 'digest': f'SHA-256={bodyDigest}', + 'content-length': str(contentLength), + 'content-type': contentType + } + signatureHeader= \ signPostHeaders(dateStr,privateKeyPem,nickname, \ domain,port, \ toDomain,toPort, \ path,httpPrefix,messageBodyJsonStr) - headers['signature'] = signatureHeader + headers['signature']=signatureHeader return headers def verifyRecentSignature(signedDateStr: str) -> bool: @@ -167,10 +176,10 @@ def verifyPostHeaders(httpPrefix: str,publicKeyPem: str,headers: dict, \ if debug: print('DEBUG: verifyPostHeaders '+method) - publicKeyPem = RSA.import_key(publicKeyPem) + publicKeyPem=RSA.import_key(publicKeyPem) # Build a dictionary of the signature values - signatureHeader = headers['signature'] - signatureDict = { + signatureHeader=headers['signature'] + signatureDict={ k: v[1:-1] for k, v in [i.split('=', 1) for i in signatureHeader.split(',')] } @@ -179,7 +188,7 @@ def verifyPostHeaders(httpPrefix: str,publicKeyPem: str,headers: dict, \ # Unpack the signed headers and set values based on current headers and # body (if a digest was included) - signedHeaderList = [] + signedHeaderList=[] for signedHeader in signatureDict['headers'].split(' '): if debug: print('DEBUG: verifyPostHeaders signedHeader='+signedHeader) @@ -236,12 +245,12 @@ def verifyPostHeaders(httpPrefix: str,publicKeyPem: str,headers: dict, \ if debug: print('DEBUG: signedHeaderList: '+str(signedHeaderList)) # Now we have our header data digest - signedHeaderText = '\n'.join(signedHeaderList) + signedHeaderText='\n'.join(signedHeaderList) #print('***********************Verify: signedHeaderText: '+signedHeaderText) - headerDigest = SHA256.new(signedHeaderText.encode('ascii')) + headerDigest=SHA256.new(signedHeaderText.encode('ascii')) # Get the signature, verify with public key, return result - signature = base64.b64decode(signatureDict['signature']) + signature=base64.b64decode(signatureDict['signature']) try: pkcs1_15.new(publicKeyPem).verify(headerDigest, signature) diff --git a/inbox.py b/inbox.py index ffd262b3d..640ddf23e 100644 --- a/inbox.py +++ b/inbox.py @@ -1,10 +1,10 @@ -__filename__ = "inbox.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="inbox.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import os @@ -101,7 +101,7 @@ def storeHashTags(baseDir: str,nickname: str,postJsonObject: {}) -> None: if postUrl not in open(tagsFilename).read(): try: with open(tagsFilename, 'r+') as tagsFile: - content = tagsFile.read() + content=tagsFile.read() tagsFile.seek(0, 0) tagsFile.write(tagline+content) except Exception as e: @@ -142,7 +142,7 @@ def validInbox(baseDir: str,nickname: str,domain: str) -> bool: return True for subdir, dirs, files in os.walk(inboxDir): for f in files: - filename = os.path.join(subdir, f) + filename=os.path.join(subdir, f) if not os.path.isfile(filename): print('filename: '+filename) return False @@ -164,7 +164,7 @@ def validInboxFilenames(baseDir: str,nickname: str,domain: str, \ expectedStr=expectedDomain+':'+str(expectedPort) for subdir, dirs, files in os.walk(inboxDir): for f in files: - filename = os.path.join(subdir, f) + filename=os.path.join(subdir, f) if not os.path.isfile(filename): print('filename: '+filename) return False @@ -185,7 +185,7 @@ def getPersonPubKey(baseDir: str,session,personUrl: str, \ if debug: print('DEBUG: Obtaining public key for shared inbox') personUrl=personUrl.replace('/users/inbox','/inbox') - personJson = getPersonFromCache(baseDir,personUrl,personCache) + personJson=getPersonFromCache(baseDir,personUrl,personCache) if not personJson: if debug: print('DEBUG: Obtaining public key for '+personUrl) @@ -193,10 +193,10 @@ def getPersonPubKey(baseDir: str,session,personUrl: str, \ if onionDomain: if '.onion/' in personUrl: personDomain=onionDomain - asHeader = { + asHeader={ 'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"' } - personJson = \ + personJson= \ getJson(session,personUrl,asHeader,None,projectVersion, \ httpPrefix,personDomain) if not personJson: @@ -258,7 +258,7 @@ def inboxPermittedMessage(domain: str,messageJson: {},federationList: []) -> boo def validPublishedDate(published: str) -> bool: currTime=datetime.datetime.utcnow() pubDate=datetime.datetime.strptime(published,"%Y-%m-%dT%H:%M:%SZ") - daysSincePublished = (currTime - pubTime).days + daysSincePublished=(currTime - pubTime).days if daysSincePublished>30: return False return True @@ -340,7 +340,7 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str, \ postId=postJsonObject['id'].replace('/activity','').replace('/undo','') published=currTime.strftime("%Y-%m-%dT%H:%M:%SZ") if not postId: - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() if actor: postId=actor+'/statuses/'+statusNumber else: @@ -372,7 +372,7 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str, \ timeDiffStr='0'+timeDiffStr print('DIGEST|'+timeDiffStr+'|'+filename) - newQueueItem = { + newQueueItem={ 'originalId': originalPostId, 'id': postId, 'actor': actor, @@ -531,7 +531,7 @@ def inboxPostRecipients(baseDir :str,postJsonObject :{}, \ domain=domain+':'+str(port) domainMatch='/'+domain+'/users/' - actor = postJsonObject['actor'] + actor=postJsonObject['actor'] # first get any specific people which the post is addressed to followerRecipients=False @@ -1417,7 +1417,7 @@ def populateReplies(baseDir :str,httpPrefix :str,domain :str, \ postRepliesFilename=postFilename.replace('.json','.replies') messageId=messageJson['id'].replace('/activity','').replace('/undo','') if os.path.isfile(postRepliesFilename): - numLines = sum(1 for line in open(postRepliesFilename)) + numLines=sum(1 for line in open(postRepliesFilename)) if numLines>maxReplies: return False if messageId not in open(postRepliesFilename).read(): @@ -1727,7 +1727,7 @@ def inboxUpdateIndex(boxname: str,baseDir: str,handle: str,destinationFilename: if os.path.isfile(indexFilename): try: with open(indexFilename, 'r+') as indexFile: - content = indexFile.read() + content=indexFile.read() indexFile.seek(0, 0) indexFile.write(destinationFilename+'\n'+content) return True diff --git a/like.py b/like.py index 7f632e1f7..b4948fa4c 100644 --- a/like.py +++ b/like.py @@ -1,10 +1,10 @@ -__filename__ = "like.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="like.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import json @@ -135,7 +135,7 @@ def updateLikesCollection(recentPostsCache: {}, \ if not postJsonObject['object'].get('likes'): if debug: print('DEBUG: Adding initial likes to '+objectUrl) - likesJson = { + likesJson={ "@context": "https://www.w3.org/ns/activitystreams", 'id': objectUrl, 'type': 'Collection', @@ -193,7 +193,7 @@ def like(recentPostsCache: {}, \ if '/statuses/' in objectUrl: likeTo=[objectUrl.split('/statuses/')[0]] - newLikeJson = { + newLikeJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Like', 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, @@ -302,7 +302,7 @@ def undolike(recentPostsCache: {}, \ if '/statuses/' in objectUrl: likeTo=[objectUrl.split('/statuses/')[0]] - newUndoLikeJson = { + newUndoLikeJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Undo', 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, @@ -368,8 +368,8 @@ def undoLikePost(recentPostsCache: {}, \ if ':' not in likeDomain: likeDomain=likeDomain+':'+str(likePort) - objectUrl = \ - httpPrefix + '://'+likeDomain+'/users/'+likeNickname+ \ + objectUrl= \ + httpPrefix+'://'+likeDomain+'/users/'+likeNickname+ \ '/statuses/'+str(likeStatusNumber) ccUrl=httpPrefix+'://'+likeDomain+'/users/'+likeNickname @@ -409,7 +409,7 @@ def sendLikeViaServer(baseDir: str,session, \ if '/statuses/' in likeUrl: toUrl=[likeUrl.split('/statuses/')[0]] - newLikeJson = { + newLikeJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Like', 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, @@ -429,7 +429,7 @@ def sendLikeViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -445,10 +445,12 @@ def sendLikeViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newLikeJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: @@ -484,7 +486,7 @@ def sendUndoLikeViaServer(baseDir: str,session, \ if '/statuses/' in likeUrl: toUrl=[likeUrl.split('/statuses/')[0]] - newUndoLikeJson = { + newUndoLikeJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Undo', 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, @@ -498,8 +500,9 @@ def sendUndoLikeViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - fromDomain,projectVersion) + wfRequest= \ + webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + fromDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -508,7 +511,7 @@ def sendUndoLikeViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -524,10 +527,12 @@ def sendUndoLikeViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newUndoLikeJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: diff --git a/manualapprove.py b/manualapprove.py index f79c5e425..60452caee 100644 --- a/manualapprove.py +++ b/manualapprove.py @@ -1,10 +1,10 @@ -__filename__ = "manualapprove.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="manualapprove.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import json @@ -99,7 +99,7 @@ def manualApproveFollowRequest(session,baseDir: str, \ print('Manual follow accept: '+approveHandle+' not in requests file '+approveFollowsFilename) return - approvefilenew = open(approveFollowsFilename+'.new', 'w+') + approvefilenew=open(approveFollowsFilename+'.new', 'w+') updateApprovedFollowers=False followActivityfilename=None with open(approveFollowsFilename, 'r') as approvefile: @@ -147,7 +147,7 @@ def manualApproveFollowRequest(session,baseDir: str, \ if approveHandle not in open(followersFilename).read(): try: with open(followersFilename, 'r+') as followersFile: - content = followersFile.read() + content=followersFile.read() followersFile.seek(0, 0) followersFile.write(approveHandle+'\n'+content) except Exception as e: diff --git a/matrix.py b/matrix.py index 61835f597..2e4ab2f66 100644 --- a/matrix.py +++ b/matrix.py @@ -1,10 +1,10 @@ -__filename__ = "matrix.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="matrix.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json diff --git a/media.py b/media.py index 82a21590a..6a04eadd4 100644 --- a/media.py +++ b/media.py @@ -1,10 +1,10 @@ -__filename__ = "media.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="media.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" from blurhash import blurhash_encode as blurencode from PIL import Image diff --git a/metadata.py b/metadata.py index 9c7f603c1..a933f4ada 100644 --- a/metadata.py +++ b/metadata.py @@ -1,10 +1,10 @@ -__filename__ = "metadata.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="metadata.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import json @@ -18,7 +18,7 @@ def metaDataNodeInfo(baseDir: str,registration: bool,version: str) -> {}: activeAccounts=noOfAccounts(baseDir) activeAccountsMonthly=noOfActiveAccountsMonthly(baseDir,1) activeAccountsHalfYear=noOfActiveAccountsMonthly(baseDir,6) - nodeinfo = { + nodeinfo={ 'openRegistrations': registration, 'protocols': ['activitypub'], 'software': { @@ -59,27 +59,28 @@ def metaDataInstance(instanceTitle: str, \ if adminActor['type']!='Person': isBot=True - instance = { + instance={ 'approval_required': False, - 'contact_account': {'acct': adminActor['preferredUsername'], - 'avatar': adminActor['icon']['url'], - 'avatar_static': adminActor['icon']['url'], - 'bot': isBot, - 'created_at': '2019-07-01T10:30:00Z', - 'display_name': adminActor['name'], - 'emojis': [], - 'fields': [], - 'followers_count': 1, - 'following_count': 1, - 'header': adminActor['image']['url'], - 'header_static': adminActor['image']['url'], - 'id': '1', - 'last_status_at': '2019-07-01T10:30:00Z', - 'locked': adminActor['manuallyApprovesFollowers'], - 'note': '

Admin of '+domain+'

', - 'statuses_count': 1, - 'url': httpPrefix+'://'+domainFull+'/@'+adminActor['preferredUsername'], - 'username': adminActor['preferredUsername'] + 'contact_account': { + 'acct': adminActor['preferredUsername'], + 'avatar': adminActor['icon']['url'], + 'avatar_static': adminActor['icon']['url'], + 'bot': isBot, + 'created_at': '2019-07-01T10:30:00Z', + 'display_name': adminActor['name'], + 'emojis': [], + 'fields': [], + 'followers_count': 1, + 'following_count': 1, + 'header': adminActor['image']['url'], + 'header_static': adminActor['image']['url'], + 'id': '1', + 'last_status_at': '2019-07-01T10:30:00Z', + 'locked': adminActor['manuallyApprovesFollowers'], + 'note': '

Admin of '+domain+'

', + 'statuses_count': 1, + 'url': httpPrefix+'://'+domainFull+'/@'+adminActor['preferredUsername'], + 'username': adminActor['preferredUsername'] }, 'description': instanceDescription, 'email': 'admin@'+domain, diff --git a/migrate.py b/migrate.py index 63bf666bb..9d561c30d 100644 --- a/migrate.py +++ b/migrate.py @@ -1,10 +1,10 @@ -__filename__ = "migrate.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="migrate.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os diff --git a/outbox.py b/outbox.py index 6878b35b0..91e24bcf8 100644 --- a/outbox.py +++ b/outbox.py @@ -1,10 +1,10 @@ -__filename__ = "outbox.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="outbox.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import json diff --git a/person.py b/person.py index 977bd1ecd..2876cb3c9 100644 --- a/person.py +++ b/person.py @@ -1,10 +1,10 @@ -__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 @@ -42,9 +42,9 @@ 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") + 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, \ @@ -100,10 +100,13 @@ def setProfileImage(baseDir: str,httpPrefix :str,nickname: str,domain: str, \ personJson=loadJson(personFilename) if personJson: personJson[iconFilenameBase]['mediaType']=mediaType - personJson[iconFilenameBase]['url']=httpPrefix+'://'+fullDomain+'/users/'+nickname+'/'+iconFilename + 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) return True @@ -180,61 +183,66 @@ def createPersonBase(baseDir: str,nickname: str,domain: str,port: int, \ 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'}], - 'attachment': [], - 'alsoKnownAs': [], - 'discoverable': False, - 'endpoints': { - 'id': personId+'/endpoints', - 'sharedInbox': httpPrefix+'://'+domain+'/inbox', - }, - 'capabilityAcquisitionEndpoint': httpPrefix+'://'+domain+'/caps/new', - 'followers': personId+'/followers', - 'following': personId+'/following', - 'shares': personId+'/shares', - 'orgSchema': None, - 'skills': {}, - 'roles': {}, - 'availability': None, - 'icon': {'mediaType': 'image/png', - 'type': 'Image', - 'url': personId+'/avatar'+str(randint(10000000000000,99999999999999))+'.png'}, - 'id': personId, - 'image': {'mediaType': 'image/png', - 'type': 'Image', - 'url': personId+'/image'+str(randint(10000000000000,99999999999999))+'.png'}, - 'inbox': inboxStr, - 'manuallyApprovesFollowers': approveFollowers, - 'name': personName, - 'outbox': personId+'/outbox', - 'preferredUsername': personName, - 'summary': '', - 'publicKey': { - 'id': personId+'#main-key', - 'owner': personId, - 'publicKeyPem': publicKeyPem - }, - 'tag': [], - 'type': personType, - 'url': personUrl, - 'nomadicLocations': [{ - 'id': personId, - 'type': 'nomadicLocation', - 'locationAddress':'acct:'+nickname+'@'+domain, - 'locationPrimary':True, - 'locationDeleted':False - }] + 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'}], + 'attachment': [], + 'alsoKnownAs': [], + 'discoverable': False, + 'endpoints': { + 'id': personId+'/endpoints', + 'sharedInbox': httpPrefix+'://'+domain+'/inbox', + }, + 'capabilityAcquisitionEndpoint': httpPrefix+'://'+domain+'/caps/new', + 'followers': personId+'/followers', + 'following': personId+'/following', + 'shares': personId+'/shares', + 'orgSchema': None, + 'skills': {}, + 'roles': {}, + 'availability': None, + 'icon': { + 'mediaType': 'image/png', + 'type': 'Image', + 'url': personId+'/avatar'+str(randint(10000000000000,99999999999999))+'.png' + }, + 'id': personId, + 'image': { + 'mediaType': 'image/png', + 'type': 'Image', + 'url': personId+'/image'+str(randint(10000000000000,99999999999999))+'.png' + }, + 'inbox': inboxStr, + 'manuallyApprovesFollowers': approveFollowers, + 'name': personName, + 'outbox': personId+'/outbox', + 'preferredUsername': personName, + 'summary': '', + 'publicKey': { + 'id': personId+'#main-key', + 'owner': personId, + 'publicKeyPem': publicKeyPem + }, + 'tag': [], + 'type': personType, + 'url': personUrl, + 'nomadicLocations': [{ + 'id': personId, + 'type': 'nomadicLocation', + 'locationAddress':'acct:'+nickname+'@'+domain, + 'locationPrimary':True, + 'locationDeleted':False + }] } if nickname=='inbox': @@ -344,7 +352,7 @@ def createPerson(baseDir: str,nickname: str,domain: str,port: int, \ if registrationsRemaining<=0: return None,None,None,None - privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint = \ + 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') @@ -621,7 +629,7 @@ def isSuspended(baseDir: str,nickname: str) -> bool: suspendedFilename=baseDir+'/accounts/suspended.txt' if os.path.isfile(suspendedFilename): with open(suspendedFilename, "r") as f: - lines = f.readlines() + lines=f.readlines() suspendedFile=open(suspendedFilename,"w+") for suspended in lines: if suspended.strip('\n')==nickname: @@ -634,7 +642,7 @@ def unsuspendAccount(baseDir: str,nickname: str) -> None: suspendedFilename=baseDir+'/accounts/suspended.txt' if os.path.isfile(suspendedFilename): with open(suspendedFilename, "r") as f: - lines = f.readlines() + lines=f.readlines() suspendedFile=open(suspendedFilename,"w+") for suspended in lines: if suspended.strip('\n')!=nickname: @@ -653,7 +661,7 @@ def suspendAccount(baseDir: str,nickname: str,domain: str) -> None: 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: return @@ -668,7 +676,7 @@ def suspendAccount(baseDir: str,nickname: str,domain: str) -> None: 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: return @@ -703,7 +711,7 @@ def canRemovePost(baseDir: str,nickname: str,domain: str,port: int,postId: str) 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: return False @@ -720,10 +728,10 @@ def removeTagsForNickname(baseDir: str,nickname: str,domain: str,port: int) -> N if ':' not in domain: domainFull=domain+':'+str(port) matchStr=domainFull+'/users/'+nickname+'/' - directory = os.fsencode(baseDir+'/tags/') + directory=os.fsencode(baseDir+'/tags/') for f in os.scandir(directory): f=f.name - filename = os.fsdecode(f) + filename=os.fsdecode(f) if not filename.endswith(".txt"): continue tagFilename=os.path.join(directory,filename) @@ -732,7 +740,7 @@ def removeTagsForNickname(baseDir: str,nickname: str,domain: str,port: int) -> N if matchStr not in open(tagFilename).read(): continue with open(tagFilename, "r") as f: - lines = f.readlines() + lines=f.readlines() tagFile=open(tagFilename,"w+") if tagFile: for tagline in lines: @@ -752,7 +760,7 @@ def removeAccount(baseDir: str,nickname: str,domain: str,port: int) -> bool: 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: return False diff --git a/pgp.py b/pgp.py index 62679319e..88e6587d8 100644 --- a/pgp.py +++ b/pgp.py @@ -1,10 +1,10 @@ -__filename__ = "pgp.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="pgp.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json diff --git a/posts.py b/posts.py index e0b74d6db..f761d441a 100644 --- a/posts.py +++ b/posts.py @@ -1,10 +1,10 @@ -__filename__ = "posts.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="posts.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import requests import json @@ -68,7 +68,7 @@ def isModerator(baseDir: str,nickname: str) -> bool: return False with open(moderatorsFile, "r") as f: - lines = f.readlines() + lines=f.readlines() if len(lines)==0: if getConfigParam(baseDir,'admin')==nickname: return True @@ -116,7 +116,7 @@ def getPersonKey(nickname: str,domain: str,baseDir: str,keyType='public', \ return keyPem def cleanHtml(rawHtml: str) -> str: - #text = BeautifulSoup(rawHtml, 'html.parser').get_text() + #text=BeautifulSoup(rawHtml, 'html.parser').get_text() text=rawHtml return html.unescape(text) @@ -134,8 +134,8 @@ def getUserUrl(wfRequest: {}) -> str: def parseUserFeed(session,feedUrl: str,asHeader: {}, \ projectVersion: str,httpPrefix: str,domain: str) -> None: - feedJson = getJson(session,feedUrl,asHeader,None, \ - projectVersion,httpPrefix,domain) + feedJson=getJson(session,feedUrl,asHeader,None, \ + projectVersion,httpPrefix,domain) if not feedJson: return @@ -143,11 +143,11 @@ def parseUserFeed(session,feedUrl: str,asHeader: {}, \ for item in feedJson['orderedItems']: yield item - nextUrl = None + nextUrl=None if 'first' in feedJson: - nextUrl = feedJson['first'] + nextUrl=feedJson['first'] elif 'next' in feedJson: - nextUrl = feedJson['next'] + nextUrl=feedJson['next'] if nextUrl: if isinstance(nextUrl, str): @@ -165,29 +165,37 @@ def getPersonBox(baseDir: str,session,wfRequest: {},personCache: {}, \ projectVersion: str,httpPrefix: str, \ nickname: str,domain: str, \ boxName='inbox') -> (str,str,str,str,str,str,str,str): - asHeader = {'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"'} + asHeader={ + 'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"' + } if not wfRequest.get('errors'): - personUrl = getUserUrl(wfRequest) + personUrl=getUserUrl(wfRequest) else: if nickname=='dev': # try single user instance print('getPersonBox: Trying single user instance with ld+json') - personUrl = httpPrefix+'://'+domain - asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} + personUrl=httpPrefix+'://'+domain + asHeader={ + 'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } else: - personUrl = httpPrefix+'://'+domain+'/users/'+nickname + personUrl=httpPrefix+'://'+domain+'/users/'+nickname if not personUrl: return None,None,None,None,None,None,None,None - personJson = getPersonFromCache(baseDir,personUrl,personCache) + personJson=getPersonFromCache(baseDir,personUrl,personCache) if not personJson: if '/channel/' in personUrl: - asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} - personJson = getJson(session,personUrl,asHeader,None, \ - projectVersion,httpPrefix,domain) + asHeader={ + 'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } + personJson=getJson(session,personUrl,asHeader,None, \ + projectVersion,httpPrefix,domain) if not personJson: - asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} - personJson = getJson(session,personUrl,asHeader,None, \ - projectVersion,httpPrefix,domain) + asHeader={ + 'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } + personJson=getJson(session,personUrl,asHeader,None, \ + projectVersion,httpPrefix,domain) if not personJson: print('Unable to get actor') return None,None,None,None,None,None,None,None @@ -246,12 +254,16 @@ def getPosts(session,outboxUrl: str,maxPosts: int, \ personPosts={} if not outboxUrl: return personPosts - asHeader = {'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"'} + asHeader={ + 'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"' + } if '/outbox/' in outboxUrl: - asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} + asHeader={ + 'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } if raw: - result = [] - i = 0 + result=[] + i=0 userFeed=parseUserFeed(session,outboxUrl,asHeader, \ projectVersion,httpPrefix,domain) for item in userFeed: @@ -262,7 +274,7 @@ def getPosts(session,outboxUrl: str,maxPosts: int, \ pprint(result) return None - i = 0 + i=0 userFeed=parseUserFeed(session,outboxUrl,asHeader, \ projectVersion,httpPrefix,domain) for item in userFeed: @@ -291,7 +303,7 @@ def getPosts(session,outboxUrl: str,maxPosts: int, \ print('No published attribute') continue #pprint(item) - published = item['object']['published'] + published=item['object']['published'] if not personPosts.get(item['id']): # check that this is a public post # #Public should appear in the "to" list @@ -304,7 +316,7 @@ def getPosts(session,outboxUrl: str,maxPosts: int, \ if not isPublic: continue - content = item['object']['content'].replace(''',"'") + content=item['object']['content'].replace(''',"'") mentions=[] emoji={} @@ -337,12 +349,12 @@ def getPosts(session,outboxUrl: str,maxPosts: int, \ print('max emojis reached') continue - summary = '' + summary='' if item['object'].get('summary'): if item['object']['summary']: - summary = item['object']['summary'] + summary=item['object']['summary'] - inReplyTo = '' + inReplyTo='' if item['object'].get('inReplyTo'): if item['object']['inReplyTo']: # No replies to non-permitted domains @@ -352,17 +364,17 @@ def getPosts(session,outboxUrl: str,maxPosts: int, \ if debug: print('url not permitted '+item['object']['inReplyTo']) continue - inReplyTo = item['object']['inReplyTo'] + inReplyTo=item['object']['inReplyTo'] - conversation = '' + conversation='' if item['object'].get('conversation'): if item['object']['conversation']: # no conversations originated in non-permitted domains if urlPermitted(item['object']['conversation'], \ federationList,"objects:read"): - conversation = item['object']['conversation'] + conversation=item['object']['conversation'] - attachment = [] + attachment=[] if item['object'].get('attachment'): if item['object']['attachment']: for attach in item['object']['attachment']: @@ -376,15 +388,15 @@ def getPosts(session,outboxUrl: str,maxPosts: int, \ if debug: print('url not permitted '+attach['url']) - sensitive = False + sensitive=False if item['object'].get('sensitive'): - sensitive = item['object']['sensitive'] + sensitive=item['object']['sensitive'] if simple: print(cleanHtml(content)+'\n') else: pprint(item) - personPosts[item['id']] = { + personPosts[item['id']]={ "sensitive": sensitive, "inreplyto": inReplyTo, "summary": summary, @@ -406,10 +418,10 @@ def deleteAllPosts(baseDir: str,nickname: str, domain: str,boxname: str) -> None """ if boxname!='inbox' and boxname!='outbox' and boxname!='tlblogs': return - boxDir = createPersonDir(nickname,domain,baseDir,boxname) + boxDir=createPersonDir(nickname,domain,baseDir,boxname) for deleteFilename in os.scandir(boxDir): deleteFilename=deleteFilename.name - filePath = os.path.join(boxDir, deleteFilename) + filePath=os.path.join(boxDir,deleteFilename) try: if os.path.isfile(filePath): os.unlink(filePath) @@ -431,7 +443,7 @@ def savePostToBox(baseDir: str,httpPrefix: str,postId: str, \ domain=domain.split(':')[0] if not postId: - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() postId= \ httpPrefix+'://'+originalDomain+'/users/'+nickname+ \ '/statuses/'+statusNumber @@ -441,7 +453,7 @@ def savePostToBox(baseDir: str,httpPrefix: str,postId: str, \ postJsonObject['object']['id']=postId postJsonObject['object']['atomUri']=postId - boxDir = createPersonDir(nickname,domain,baseDir,boxname) + boxDir=createPersonDir(nickname,domain,baseDir,boxname) filename=boxDir+'/'+postId.replace('/','#')+'.json' saveJson(postJsonObject,filename) return filename @@ -472,7 +484,7 @@ def updateHashtagsIndex(baseDir: str,tag: {},newPostId: str) -> None: if tagline not in open(tagsFilename).read(): try: with open(tagsFilename, 'r+') as tagsFile: - content = tagsFile.read() + content=tagsFile.read() tagsFile.seek(0, 0) tagsFile.write(tagline+content) except Exception as e: @@ -491,7 +503,7 @@ def addSchedulePost(baseDir: str,nickname: str,domain: str, \ if indexStr not in open(scheduleIndexFilename).read(): try: with open(scheduleIndexFilename, 'r+') as scheduleFile: - content = scheduleFile.read() + content=scheduleFile.read() scheduleFile.seek(0, 0) scheduleFile.write(indexStr+'\n'+content) print('DEBUG: scheduled post added to index') @@ -551,7 +563,7 @@ def createPostBase(baseDir: str,nickname: str,domain: str,port: int, \ if tag['name'] not in content: del hashtagsDict[tagName] - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() postTo='https://www.w3.org/ns/activitystreams#Public' postCC=httpPrefix+'://'+domain+'/users/'+nickname+'/followers' if followersOnly: @@ -659,7 +671,7 @@ def createPostBase(baseDir: str,nickname: str,domain: str,port: int, \ if oc: if oc.get('id'): capabilityIdList=[oc['id']] - newPost = { + newPost={ "@context": postContext, 'id': newPostId+'/activity', 'capability': capabilityIdList, @@ -704,7 +716,7 @@ def createPostBase(baseDir: str,nickname: str,domain: str,port: int, \ newPost['object'],attachImageFilename, \ mediaType,imageDescription,useBlurhash) else: - newPost = { + newPost={ "@context": postContext, 'id': newPostId, 'type': 'Note', @@ -788,16 +800,16 @@ def outboxMessageCreateWrap(httpPrefix: str, \ if port!=80 and port!=443: if ':' not in domain: domain=domain+':'+str(port) - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() if messageJson.get('published'): - published = messageJson['published'] + published=messageJson['published'] newPostId=httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber cc=[] if messageJson.get('cc'): cc=messageJson['cc'] # TODO capabilityUrl=[] - newPost = { + newPost={ "@context": "https://www.w3.org/ns/activitystreams", 'id': newPostId+'/activity', 'capability': capabilityUrl, @@ -1207,7 +1219,7 @@ def threadSendPost(session,postJsonStr: str,federationList: [],\ postResult=None unauthorized=False try: - postResult,unauthorized = \ + postResult,unauthorized= \ postJsonString(session,postJsonStr,federationList, \ inboxUrl,signatureHeaderJson, \ "inbox:write",debug) @@ -1272,8 +1284,8 @@ def sendPost(projectVersion: str, \ handle=httpPrefix+'://'+toDomain+'/@'+toNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - domain,projectVersion) + wfRequest=webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + domain,projectVersion) if not wfRequest: return 1 @@ -1285,7 +1297,7 @@ def sendPost(projectVersion: str, \ postToBox='tlblogs' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,toPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,toPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix, \ nickname,domain,postToBox) @@ -1305,7 +1317,7 @@ def sendPost(projectVersion: str, \ return 5 # sharedInbox and capabilities are optional - postJsonObject = \ + postJsonObject= \ createPostBase(baseDir,nickname,domain,port, \ toPersonId,cc,httpPrefix,content, \ followersOnly,saveToFile,clientToServer, \ @@ -1328,7 +1340,7 @@ def sendPost(projectVersion: str, \ postJsonStr=json.dumps(postJsonObject) # construct the http header, including the message body digest - signatureHeaderJson = \ + signatureHeaderJson= \ createSignedHeader(privateKeyPem,nickname,domain,port, \ toDomain,toPort, \ postPath,httpPrefix,withDigest,postJsonStr) @@ -1339,7 +1351,7 @@ def sendPost(projectVersion: str, \ sendThreads[0].kill() sendThreads.pop(0) print('WARN: thread killed') - thr = \ + thr= \ threadWithTrace(target=threadSendPost, \ args=(session, \ postJsonStr, \ @@ -1378,7 +1390,7 @@ def sendPostViaServer(projectVersion: str, \ handle=httpPrefix+'://'+fromDomain+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = \ + wfRequest= \ webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ fromDomain,projectVersion) if not wfRequest: @@ -1391,7 +1403,7 @@ def sendPostViaServer(projectVersion: str, \ postToBox='tlblogs' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,fromNickname, \ fromDomain,postToBox) @@ -1431,7 +1443,7 @@ def sendPostViaServer(projectVersion: str, \ toDomainFull=toDomain+':'+str(toPort) toPersonId=httpPrefix+'://'+toDomainFull+'/users/'+toNickname - postJsonObject = \ + postJsonObject= \ createPostBase(baseDir, \ fromNickname,fromDomain,fromPort, \ toPersonId,cc,httpPrefix,content, \ @@ -1444,9 +1456,11 @@ def sendPostViaServer(projectVersion: str, \ authHeader=createBasicAuthHeader(fromNickname,password) if attachImageFilename: - headers = {'host': fromDomain, \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Authorization': authHeader + } + postResult= \ postImage(session,attachImageFilename,[], \ inboxUrl,headers,"inbox:write") #if not postResult: @@ -1454,10 +1468,12 @@ def sendPostViaServer(projectVersion: str, \ # print('DEBUG: Failed to upload image') # return 9 - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJsonString(session,json.dumps(postJsonObject),[], \ inboxUrl,headers,"inbox:write",debug) #if not postResult: @@ -1578,7 +1594,7 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str, \ postToBox='outbox' # get the actor inbox/outbox/capabilities for the To handle - inboxUrl,pubKeyId,pubKey,toPersonId,sharedInboxUrl,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,toPersonId,sharedInboxUrl,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,nickname,domain,postToBox) @@ -1633,7 +1649,7 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str, \ postJsonStr=json.dumps(postJsonObject) # construct the http header, including the message body digest - signatureHeaderJson = \ + signatureHeaderJson= \ createSignedHeader(privateKeyPem,nickname,domain,port, \ toDomain,toPort, \ postPath,httpPrefix,withDigest,postJsonStr) @@ -1648,14 +1664,15 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str, \ if debug: print('DEBUG: starting thread to send post') pprint(postJsonObject) - thr = threadWithTrace(target=threadSendPost, \ - args=(session, \ - postJsonStr, \ - federationList, \ - inboxUrl,baseDir, \ - signatureHeaderJson.copy(), \ - postLog, - debug),daemon=True) + thr= \ + threadWithTrace(target=threadSendPost, \ + args=(session, \ + postJsonStr, \ + federationList, \ + inboxUrl,baseDir, \ + signatureHeaderJson.copy(), \ + postLog, + debug),daemon=True) sendThreads.append(thr) #thr.start() return 0 @@ -2030,7 +2047,7 @@ def createModeration(baseDir: str,nickname: str,domain: str,port: int, \ httpPrefix: str, \ itemsPerPage: int,headerOnly: bool, \ ocapAlways: bool,pageNumber=None) -> {}: - boxDir = createPersonDir(nickname,domain,baseDir,'inbox') + boxDir=createPersonDir(nickname,domain,baseDir,'inbox') boxname='moderation' if port: @@ -2042,24 +2059,28 @@ def createModeration(baseDir: str,nickname: str,domain: str,port: int, \ pageNumber=1 pageStr='?page='+str(pageNumber) - boxHeader = {'@context': 'https://www.w3.org/ns/activitystreams', - 'first': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+'?page=true', - 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname, - 'last': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+'?page=true', - 'totalItems': 0, - 'type': 'OrderedCollection'} - boxItems = {'@context': 'https://www.w3.org/ns/activitystreams', - 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+pageStr, - 'orderedItems': [ - ], - 'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname, - 'type': 'OrderedCollectionPage'} + boxHeader={ + '@context': 'https://www.w3.org/ns/activitystreams', + 'first': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+'?page=true', + 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname, + 'last': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+'?page=true', + 'totalItems': 0, + 'type': 'OrderedCollection' + } + boxItems={ + '@context': 'https://www.w3.org/ns/activitystreams', + 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+pageStr, + 'orderedItems': [ + ], + 'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname, + 'type': 'OrderedCollectionPage' + } if isModerator(baseDir,nickname): moderationIndexFile=baseDir+'/accounts/moderation.txt' if os.path.isfile(moderationIndexFile): with open(moderationIndexFile, "r") as f: - lines = f.readlines() + lines=f.readlines() boxHeader['totalItems']=len(lines) if headerOnly: return boxHeader @@ -2237,7 +2258,7 @@ def createSharedInboxIndex(baseDir: str,sharedBoxDir: str, \ # is the actor followed by this account? if not followingHandles: with open(followingFilename, 'r') as followingFile: - followingHandles = followingFile.read() + followingHandles=followingFile.read() if actorNickname+'@'+actorDomain not in followingHandles: continue @@ -2304,7 +2325,7 @@ def addPostToTimeline(filePath: str,boxname: str, \ """ Reads a post from file and decides whether it is valid """ with open(filePath, 'r') as postFile: - postStr = postFile.read() + postStr=postFile.read() return addPostStringToTimeline(postStr,boxname,postsInBox,boxActor) return False @@ -2327,17 +2348,17 @@ def createBoxIndexed(recentPostsCache: {}, \ if boxname!='dm' and boxname!='tlreplies' and \ boxname!='tlmedia' and boxname!='tlblogs' and \ boxname!='tlbookmarks': - boxDir = createPersonDir(nickname,domain,baseDir,boxname) + boxDir=createPersonDir(nickname,domain,baseDir,boxname) else: # extract DMs or replies or media from the inbox - boxDir = createPersonDir(nickname,domain,baseDir,'inbox') + boxDir=createPersonDir(nickname,domain,baseDir,'inbox') announceCacheDir=baseDir+'/cache/announce/'+nickname sharedBoxDir=None if boxname=='inbox' or boxname=='tlreplies' or \ boxname=='tlmedia' or boxname=='tlblogs': - sharedBoxDir = createPersonDir('inbox',domain,baseDir,boxname) + sharedBoxDir=createPersonDir('inbox',domain,baseDir,boxname) # bookmarks timeline is like the inbox but has its own separate index indexBoxName=boxname @@ -2365,18 +2386,22 @@ def createBoxIndexed(recentPostsCache: {}, \ pageStr='?page='+str(pageNumber) except: pass - boxHeader = {'@context': 'https://www.w3.org/ns/activitystreams', - 'first': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+'?page=true', - 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname, - 'last': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+'?page=true', - 'totalItems': 0, - 'type': 'OrderedCollection'} - boxItems = {'@context': 'https://www.w3.org/ns/activitystreams', - 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+pageStr, - 'orderedItems': [ - ], - 'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname, - 'type': 'OrderedCollectionPage'} + boxHeader={ + '@context': 'https://www.w3.org/ns/activitystreams', + 'first': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+'?page=true', + 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname, + 'last': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+'?page=true', + 'totalItems': 0, + 'type': 'OrderedCollection' + } + boxItems={ + '@context': 'https://www.w3.org/ns/activitystreams', + 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname+pageStr, + 'orderedItems': [ + ], + 'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname, + 'type': 'OrderedCollectionPage' + } postsInBox=[] @@ -2528,7 +2553,7 @@ def archivePostsForPerson(httpPrefix: str,nickname: str,domain: str,baseDir: str if archiveDir: if not os.path.isdir(archiveDir): os.mkdir(archiveDir) - boxDir = createPersonDir(nickname,domain,baseDir,boxname) + boxDir=createPersonDir(nickname,domain,baseDir,boxname) postsInBox=os.scandir(boxDir) noOfPosts=0 for f in postsInBox: @@ -2624,7 +2649,7 @@ def getPublicPostsOfPerson(baseDir: str,nickname: str,domain: str, \ debug: bool,projectVersion: str) -> None: """ This is really just for test purposes """ - session = createSession(useTor) + session=createSession(useTor) personCache={} cachedWebfingers={} federationList=[] @@ -2635,7 +2660,7 @@ def getPublicPostsOfPerson(baseDir: str,nickname: str,domain: str, \ if ':' not in domain: domainFull=domain+':'+str(port) handle=httpPrefix+"://"+domainFull+"/@"+nickname - wfRequest = \ + wfRequest= \ webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ domain,projectVersion) if not wfRequest: @@ -2644,12 +2669,12 @@ def getPublicPostsOfPerson(baseDir: str,nickname: str,domain: str, \ personUrl,pubKeyId,pubKey,personId,shaedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,nickname,domain,'outbox') - wfResult = json.dumps(wfRequest, indent=2, sort_keys=False) + wfResult=json.dumps(wfRequest,indent=2,sort_keys=False) maxMentions=10 maxEmoji=10 maxAttachments=5 - userPosts = \ + userPosts= \ getPosts(session,personUrl,30,maxMentions,maxEmoji, \ maxAttachments,federationList, \ personCache,raw,simple,debug, \ diff --git a/question.py b/question.py index 3b2eb0948..57eb2d3e3 100644 --- a/question.py +++ b/question.py @@ -1,10 +1,10 @@ -__filename__ = "question.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="question.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os from utils import locatePost @@ -76,7 +76,7 @@ def questionUpdateVotes(baseDir: str,nickname: str,domain: str,replyJson: {}) -> else: # change an entry in the voters file with open(votersFilename, "r") as votersFile: - lines = votersFile.readlines() + lines=votersFile.readlines() newlines=[] saveVotersFile=False for voteLine in lines: @@ -101,7 +101,7 @@ def questionUpdateVotes(baseDir: str,nickname: str,domain: str,replyJson: {}) -> continue totalItems=0 with open(votersFilename, "r") as votersFile: - lines = votersFile.readlines() + lines=votersFile.readlines() for voteLine in lines: if voteLine.endswith(votersFileSeparator+possibleAnswer['name']+'\n'): totalItems+=1 diff --git a/roles.py b/roles.py index 36228aa4d..01c0c7848 100644 --- a/roles.py +++ b/roles.py @@ -1,10 +1,10 @@ -__filename__ = "roles.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="roles.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import os @@ -23,10 +23,10 @@ def clearModeratorStatus(baseDir: str) -> None: This could be slow if there are many users, but only happens rarely when moderators are appointed or removed """ - directory = os.fsencode(baseDir+'/accounts/') + directory=os.fsencode(baseDir+'/accounts/') for f in os.scandir(directory): f=f.name - filename = os.fsdecode(f) + filename=os.fsdecode(f) if filename.endswith(".json") and '@' in filename: filename=os.path.join(baseDir+'/accounts/', filename) if '"moderator"' in open(filename).read(): @@ -46,7 +46,7 @@ def addModerator(baseDir: str,nickname: str,domain: str) -> None: if os.path.isfile(moderatorsFile): # is this nickname already in the file? with open(moderatorsFile, "r") as f: - lines = f.readlines() + lines=f.readlines() for moderator in lines: moderator=moderator.strip('\n') if line==nickname: @@ -70,7 +70,7 @@ def removeModerator(baseDir: str,nickname: str): if not os.path.isfile(moderatorsFile): return with open(moderatorsFile, "r") as f: - lines = f.readlines() + lines=f.readlines() with open(moderatorsFile, "w") as f: for moderator in lines: moderator=moderator.strip('\n') @@ -229,14 +229,17 @@ def sendRoleViaServer(baseDir: str,session, \ if ':' not in delegatorDomain: delegatorDomainFull=delegatorDomain+':'+str(fromPort) - toUrl = httpPrefix+'://'+delegatorDomainFull+'/users/'+nickname - ccUrl = httpPrefix+'://'+delegatorDomainFull+'/users/'+delegatorNickname+'/followers' + toUrl= \ + httpPrefix+'://'+delegatorDomainFull+'/users/'+nickname + ccUrl= \ + httpPrefix+'://'+delegatorDomainFull+'/users/'+ \ + delegatorNickname+'/followers' if role: roleStr=project.lower()+';'+role.lower() else: roleStr=project.lower()+';' - newRoleJson = { + newRoleJson={ 'type': 'Delegate', 'actor': httpPrefix+'://'+delegatorDomainFull+'/users/'+delegatorNickname, 'object': { @@ -253,8 +256,8 @@ def sendRoleViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+delegatorDomainFull+'/@'+delegatorNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - delegatorDomain,projectVersion) + wfRequest=webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + delegatorDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -263,7 +266,7 @@ def sendRoleViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix, \ delegatorNickname,delegatorDomain,postToBox) @@ -279,10 +282,12 @@ def sendRoleViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(delegatorNickname,password) - headers = {'host': delegatorDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': delegatorDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newRoleJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: diff --git a/schedule.py b/schedule.py index 0345358b7..895e97523 100644 --- a/schedule.py +++ b/schedule.py @@ -1,10 +1,10 @@ -__filename__ = "schedule.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="schedule.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import time @@ -70,7 +70,7 @@ def updatePostSchedule(baseDir: str,handle: str,httpd,maxScheduledPosts: int) -> # set the published time # If this is not recent then http checks on the receiving side # will reject it - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() if postJsonObject.get('published'): postJsonObject['published']=published if postJsonObject.get('object'): diff --git a/session.py b/session.py index eed603926..f6398737e 100644 --- a/session.py +++ b/session.py @@ -1,10 +1,10 @@ -__filename__ = "session.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="session.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import sys @@ -15,11 +15,11 @@ import json baseDirectory=None def createSession(onionRoute: bool): - session = requests.session() + session=requests.session() if onionRoute: - session.proxies = {} - session.proxies['http'] = 'socks5h://localhost:9050' - session.proxies['https'] = 'socks5h://localhost:9050' + session.proxies={} + session.proxies['http']='socks5h://localhost:9050' + session.proxies['https']='socks5h://localhost:9050' return session def getJson(session,url: str,headers: {},params: {}, \ @@ -94,11 +94,12 @@ def postJsonString(session,postJsonStr: str, \ print('postJson: '+inboxUrl+' not permitted by capabilities') return None,None - postResult = session.post(url = inboxUrl, data = postJsonStr, headers=headers) + postResult= \ + session.post(url=inboxUrl,data=postJsonStr,headers=headers) if postResult.status_code<200 or postResult.status_code>202: #if postResult.status_code==400: # headers['content-type']='application/ld+json' - # postResult = session.post(url = inboxUrl, data = postJsonStr, headers=headers) + # postResult=session.post(url=inboxUrl,data=postJsonStr,headers=headers) # if not (postResult.status_code<200 or postResult.status_code>202): # return True if postResult.status_code>=400 and postResult.status_code<=405 and \ @@ -140,8 +141,8 @@ def postImage(session,attachImageFilename: str,federationList: [], \ headers['Content-type']=contentType with open(attachImageFilename, 'rb') as avFile: - mediaBinary = avFile.read() - postResult = session.post(url=inboxUrl, data=mediaBinary, headers=headers) + mediaBinary=avFile.read() + postResult=session.post(url=inboxUrl,data=mediaBinary,headers=headers) if postResult: return postResult.text return None diff --git a/shares.py b/shares.py index 350a2d54f..d85ad006f 100644 --- a/shares.py +++ b/shares.py @@ -1,10 +1,10 @@ -__filename__ = "shares.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="shares.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import os @@ -142,7 +142,7 @@ def addShare(baseDir: str, \ os.remove(imageFilename) imageUrl=httpPrefix+'://'+domainFull+'/sharefiles/'+nickname+'/'+itemID+'.gif' - sharesJson[itemID] = { + sharesJson[itemID]={ "displayName": displayName, "summary": summary, "imageUrl": imageUrl, @@ -261,25 +261,27 @@ def getSharesFeedForPerson(baseDir: str, \ sharesJson=loadJson(sharesFilename) if sharesJson: noOfShares=len(sharesJson.items()) - shares = { + shares={ '@context': 'https://www.w3.org/ns/activitystreams', 'first': httpPrefix+'://'+domain+'/users/'+nickname+'/shares?page=1', 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/shares', 'totalItems': str(noOfShares), - 'type': 'OrderedCollection'} + 'type': 'OrderedCollection' + } return shares if not pageNumber: pageNumber=1 nextPageNumber=int(pageNumber+1) - shares = { + shares={ '@context': 'https://www.w3.org/ns/activitystreams', 'id': httpPrefix+'://'+domain+'/users/'+nickname+'/shares?page='+str(pageNumber), 'orderedItems': [], 'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/shares', 'totalItems': 0, - 'type': 'OrderedCollectionPage'} + 'type': 'OrderedCollectionPage' + } if not os.path.isfile(sharesFilename): print("test5") @@ -332,10 +334,10 @@ def sendShareViaServer(baseDir,session, \ if ':' not in fromDomain: fromDomainFull=fromDomain+':'+str(fromPort) - toUrl = 'https://www.w3.org/ns/activitystreams#Public' - ccUrl = httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers' + toUrl='https://www.w3.org/ns/activitystreams#Public' + ccUrl=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers' - newShareJson = { + newShareJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Add', 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, @@ -358,8 +360,8 @@ def sendShareViaServer(baseDir,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - fromDomain,projectVersion) + wfRequest=webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + fromDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -368,7 +370,7 @@ def sendShareViaServer(baseDir,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix, \ fromNickname,fromDomain,postToBox) @@ -385,15 +387,19 @@ def sendShareViaServer(baseDir,session, \ authHeader=createBasicAuthHeader(fromNickname,password) if imageFilename: - headers = {'host': fromDomain, \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Authorization': authHeader + } + postResult= \ postImage(session,imageFilename,[],inboxUrl.replace('/'+postToBox,'/shares'),headers,"inbox:write") - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newShareJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: @@ -424,10 +430,10 @@ def sendUndoShareViaServer(baseDir: str,session, \ if ':' not in fromDomain: fromDomainFull=fromDomain+':'+str(fromPort) - toUrl = 'https://www.w3.org/ns/activitystreams#Public' - ccUrl = httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers' + toUrl='https://www.w3.org/ns/activitystreams#Public' + ccUrl=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers' - undoShareJson = { + undoShareJson={ "@context": "https://www.w3.org/ns/activitystreams", 'type': 'Remove', 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, @@ -445,8 +451,8 @@ def sendUndoShareViaServer(baseDir: str,session, \ handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - fromDomain,projectVersion) + wfRequest=webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + fromDomain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -455,7 +461,7 @@ def sendUndoShareViaServer(baseDir: str,session, \ postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix, \ fromNickname,fromDomain,postToBox) @@ -471,10 +477,12 @@ def sendUndoShareViaServer(baseDir: str,session, \ authHeader=createBasicAuthHeader(fromNickname,password) - headers = {'host': fromDomain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': fromDomain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,undoShareJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: diff --git a/skills.py b/skills.py index 6a707b5c7..43b5e992c 100644 --- a/skills.py +++ b/skills.py @@ -1,10 +1,10 @@ -__filename__ = "skills.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="skills.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import os @@ -109,14 +109,14 @@ def sendSkillViaServer(baseDir: str,session,nickname: str,password: str, if ':' not in domain: domainFull=domain+':'+str(port) - toUrl = httpPrefix+'://'+domainFull+'/users/'+nickname - ccUrl = httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers' + toUrl=httpPrefix+'://'+domainFull+'/users/'+nickname + ccUrl=httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers' if skillLevelPercent: skillStr=skill+';'+str(skillLevelPercent) else: skillStr=skill+';0' - newSkillJson = { + newSkillJson={ 'type': 'Skill', 'actor': httpPrefix+'://'+domainFull+'/users/'+nickname, 'object': '"'+skillStr+'"', @@ -127,8 +127,8 @@ def sendSkillViaServer(baseDir: str,session,nickname: str,password: str, handle=httpPrefix+'://'+domainFull+'/@'+nickname # lookup the inbox for the To handle - wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ - domain,projectVersion) + wfRequest=webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ + domain,projectVersion) if not wfRequest: if debug: print('DEBUG: announce webfinger failed for '+handle) @@ -137,7 +137,7 @@ def sendSkillViaServer(baseDir: str,session,nickname: str,password: str, postToBox='outbox' # get the actor inbox for the To handle - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,nickname,domain,postToBox) @@ -152,10 +152,12 @@ def sendSkillViaServer(baseDir: str,session,nickname: str,password: str, authHeader=createBasicAuthHeader(Nickname,password) - headers = {'host': domain, \ - 'Content-type': 'application/json', \ - 'Authorization': authHeader} - postResult = \ + headers={ + 'host': domain, \ + 'Content-type': 'application/json', \ + 'Authorization': authHeader + } + postResult= \ postJson(session,newSkillJson,[],inboxUrl,headers,"inbox:write") #if not postResult: # if debug: diff --git a/ssb.py b/ssb.py index 9fbe874b9..f52339033 100644 --- a/ssb.py +++ b/ssb.py @@ -1,10 +1,10 @@ -__filename__ = "ssb.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="ssb.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json diff --git a/tests.py b/tests.py index 7b2d6ebcd..2bd3fb4ac 100644 --- a/tests.py +++ b/tests.py @@ -1,10 +1,10 @@ -__filename__ = "tests.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="tests.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import base64 import time @@ -77,9 +77,9 @@ from content import addHtmlTags from content import removeLongWords from theme import setCSSparam -testServerAliceRunning = False -testServerBobRunning = False -testServerEveRunning = False +testServerAliceRunning=False +testServerBobRunning=False +testServerEveRunning=False thrAlice=None thrBob=None thrEve=None @@ -103,7 +103,11 @@ def testHttpsigBase(withDigest): privateKeyPem,publicKeyPem,person,wfEndpoint= \ createPerson(path,nickname,domain,port,httpPrefix,False,password) assert privateKeyPem - messageBodyJson = {"a key": "a value", "another key": "A string","yet another key": "Another string"} + messageBodyJson={ + "a key": "a value", + "another key": "A string", + "yet another key": "Another string" + } messageBodyJsonStr=json.dumps(messageBodyJson) headersDomain=domain @@ -115,23 +119,33 @@ def testHttpsigBase(withDigest): dateStr=strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime()) boxpath='/inbox' if not withDigest: - headers = {'host': headersDomain,'date': dateStr,'content-type': 'application/json'} - signatureHeader = \ + headers={ + 'host': headersDomain, + 'date': dateStr, + 'content-type': 'application/json' + } + signatureHeader= \ signPostHeaders(dateStr,privateKeyPem, nickname, \ domain, port, \ domain, port, \ boxpath, httpPrefix, None) else: - bodyDigest = messageContentDigest(messageBodyJsonStr) + bodyDigest=messageContentDigest(messageBodyJsonStr) contentLength=len(messageBodyJsonStr) - headers = {'host': headersDomain,'date': dateStr,'digest': f'SHA-256={bodyDigest}','content-type': contentType,'content-length': str(contentLength)} - signatureHeader = \ + headers={ + 'host': headersDomain, + 'date': dateStr, + 'digest': f'SHA-256={bodyDigest}', + 'content-type': contentType, + 'content-length': str(contentLength) + } + signatureHeader= \ signPostHeaders(dateStr,privateKeyPem, nickname, \ domain, port, \ domain, port, \ boxpath, httpPrefix, messageBodyJsonStr) - headers['signature'] = signatureHeader + headers['signature']=signatureHeader assert verifyPostHeaders(httpPrefix,publicKeyPem,headers, \ boxpath,False,None, \ messageBodyJsonStr,False) @@ -149,14 +163,24 @@ def testHttpsigBase(withDigest): messageBodyJsonStr,False) == False if not withDigest: # fake domain - headers = {'host': 'bogon.domain','date': dateStr,'content-type': 'application/json'} + headers={ + 'host': 'bogon.domain', + 'date': dateStr, + 'content-type': 'application/json' + } else: # correct domain but fake message - messageBodyJsonStr = '{"a key": "a value", "another key": "Fake GNUs", "yet another key": "More Fake GNUs"}' + messageBodyJsonStr='{"a key": "a value", "another key": "Fake GNUs", "yet another key": "More Fake GNUs"}' contentLength=len(messageBodyJsonStr) - bodyDigest = messageContentDigest(messageBodyJsonStr) - headers = {'host': domain,'date': dateStr,'digest': f'SHA-256={bodyDigest}','content-type': contentType,'content-length': str(contentLength)} - headers['signature'] = signatureHeader + bodyDigest=messageContentDigest(messageBodyJsonStr) + headers={ + 'host': domain, + 'date': dateStr, + 'digest': f'SHA-256={bodyDigest}', + 'content-type': contentType, + 'content-length': str(contentLength) + } + headers['signature']=signatureHeader assert verifyPostHeaders(httpPrefix,publicKeyPem,headers, \ boxpath,True,None, \ messageBodyJsonStr,False) == False @@ -184,7 +208,8 @@ def testThreadsFunction(param: str): def testThreads(): print('testThreads') - thr = threadWithTrace(target=testThreadsFunction,args=('test',),daemon=True) + thr= \ + threadWithTrace(target=testThreadsFunction,args=('test',),daemon=True) thr.start() assert thr.isAlive()==True time.sleep(1) @@ -235,7 +260,7 @@ def createServerAlice(path: str,domain: str,port: int,bobAddress: str,federation "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", \ False, True, clientToServer,None,None,useBlurhash) global testServerAliceRunning - testServerAliceRunning = True + testServerAliceRunning=True maxMentions=10 maxEmoji=10 onionDomain=None @@ -292,7 +317,7 @@ def createServerBob(path: str,domain: str,port: int,aliceAddress: str,federation "Quantum physics is a bit of a passion of mine", \ False, True, clientToServer,None,None,useBlurhash) global testServerBobRunning - testServerBobRunning = True + testServerBobRunning=True maxMentions=10 maxEmoji=10 onionDomain=None @@ -329,7 +354,7 @@ def createServerEve(path: str,domain: str,port: int,federationList: [], \ deleteAllPosts(path,nickname,domain,'inbox') deleteAllPosts(path,nickname,domain,'outbox') global testServerEveRunning - testServerEveRunning = True + testServerEveRunning=True maxMentions=10 maxEmoji=10 onionDomain=None @@ -346,8 +371,8 @@ def testPostMessageBetweenServers(): global testServerAliceRunning global testServerBobRunning - testServerAliceRunning = False - testServerBobRunning = False + testServerAliceRunning=False + testServerBobRunning=False httpPrefix='http' useTor=False @@ -380,7 +405,7 @@ def testPostMessageBetweenServers(): time.sleep(1) thrAlice.kill() - thrAlice = \ + thrAlice= \ threadWithTrace(target=createServerAlice, \ args=(aliceDir,aliceDomain,alicePort,bobAddress, \ federationList,False,False, \ @@ -393,7 +418,7 @@ def testPostMessageBetweenServers(): time.sleep(1) thrBob.kill() - thrBob = \ + thrBob= \ threadWithTrace(target=createServerBob, \ args=(bobDir,bobDomain,bobPort,aliceAddress, \ federationList,False,False, \ @@ -413,11 +438,11 @@ def testPostMessageBetweenServers(): print('\n\n*******************************************************') print('Alice sends to Bob') os.chdir(aliceDir) - sessionAlice = createSession(useTor) + sessionAlice=createSession(useTor) inReplyTo=None inReplyToAtomUri=None subject=None - alicePostLog = [] + alicePostLog=[] followersOnly=False saveToFile=True clientToServer=False @@ -433,7 +458,7 @@ def testPostMessageBetweenServers(): outboxPath=aliceDir+'/accounts/alice@'+aliceDomain+'/outbox' assert len([name for name in os.listdir(outboxPath) if os.path.isfile(os.path.join(outboxPath, name))])==0 - sendResult = \ + sendResult= \ sendPost(__version__, \ sessionAlice,aliceDir,'alice',aliceDomain,alicePort, \ 'bob',bobDomain,bobPort,ccUrl,httpPrefix, \ @@ -486,8 +511,8 @@ def testPostMessageBetweenServers(): followPerson(aliceDir,'alice',aliceDomain,'bob', \ bobDomain+':'+str(bobPort),federationList,False) - sessionBob = createSession(useTor) - bobPostLog = [] + sessionBob=createSession(useTor) + bobPostLog=[] bobPersonCache={} bobCachedWebfingers={} statusNumber=None @@ -563,8 +588,8 @@ def testFollowBetweenServers(): global testServerAliceRunning global testServerBobRunning - testServerAliceRunning = False - testServerBobRunning = False + testServerAliceRunning=False + testServerBobRunning=False httpPrefix='http' useTor=False @@ -597,7 +622,7 @@ def testFollowBetweenServers(): time.sleep(1) thrAlice.kill() - thrAlice = \ + thrAlice= \ threadWithTrace(target=createServerAlice, \ args=(aliceDir,aliceDomain,alicePort,bobAddress, \ federationList,False,False, \ @@ -610,7 +635,7 @@ def testFollowBetweenServers(): time.sleep(1) thrBob.kill() - thrBob = \ + thrBob= \ threadWithTrace(target=createServerBob, \ args=(bobDir,bobDomain,bobPort,aliceAddress, \ federationList,False,False, \ @@ -638,11 +663,11 @@ def testFollowBetweenServers(): print('*********************************************************') print('Alice sends a follow request to Bob') os.chdir(aliceDir) - sessionAlice = createSession(useTor) + sessionAlice=createSession(useTor) inReplyTo=None inReplyToAtomUri=None subject=None - alicePostLog = [] + alicePostLog=[] followersOnly=False saveToFile=True clientToServer=False @@ -650,7 +675,7 @@ def testFollowBetweenServers(): alicePersonCache={} aliceCachedWebfingers={} alicePostLog=[] - sendResult = \ + sendResult= \ sendFollowRequest(sessionAlice,aliceDir, \ 'alice',aliceDomain,alicePort,httpPrefix, \ 'bob',bobDomain,bobPort,httpPrefix, \ @@ -671,13 +696,13 @@ def testFollowBetweenServers(): print('\n\n*********************************************************') print('Alice sends a message to Bob') - alicePostLog = [] + alicePostLog=[] alicePersonCache={} aliceCachedWebfingers={} alicePostLog=[] useBlurhash=False isArticle=False - sendResult = \ + sendResult= \ sendPost(__version__, \ sessionAlice,aliceDir,'alice',aliceDomain,alicePort, \ 'bob',bobDomain,bobPort,ccUrl, \ @@ -860,7 +885,7 @@ def testFollows(): followPerson(baseDir,nickname,domain,'batman','mesh.com',federationList,False) followPerson(baseDir,nickname,domain,'giraffe','trees.com',federationList,False) - f = open(baseDir+'/accounts/'+nickname+'@'+domain+'/following.txt', "r") + f=open(baseDir+'/accounts/'+nickname+'@'+domain+'/following.txt', "r") domainFound=False for followingDomain in f: testDomain=followingDomain.split('@')[1].replace('\n','') @@ -887,7 +912,7 @@ def testFollows(): followerOfPerson(baseDir,nickname,domain,'batman','mesh.com',federationList,False) followerOfPerson(baseDir,nickname,domain,'giraffe','trees.com',federationList,False) - f = open(baseDir+'/accounts/'+nickname+'@'+domain+'/followers.txt', "r") + f=open(baseDir+'/accounts/'+nickname+'@'+domain+'/followers.txt', "r") for followerDomain in f: testDomain=followerDomain.split('@')[1].replace('\n','') if testDomain not in federationList: @@ -949,7 +974,7 @@ def testDelegateRoles(): httpPrefix='http' project='artechoke' role='delegator' - newRoleJson = { + newRoleJson={ 'type': 'Delegate', 'actor': httpPrefix+'://'+domain+'/users/'+nickname, 'object': { @@ -970,7 +995,7 @@ def testDelegateRoles(): assert '"delegator"' in open(baseDir+'/accounts/'+nickname+'@'+domain+'.json').read() assert '"delegator"' in open(baseDir+'/accounts/'+nicknameDelegated+'@'+domain+'.json').read() - newRoleJson = { + newRoleJson={ 'type': 'Delegate', 'actor': httpPrefix+'://'+domain+'/users/'+nicknameDelegated, 'object': { @@ -1030,8 +1055,8 @@ def testClientToServer(): global testServerAliceRunning global testServerBobRunning - testServerAliceRunning = False - testServerBobRunning = False + testServerAliceRunning=False + testServerBobRunning=False httpPrefix='http' useTor=False @@ -1064,7 +1089,7 @@ def testClientToServer(): time.sleep(1) thrAlice.kill() - thrAlice = \ + thrAlice= \ threadWithTrace(target=createServerAlice, \ args=(aliceDir,aliceDomain,alicePort,bobAddress, \ federationList,False,False, \ @@ -1077,7 +1102,7 @@ def testClientToServer(): time.sleep(1) thrBob.kill() - thrBob = \ + thrBob= \ threadWithTrace(target=createServerBob, \ args=(bobDir,bobDomain,bobPort,aliceAddress, \ federationList,False,False, \ @@ -1103,7 +1128,7 @@ def testClientToServer(): print('\n\n*******************************************************') print('Alice sends to Bob via c2s') - sessionAlice = createSession(useTor) + sessionAlice=createSession(useTor) followersOnly=False attachedImageFilename=baseDir+'/img/logo.png' mediaType=getAttachmentMediaType(attachedImageFilename) @@ -1214,7 +1239,7 @@ def testClientToServer(): print('\n\nBob likes the post') - sessionBob = createSession(useTor) + sessionBob=createSession(useTor) password='bobpass' outboxPath=bobDir+'/accounts/bob@'+bobDomain+'/outbox' inboxPath=aliceDir+'/accounts/alice@'+aliceDomain+'/inbox' @@ -1262,7 +1287,7 @@ def testClientToServer(): inboxPath=bobDir+'/accounts/bob@'+bobDomain+'/inbox' outboxPath=aliceDir+'/accounts/alice@'+aliceDomain+'/outbox' - postsBefore = len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))]) + postsBefore=len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))]) print('\n\nAlice deletes her post: '+outboxPostId+' '+str(postsBefore)) password='alicepass' sendDeleteViaServer(aliceDir,sessionAlice,'alice',password, @@ -1418,7 +1443,7 @@ def testGetStatusNumber(): print('testGetStatusNumber') prevStatusNumber=None for i in range(1,20): - statusNumber,published = getStatusNumber() + statusNumber,published=getStatusNumber() if prevStatusNumber: assert len(statusNumber) == 18 assert int(statusNumber) > prevStatusNumber diff --git a/theme.py b/theme.py index ee4cc8f0c..29f466c2b 100644 --- a/theme.py +++ b/theme.py @@ -1,10 +1,10 @@ -__filename__ = "theme.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="theme.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os from utils import loadJson diff --git a/threads.py b/threads.py index 534cb0b70..34c5347cb 100644 --- a/threads.py +++ b/threads.py @@ -1,10 +1,10 @@ -__filename__ = "threads.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="threads.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import threading import os @@ -20,9 +20,9 @@ class threadWithTrace(threading.Thread): tries=0 while tries<3: try: - self._args, self._keywords = args, keywords - threading.Thread.__init__(self, *self._args, **self._keywords) - self.killed = False + self._args,self._keywords=args,keywords + threading.Thread.__init__(self,*self._args,**self._keywords) + self.killed=False break except Exception as e: print('ERROR: threads.py/__init__ failed - '+str(e)) @@ -33,8 +33,8 @@ class threadWithTrace(threading.Thread): tries=0 while tries<3: try: - self.__run_backup = self.run - self.run = self.__run + self.__run_backup=self.run + self.run=self.__run threading.Thread.start(self) break except Exception as e: @@ -47,7 +47,7 @@ class threadWithTrace(threading.Thread): def __run(self): sys.settrace(self.globaltrace) self.__run_backup() - self.run = self.__run_backup + self.run=self.__run_backup def globaltrace(self, frame, event, arg): if event == 'call': @@ -62,7 +62,7 @@ class threadWithTrace(threading.Thread): return self.localtrace def kill(self): - self.killed = True + self.killed=True def clone(self,fn): return threadWithTrace(target=fn, \ diff --git a/tox.py b/tox.py index 248fd1505..e481279c7 100644 --- a/tox.py +++ b/tox.py @@ -1,10 +1,10 @@ -__filename__ = "tox.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="tox.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json diff --git a/utils.py b/utils.py index 2cdbea459..0bf329e1e 100644 --- a/utils.py +++ b/utils.py @@ -1,10 +1,10 @@ -__filename__ = "utils.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="utils.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import os import time @@ -198,17 +198,21 @@ def getDomainFromActor(actor: str) -> (str,int): """ port=None if '/profile/' in actor: - domain = actor.split('/profile/')[0].replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','') + domain= \ + actor.split('/profile/')[0].replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','') else: if '/channel/' in actor: - domain = actor.split('/channel/')[0].replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','') + domain= \ + actor.split('/channel/')[0].replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','') else: if '/users/' not in actor: - domain = actor.replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','') + domain= \ + actor.replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','') if '/' in actor: domain=domain.split('/')[0] else: - domain = actor.split('/users/')[0].replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','') + domain= \ + actor.split('/users/')[0].replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','') if ':' in domain: portStr=domain.split(':')[1] if not portStr.isdigit(): @@ -252,7 +256,7 @@ def followPerson(baseDir: str,nickname: str, domain: str, \ # remove them from the unfollowed file newLines='' with open(unfollowedFilename, "r") as f: - lines = f.readlines() + lines=f.readlines() for line in lines: if handleToFollow not in line: newLines+=line @@ -271,7 +275,7 @@ def followPerson(baseDir: str,nickname: str, domain: str, \ # prepend to follow file try: with open(filename, 'r+') as followFile: - content = followFile.read() + content=followFile.read() followFile.seek(0, 0) followFile.write(handleToFollow+'\n'+content) if debug: @@ -347,7 +351,7 @@ def removeModerationPostFromIndex(baseDir: str,postUrl: str,debug: bool) -> None postId=postUrl.replace('/activity','') if postId in open(moderationIndexFile).read(): with open(moderationIndexFile, "r") as f: - lines = f.readlines() + lines=f.readlines() with open(moderationIndexFile, "w+") as f: for line in lines: if line.strip("\n") != postId: @@ -485,7 +489,7 @@ def noOfActiveAccountsMonthly(baseDir: str,months: int) -> bool: lastUsedFilename=baseDir+'/accounts/'+account+'/.lastUsed' if os.path.isfile(lastUsedFilename): with open(lastUsedFilename, 'r') as lastUsedFile: - lastUsed = lastUsedFile.read() + lastUsed=lastUsedFile.read() if lastUsed.isdigit(): timeDiff=(currTime-int(lastUsed)) if timeDiff str: """Returns the date when a file was last modified """ - t = os.path.getmtime(filename) + t=os.path.getmtime(filename) modifiedTime=datetime.datetime.fromtimestamp(t) return modifiedTime.strftime("%Y-%m-%dT%H:%M:%SZ") @@ -624,7 +628,7 @@ def daysInMonth(year: int,monthNumber: int) -> int: def mergeDicts(dict1: {}, dict2: {}) -> {}: """Merges two dictionaries """ - res = {**dict1, **dict2} + res={**dict1,**dict2} return res def isBlogPost(postJsonObject: {}) -> bool: diff --git a/webfinger.py b/webfinger.py index 90e0a48c4..d564c79cf 100644 --- a/webfinger.py +++ b/webfinger.py @@ -1,10 +1,10 @@ -__filename__ = "webfinger.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="webfinger.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import base64 try: @@ -26,21 +26,21 @@ from utils import saveJson def parseHandle(handle: str) -> (str,str): if '.' not in handle: - return None, None + return None,None if '/@' in handle: - domain, nickname = \ + domain,nickname= \ handle.replace('https://','').replace('http://','').replace('dat://','').replace('i2p://','').split('/@') else: if '/users/' in handle: - domain, nickname = \ + domain,nickname= \ handle.replace('https://','').replace('http://','').replace('i2p://','').replace('dat://','').split('/users/') else: if '@' in handle: - nickname, domain = handle.split('@') + nickname,domain=handle.split('@') else: - return None, None + return None,None - return nickname, domain + return nickname,domain def webfingerHandle(session,handle: str,httpPrefix: str,cachedWebfingers: {}, \ fromDomain: str,projectVersion: str) -> {}: @@ -48,7 +48,7 @@ def webfingerHandle(session,handle: str,httpPrefix: str,cachedWebfingers: {}, \ print('WARN: No session specified for webfingerHandle') return None - nickname, domain = parseHandle(handle) + nickname,domain=parseHandle(handle) if not nickname: return None wfDomain=domain @@ -61,11 +61,15 @@ def webfingerHandle(session,handle: str,httpPrefix: str,cachedWebfingers: {}, \ wf=getWebfingerFromCache(nickname+'@'+wfDomain,cachedWebfingers) if wf: return wf - url = '{}://{}/.well-known/webfinger'.format(httpPrefix,domain) - par = {'resource': 'acct:{}'.format(nickname+'@'+wfDomain)} - hdr = {'Accept': 'application/jrd+json'} + url='{}://{}/.well-known/webfinger'.format(httpPrefix,domain) + par={ + 'resource': 'acct:{}'.format(nickname+'@'+wfDomain) + } + hdr={ + 'Accept': 'application/jrd+json' + } try: - result = getJson(session,url,hdr,par,projectVersion,httpPrefix,fromDomain) + result=getJson(session,url,hdr,par,projectVersion,httpPrefix,fromDomain) except Exception as e: print("Unable to webfinger " + url) print('nickname: '+str(nickname)) @@ -81,9 +85,9 @@ def generateMagicKey(publicKeyPem) -> str: """See magic_key method in https://github.com/tootsuite/mastodon/blob/707ddf7808f90e3ab042d7642d368c2ce8e95e6f/app/models/account.rb """ - privkey = RSA.importKey(publicKeyPem) - mod = base64.urlsafe_b64encode(number.long_to_bytes(privkey.n)).decode("utf-8") - pubexp = base64.urlsafe_b64encode(number.long_to_bytes(privkey.e)).decode("utf-8") + privkey=RSA.importKey(publicKeyPem) + mod=base64.urlsafe_b64encode(number.long_to_bytes(privkey.n)).decode("utf-8") + pubexp=base64.urlsafe_b64encode(number.long_to_bytes(privkey.e)).decode("utf-8") return f"data:application/magic-public-key,RSA.{mod}.{pubexp}" def storeWebfingerEndpoint(nickname: str,domain: str,port: int,baseDir: str, \ @@ -127,7 +131,7 @@ def createWebfingerEndpoint(nickname: str,domain: str,port: int, \ subjectStr="acct:"+originalDomain+"@"+originalDomain profilePageHref=httpPrefix+'://'+domain+'/about/more?instance_actor=true' - account = { + account={ "aliases": [ httpPrefix+"://"+domain+"/@"+personName, personId @@ -160,7 +164,7 @@ def createWebfingerEndpoint(nickname: str,domain: str,port: int, \ def webfingerNodeInfo(httpPrefix: str,domainFull: str) -> {}: """ /.well-known/nodeinfo endpoint """ - nodeinfo = { + nodeinfo={ 'links': [ { 'href': httpPrefix+'://'+domainFull+'/nodeinfo/2.0', diff --git a/webinterface.py b/webinterface.py index 2f382b5e3..574c7c953 100644 --- a/webinterface.py +++ b/webinterface.py @@ -1,10 +1,10 @@ -__filename__ = "webinterface.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" +__filename__="webinterface.py" +__author__="Bob Mottram" +__license__="AGPL3+" +__version__="1.1.0" +__maintainer__="Bob Mottram" +__email__="bob@freedombone.net" +__status__="Production" import json import time @@ -81,17 +81,25 @@ def updateAvatarImageCache(session,baseDir: str,httpPrefix: str, \ actorStr=actor.replace('/','-') avatarImagePath=baseDir+'/cache/avatars/'+actorStr if avatarUrl.endswith('.png') or '.png?' in avatarUrl: - sessionHeaders = {'Accept': 'image/png'} + sessionHeaders={ + 'Accept': 'image/png' + } avatarImageFilename=avatarImagePath+'.png' elif avatarUrl.endswith('.jpg') or avatarUrl.endswith('.jpeg') or \ '.jpg?' in avatarUrl or '.jpeg?' in avatarUrl: - sessionHeaders = {'Accept': 'image/jpeg'} + sessionHeaders={ + 'Accept': 'image/jpeg' + } avatarImageFilename=avatarImagePath+'.jpg' elif avatarUrl.endswith('.gif') or '.gif?' in avatarUrl: - sessionHeaders = {'Accept': 'image/gif'} + sessionHeaders={ + 'Accept': 'image/gif' + } avatarImageFilename=avatarImagePath+'.gif' elif avatarUrl.endswith('.webp') or '.webp?' in avatarUrl: - sessionHeaders = {'Accept': 'image/webp'} + sessionHeaders={ + 'Accept': 'image/webp' + } avatarImageFilename=avatarImagePath+'.webp' else: return None @@ -114,14 +122,14 @@ def updateAvatarImageCache(session,baseDir: str,httpPrefix: str, \ print('Failed to download avatar image: '+str(avatarUrl)) print(e) if '/channel/' not in actor: - sessionHeaders = { + sessionHeaders={ 'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"' } else: - sessionHeaders = { + sessionHeaders={ 'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' } - personJson = \ + personJson= \ getJson(session,actor,sessionHeaders,None,__version__, \ httpPrefix,None) if personJson: @@ -147,7 +155,7 @@ def updateAvatarImageCache(session,baseDir: str,httpPrefix: str, \ def getPersonAvatarUrl(baseDir: str,personUrl: str,personCache: {}) -> str: """Returns the avatar url for the person """ - personJson = getPersonFromCache(baseDir,personUrl,personCache) + personJson=getPersonFromCache(baseDir,personUrl,personCache) if not personJson: return None # get from locally stored image @@ -204,10 +212,10 @@ def htmlSearchEmoji(translate: {},baseDir: str,httpPrefix: str, \ results={} for emojiName,filename in emojiJson.items(): if searchStr in emojiName: - results[emojiName] = filename+'.png' + results[emojiName]=filename+'.png' for emojiName,filename in emojiJson.items(): if emojiName in searchStr: - results[emojiName] = filename+'.png' + results[emojiName]=filename+'.png' headingShown=False emojiForm+='
' for emojiName,filename in results.items(): @@ -382,7 +390,7 @@ def htmlModerationInfo(translate: {},baseDir: str,httpPrefix: str) -> str: suspendedFilename=baseDir+'/accounts/suspended.txt' if os.path.isfile(suspendedFilename): with open(suspendedFilename, "r") as f: - suspendedStr = f.read() + suspendedStr=f.read() infoForm+='
' infoForm+='
'+translate['Suspended accounts']+'' infoForm+='
'+translate['These are currently suspended'] @@ -395,7 +403,7 @@ def htmlModerationInfo(translate: {},baseDir: str,httpPrefix: str) -> str: blockingFilename=baseDir+'/accounts/blocking.txt' if os.path.isfile(blockingFilename): with open(blockingFilename, "r") as f: - blockedStr = f.read() + blockedStr=f.read() infoForm+='
' infoForm+= \ '
'+translate['Blocked accounts and hashtags']+'' @@ -437,14 +445,14 @@ def htmlHashtagSearch(nickname: str,domain: str,port: int, \ # read the index with open(hashtagIndexFile, "r") as f: - lines = f.readlines() + lines=f.readlines() # read the css cssFilename=baseDir+'/epicyon-profile.css' if os.path.isfile(baseDir+'/epicyon.css'): cssFilename=baseDir+'/epicyon.css' with open(cssFilename, 'r') as cssFile: - hashtagSearchCSS = cssFile.read() + hashtagSearchCSS=cssFile.read() if httpPrefix!='https': hashtagSearchCSS= \ hashtagSearchCSS.replace('https://',httpPrefix+'://') @@ -546,7 +554,7 @@ def htmlSkillsSearch(translate: {},baseDir: str, \ continue if f.startswith('inbox@'): continue - actorFilename = os.path.join(subdir, f) + actorFilename=os.path.join(subdir, f) actorJson=loadJson(actorFilename) if actorJson: if actorJson.get('id') and \ @@ -556,17 +564,19 @@ def htmlSkillsSearch(translate: {},baseDir: str, \ actor=actorJson['id'] for skillName,skillLevel in actorJson['skills'].items(): skillName=skillName.lower() - if skillName in skillsearch or skillsearch in skillName: - skillLevelStr=str(skillLevel) - if skillLevel<100: - skillLevelStr='0'+skillLevelStr - if skillLevel<10: - skillLevelStr='0'+skillLevelStr - indexStr= \ - skillLevelStr+';'+actor+';'+actorJson['name']+ \ - ';'+actorJson['icon']['url'] - if indexStr not in results: - results.append(indexStr) + if not (skillName in skillsearch or \ + skillsearch in skillName): + continue + skillLevelStr=str(skillLevel) + if skillLevel<100: + skillLevelStr='0'+skillLevelStr + if skillLevel<10: + skillLevelStr='0'+skillLevelStr + indexStr= \ + skillLevelStr+';'+actor+';'+actorJson['name']+ \ + ';'+actorJson['icon']['url'] + if indexStr not in results: + results.append(indexStr) if not instanceOnly: # search actor cache for subdir, dirs, files in os.walk(baseDir+'/cache/actors/'): @@ -577,7 +587,7 @@ def htmlSkillsSearch(translate: {},baseDir: str, \ continue if f.startswith('inbox@'): continue - actorFilename = os.path.join(subdir, f) + actorFilename=os.path.join(subdir, f) cachedActorJson=loadJson(actorFilename) if cachedActorJson: if cachedActorJson.get('actor'): @@ -589,17 +599,19 @@ def htmlSkillsSearch(translate: {},baseDir: str, \ actor=actorJson['id'] for skillName,skillLevel in actorJson['skills'].items(): skillName=skillName.lower() - if skillName in skillsearch or skillsearch in skillName: - skillLevelStr=str(skillLevel) - if skillLevel<100: - skillLevelStr='0'+skillLevelStr - if skillLevel<10: - skillLevelStr='0'+skillLevelStr - indexStr= \ - skillLevelStr+';'+actor+';'+actorJson['name']+ \ - ';'+actorJson['icon']['url'] - if indexStr not in results: - results.append(indexStr) + if not (skillName in skillsearch or \ + skillsearch in skillName): + continue + skillLevelStr=str(skillLevel) + if skillLevel<100: + skillLevelStr='0'+skillLevelStr + if skillLevel<10: + skillLevelStr='0'+skillLevelStr + indexStr= \ + skillLevelStr+';'+actor+';'+actorJson['name']+ \ + ';'+actorJson['icon']['url'] + if indexStr not in results: + results.append(indexStr) results.sort(reverse=True) @@ -607,7 +619,7 @@ def htmlSkillsSearch(translate: {},baseDir: str, \ if os.path.isfile(baseDir+'/epicyon.css'): cssFilename=baseDir+'/epicyon.css' with open(cssFilename, 'r') as cssFile: - skillSearchCSS = cssFile.read() + skillSearchCSS=cssFile.read() if httpPrefix!='https': skillSearchCSS=skillSearchCSS.replace('https://',httpPrefix+'://') skillSearchForm=htmlHeader(cssFilename,skillSearchCSS) @@ -622,17 +634,20 @@ def htmlSkillsSearch(translate: {},baseDir: str, \ ctr=0 for skillMatch in results: skillMatchFields=skillMatch.split(';') - if len(skillMatchFields)==4: - actor=skillMatchFields[1] - actorName=skillMatchFields[2] - avatarUrl=skillMatchFields[3] - skillSearchForm+='' - ctr+=1 - if ctr>=postsPerPage: - break + if len(skillMatchFields)!=4: + continue + actor=skillMatchFields[1] + actorName=skillMatchFields[2] + avatarUrl=skillMatchFields[3] + skillSearchForm+= \ + '' + ctr+=1 + if ctr>=postsPerPage: + break skillSearchForm+='
' skillSearchForm+=htmlFooter() return skillSearchForm @@ -640,7 +655,8 @@ def htmlSkillsSearch(translate: {},baseDir: str, \ def scheduledPostsExist(baseDir: str,nickname: str,domain: str) -> bool: """Returns true if there are posts scheduled to be delivered """ - scheduleIndexFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/schedule.index' + scheduleIndexFilename= \ + baseDir+'/accounts/'+nickname+'@'+domain+'/schedule.index' if not os.path.isfile(scheduleIndexFilename): return False if '#users#' in open(scheduleIndexFilename).read(): @@ -653,7 +669,8 @@ def htmlEditProfile(translate: {},baseDir: str,path: str, \ """ imageFormats='.png, .jpg, .jpeg, .gif, .webp' pathOriginal=path - path=path.replace('/inbox','').replace('/outbox','').replace('/shares','') + path= \ + path.replace('/inbox','').replace('/outbox','').replace('/shares','') nickname=getNicknameFromActor(path) if not nickname: return '' @@ -730,13 +747,15 @@ def htmlEditProfile(translate: {},baseDir: str,path: str, \ switchStr=switchfile.read() blockedStr='' - blockedFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/blocking.txt' + blockedFilename= \ + baseDir+'/accounts/'+nickname+'@'+domain+'/blocking.txt' if os.path.isfile(blockedFilename): with open(blockedFilename, 'r') as blockedfile: blockedStr=blockedfile.read() allowedInstancesStr='' - allowedInstancesFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/allowedinstances.txt' + allowedInstancesFilename= \ + baseDir+'/accounts/'+nickname+'@'+domain+'/allowedinstances.txt' if os.path.isfile(allowedInstancesFilename): with open(allowedInstancesFilename, 'r') as allowedInstancesFile: allowedInstancesStr=allowedInstancesFile.read() @@ -766,7 +785,7 @@ def htmlEditProfile(translate: {},baseDir: str,path: str, \ if os.path.isfile(baseDir+'/epicyon.css'): cssFilename=baseDir+'/epicyon.css' with open(cssFilename, 'r') as cssFile: - editProfileCSS = cssFile.read() + editProfileCSS=cssFile.read() if httpPrefix!='https': editProfileCSS=editProfileCSS.replace('https://',httpPrefix+'://') @@ -804,7 +823,7 @@ def htmlEditProfile(translate: {},baseDir: str,path: str, \ moderatorsFile=baseDir+'/accounts/moderators.txt' if os.path.isfile(moderatorsFile): with open(moderatorsFile, "r") as f: - moderators = f.read() + moderators=f.read() moderatorsStr='
' moderatorsStr+=' '+translate['Moderators']+'
' moderatorsStr+=' '+translate['A list of moderator nicknames. One per line.'] @@ -928,7 +947,8 @@ def htmlEditProfile(translate: {},baseDir: str,path: str, \ editProfileForm+=htmlFooter() return editProfileForm -def htmlGetLoginCredentials(loginParams: str,lastLoginTime: int) -> (str,str,bool): +def htmlGetLoginCredentials(loginParams: str, \ + lastLoginTime: int) -> (str,str,bool): """Receives login credentials via HTTPServer POST """ if not loginParams.startswith('username='): @@ -997,13 +1017,13 @@ def htmlLogin(translate: {},baseDir: str,autocomplete=True) -> str: if os.path.isfile(baseDir+'/accounts/login.txt'): # custom login message with open(baseDir+'/accounts/login.txt', 'r') as file: - loginText = '' + loginText='' cssFilename=baseDir+'/epicyon-login.css' if os.path.isfile(baseDir+'/login.css'): cssFilename=baseDir+'/login.css' with open(cssFilename, 'r') as cssFile: - loginCSS = cssFile.read() + loginCSS=cssFile.read() # show the register button registerButtonStr='' @@ -1065,7 +1085,7 @@ def htmlLogin(translate: {},baseDir: str,autocomplete=True) -> str: def htmlTermsOfService(baseDir: str,httpPrefix: str,domainFull: str) -> str: """Show the terms of service screen """ - adminNickname = getConfigParam(baseDir,'admin') + adminNickname=getConfigParam(baseDir,'admin') if not os.path.isfile(baseDir+'/accounts/tos.txt'): copyfile(baseDir+'/default_tos.txt',baseDir+'/accounts/tos.txt') if os.path.isfile(baseDir+'/img/login-background.png'): @@ -1076,14 +1096,14 @@ def htmlTermsOfService(baseDir: str,httpPrefix: str,domainFull: str) -> str: TOSText='Terms of Service go here.' if os.path.isfile(baseDir+'/accounts/tos.txt'): with open(baseDir+'/accounts/tos.txt', 'r') as file: - TOSText = file.read() + TOSText=file.read() TOSForm='' cssFilename=baseDir+'/epicyon-profile.css' if os.path.isfile(baseDir+'/epicyon.css'): cssFilename=baseDir+'/epicyon.css' with open(cssFilename, 'r') as cssFile: - termsCSS = cssFile.read() + termsCSS=cssFile.read() if httpPrefix!='https': termsCSS=termsCSS.replace('https://',httpPrefix+'://') @@ -1100,7 +1120,7 @@ def htmlTermsOfService(baseDir: str,httpPrefix: str,domainFull: str) -> str: def htmlAbout(baseDir: str,httpPrefix: str,domainFull: str) -> str: """Show the about screen """ - adminNickname = getConfigParam(baseDir,'admin') + adminNickname=getConfigParam(baseDir,'admin') if not os.path.isfile(baseDir+'/accounts/about.txt'): copyfile(baseDir+'/default_about.txt',baseDir+'/accounts/about.txt') if os.path.isfile(baseDir+'/img/login-background.png'): @@ -1111,14 +1131,14 @@ def htmlAbout(baseDir: str,httpPrefix: str,domainFull: str) -> str: aboutText='Information about this instance goes here.' if os.path.isfile(baseDir+'/accounts/about.txt'): with open(baseDir+'/accounts/about.txt', 'r') as file: - aboutText = file.read() + aboutText=file.read() aboutForm='' cssFilename=baseDir+'/epicyon-profile.css' if os.path.isfile(baseDir+'/epicyon.css'): cssFilename=baseDir+'/epicyon.css' with open(cssFilename, 'r') as cssFile: - termsCSS = cssFile.read() + termsCSS=cssFile.read() if httpPrefix!='http': termsCSS=termsCSS.replace('https://',httpPrefix+'://') @@ -1231,13 +1251,13 @@ def htmlNewPost(mediaInstance: bool,translate: {}, \ if os.path.isfile(baseDir+'/accounts/newpost.txt'): with open(baseDir+'/accounts/newpost.txt', 'r') as file: - newPostText = '

'+file.read()+'

' + newPostText='

'+file.read()+'

' cssFilename=baseDir+'/epicyon-profile.css' if os.path.isfile(baseDir+'/epicyon.css'): cssFilename=baseDir+'/epicyon.css' with open(cssFilename, 'r') as cssFile: - newPostCSS = cssFile.read() + newPostCSS=cssFile.read() if httpPrefix!='https': newPostCSS=newPostCSS.replace('https://',httpPrefix+'://') @@ -2017,7 +2037,7 @@ def htmlProfile(defaultTimeline: str, \ if os.path.isfile(baseDir+'/epicyon.css'): cssFilename=baseDir+'/epicyon.css' with open(cssFilename, 'r') as cssFile: - profileStyle = \ + profileStyle= \ cssFile.read().replace('image.png', \ profileJson['image']['url']) @@ -2085,7 +2105,7 @@ def individualFollowAsHtml(translate: {}, \ if not avatarUrl: avatarUrl=followUrl+'/avatar.png' if domain not in followUrl: - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl2,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl2,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,nickname,domain,'outbox') if avatarUrl2: @@ -2131,8 +2151,8 @@ def cursorToEndOfMessageScript() -> str: This avoids the cursor being in the wrong position when replying """ script='function focusOnMessage() {\n' - script+=" var replyTextArea = document.getElementById('message');\n" - script+=' val = replyTextArea.value;\n' + script+=" var replyTextArea=document.getElementById('message');\n" + script+=' val=replyTextArea.value;\n' script+=' if ((val.length>0) && (val.charAt(val.length-1) != " ")) {\n' script+=' val += " ";\n' script+=' }\n' @@ -2140,8 +2160,8 @@ def cursorToEndOfMessageScript() -> str: script+=' replyTextArea.value="";\n' script+=' replyTextArea.value=val;\n' script+='}\n' - script+="var replyTextArea = document.getElementById('message')\n" - script+='replyTextArea.onFocus = function() {\n' + script+="var replyTextArea=document.getElementById('message')\n" + script+='replyTextArea.onFocus=function() {\n' script+=' focusOnMessage();' script+='}\n' return script @@ -2150,11 +2170,11 @@ def contentWarningScript() -> str: """Returns a script used for content warnings """ script='function showContentWarning(postID) {\n' - script+=' var x = document.getElementById(postID);\n' + script+=' var x=document.getElementById(postID);\n' script+=' if (x.style.display !== "block") {\n' - script+=' x.style.display = "block";\n' + script+=' x.style.display="block";\n' script+=' } else {\n' - script+=' x.style.display = "none";\n' + script+=' x.style.display="none";\n' script+=' }\n' script+='}\n' return script @@ -2164,8 +2184,8 @@ def contentWarningScriptOpen() -> str: The warning is open by default. This is used on blog replies. """ script='function showContentWarning(postID) {\n' - script+=' var x = document.getElementById(postID);\n' - script+=' x.style.display = "block";\n' + script+=' var x=document.getElementById(postID);\n' + script+=' x.style.display="block";\n' script+='}\n' return script @@ -2531,7 +2551,7 @@ def loadIndividualPostAsHtmlFromCache(baseDir: str,nickname: str,domain: str, \ while tries<3: try: with open(cachedPostFilename, 'r') as file: - postHtml = file.read() + postHtml=file.read() break except Exception as e: print(e) @@ -2847,7 +2867,7 @@ def individualPostAsHtml(recentPostsCache: {},maxRecentPosts: int, \ avatarUrl=postActor+'/avatar.png' if fullDomain not in postActor: - inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl2,displayName = \ + inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl2,displayName= \ getPersonBox(baseDir,session,wfRequest,personCache, \ projectVersion,httpPrefix,nickname,domain,'outbox') if avatarUrl2: @@ -3267,15 +3287,15 @@ def individualPostAsHtml(recentPostsCache: {},maxRecentPosts: int, \ publishedStr=postJsonObject['object']['published'] if '.' not in publishedStr: if '+' not in publishedStr: - datetimeObject = \ + datetimeObject= \ datetime.strptime(publishedStr,"%Y-%m-%dT%H:%M:%SZ") else: - datetimeObject = \ + datetimeObject= \ datetime.strptime(publishedStr.split('+')[0]+'Z', \ "%Y-%m-%dT%H:%M:%SZ") else: publishedStr=publishedStr.replace('T',' ').split('.')[0] - datetimeObject = parse(publishedStr) + datetimeObject=parse(publishedStr) publishedStr=datetimeObject.strftime("%a %b %d, %H:%M") publishedLink=messageId @@ -3459,7 +3479,7 @@ def htmlTimeline(defaultTimeline: str, \ bannerFile='banner.webp' with open(cssFilename, 'r') as cssFile: - profileStyle = \ + profileStyle= \ cssFile.read().replace('banner.png', \ '/users/'+nickname+'/'+bannerFile) if httpPrefix!='https': @@ -4069,7 +4089,7 @@ def htmlRemoveSharedItem(translate: {},baseDir: str,actor: str,shareName: str) - if os.path.isfile(baseDir+'/follow.css'): cssFilename=baseDir+'/follow.css' with open(cssFilename, 'r') as cssFile: - profileStyle = cssFile.read() + profileStyle=cssFile.read() sharesStr=htmlHeader(cssFilename,profileStyle) sharesStr+='