flake8 style

main
Bob Mottram 2020-04-01 22:22:51 +00:00
parent 0f1e754913
commit fa7c457150
2 changed files with 376 additions and 379 deletions

View File

@ -31,19 +31,22 @@ Very close port of the original Swift implementation by Dag Ågren.
import math import math
# Alphabet for base 83 # Alphabet for base 83
alphabet="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~" alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~"
alphabet_values=dict(zip(alphabet,range(len(alphabet)))) alphabet_values = dict(zip(alphabet, range(len(alphabet))))
def base83_decode(base83_str): def base83_decode(base83_str):
""" """
Decodes a base83 string, as used in blurhash, to an integer. Decodes a base83 string, as used in blurhash, to an integer.
""" """
value=0 value = 0
for base83_char in base83_str: for base83_char in base83_str:
value=value*83+alphabet_values[base83_char] value = value * 83 + alphabet_values[base83_char]
return value return value
def base83_encode(value, length): def base83_encode(value, length):
""" """
Decodes an integer to a base83 string, as used in blurhash. Decodes an integer to a base83 string, as used in blurhash.
@ -54,20 +57,22 @@ def base83_encode(value, length):
if int(value) // (83 ** (length)) != 0: if int(value) // (83 ** (length)) != 0:
raise ValueError("Specified length is too short to encode given value.") raise ValueError("Specified length is too short to encode given value.")
result="" result = ""
for i in range(1,length+1): for i in range(1, length+1):
digit=int(value) // (83 ** (length - i)) % 83 digit = int(value) // (83 ** (length - i)) % 83
result += alphabet[int(digit)] result += alphabet[int(digit)]
return result return result
def srgb_to_linear(value): def srgb_to_linear(value):
""" """
srgb 0-255 integer to linear 0.0-1.0 floating point conversion. 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: if value <= 0.04045:
return value / 12.92 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): def sign_pow(value, exp):
""" """
@ -75,14 +80,16 @@ def sign_pow(value, exp):
""" """
return math.copysign(math.pow(abs(value), exp), value) return math.copysign(math.pow(abs(value), exp), value)
def linear_to_srgb(value): def linear_to_srgb(value):
""" """
linear 0.0-1.0 floating point to srgb 0-255 integer conversion. 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: if value <= 0.0031308:
return int(value*12.92*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) return int((1.055 * math.pow(value, 1 / 2.4) - 0.055) * 255 + 0.5)
def blurhash_components(blurhash): def blurhash_components(blurhash):
""" """
@ -92,13 +99,14 @@ def blurhash_components(blurhash):
raise ValueError("BlurHash must be at least 6 characters long.") raise ValueError("BlurHash must be at least 6 characters long.")
# Decode metadata # Decode metadata
size_info=base83_decode(blurhash[0]) size_info = base83_decode(blurhash[0])
size_y=int(size_info / 9)+1 size_y = int(size_info / 9) + 1
size_x=(size_info % 9)+1 size_x = (size_info % 9) + 1
return size_x, size_y 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. Decodes the given blurhash to an image of the specified size.
@ -117,20 +125,20 @@ def blurhash_decode(blurhash,width,height,punch=1.0,linear=False):
raise ValueError("BlurHash must be at least 6 characters long.") raise ValueError("BlurHash must be at least 6 characters long.")
# Decode metadata # Decode metadata
size_info=base83_decode(blurhash[0]) size_info = base83_decode(blurhash[0])
size_y=int(size_info / 9)+1 size_y = int(size_info / 9) + 1
size_x=(size_info % 9)+1 size_x = (size_info % 9) + 1
quant_max_value=base83_decode(blurhash[1]) quant_max_value = base83_decode(blurhash[1])
real_max_value=(float(quant_max_value+1)/166.0)*punch real_max_value = (float(quant_max_value+1) / 166.0) * punch
# Make sure we at least have the right number of characters # 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.") raise ValueError("Invalid BlurHash length.")
# Decode DC component # Decode DC component
dc_value=base83_decode(blurhash[2:6]) dc_value = base83_decode(blurhash[2:6])
colours=[( colours = [(
srgb_to_linear(dc_value >> 16), srgb_to_linear(dc_value >> 16),
srgb_to_linear((dc_value >> 8) & 255), srgb_to_linear((dc_value >> 8) & 255),
srgb_to_linear(dc_value & 255) srgb_to_linear(dc_value & 255)
@ -138,7 +146,7 @@ def blurhash_decode(blurhash,width,height,punch=1.0,linear=False):
# Decode AC components # Decode AC components
for component in range(1, size_x * size_y): 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(( 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,
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,21 +155,20 @@ def blurhash_decode(blurhash,width,height,punch=1.0,linear=False):
# Return image RGB values, as a list of lists of lists, # Return image RGB values, as a list of lists of lists,
# consumable by something like numpy or PIL. # consumable by something like numpy or PIL.
pixels=[] pixels = []
for y in range(height): for y in range(height):
pixel_row=[] pixel_row = []
for x in range(width): 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 j in range(size_y):
for i in range(size_x): for i in range(size_x):
basis= \ basis = math.cos(math.pi * float(x) * float(i) / float(width)) * \
math.cos(math.pi*float(x)*float(i)/float(width))* \ math.cos(math.pi * float(y) * float(j) / float(height))
math.cos(math.pi*float(y)*float(j)/float(height)) colour = colours[i + j * size_x]
colour=colours[i+j*size_x] pixel[0] += colour[0] * basis
pixel[0] += colour[0]*basis pixel[1] += colour[1] * basis
pixel[1] += colour[1]*basis pixel[2] += colour[2] * basis
pixel[2] += colour[2]*basis
if linear == False: if linear == False:
pixel_row.append([ pixel_row.append([
linear_to_srgb(pixel[0]), linear_to_srgb(pixel[0]),
@ -173,7 +180,8 @@ def blurhash_decode(blurhash,width,height,punch=1.0,linear=False):
pixels.append(pixel_row) pixels.append(pixel_row)
return pixels 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. Calculates the blurhash for an image using the given x and y component counts.
@ -185,16 +193,18 @@ def blurhash_encode(image,components_x=4,components_y=4,linear=False):
useful if you want to encode a version of your image resized to a smaller size (which useful if you want to encode a version of your image resized to a smaller size (which
you should ideally do in linear colour). you should ideally do in linear colour).
""" """
if components_x < 1 or components_x > 9 or components_y < 1 or components_y > 9: if components_x < 1 or components_x > 9 or \
raise ValueError("x and y component counts must be between 1 and 9 inclusive.") components_y < 1 or components_y > 9:
height=float(len(image)) raise ValueError("x and y component counts must be " +
width=float(len(image[0])) "between 1 and 9 inclusive.")
height = float(len(image))
width = float(len(image[0]))
# Convert to linear if neeeded # Convert to linear if neeeded
image_linear=[] image_linear = []
if linear==False: if linear == False:
for y in range(int(height)): for y in range(int(height)):
image_linear_line=[] image_linear_line = []
for x in range(int(width)): for x in range(int(width)):
image_linear_line.append([ image_linear_line.append([
srgb_to_linear(image[y][x][0]), srgb_to_linear(image[y][x][0]),
@ -203,19 +213,18 @@ def blurhash_encode(image,components_x=4,components_y=4,linear=False):
]) ])
image_linear.append(image_linear_line) image_linear.append(image_linear_line)
else: else:
image_linear=image image_linear = image
# Calculate components # Calculate components
components=[] components = []
max_ac_component=0.0 max_ac_component = 0.0
for j in range(components_y): for j in range(components_y):
for i in range(components_x): for i in range(components_x):
norm_factor=1.0 if (i==0 and j==0) else 2.0 norm_factor = 1.0 if (i == 0 and j == 0) else 2.0
component=[0.0,0.0,0.0] component = [0.0, 0.0, 0.0]
for y in range(int(height)): for y in range(int(height)):
for x in range(int(width)): for x in range(int(width)):
basis= \ basis = norm_factor * math.cos(math.pi * float(i) * float(x) / width) * \
norm_factor * math.cos(math.pi * float(i) * float(x) / width) * \
math.cos(math.pi * float(j) * float(y) / height) math.cos(math.pi * float(j) * float(y) / height)
component[0] += basis * image_linear[y][x][0] component[0] += basis * image_linear[y][x][0]
component[1] += basis * image_linear[y][x][1] component[1] += basis * image_linear[y][x][1]
@ -227,22 +236,20 @@ def blurhash_encode(image,components_x=4,components_y=4,linear=False):
components.append(component) components.append(component)
if not (i==0 and j==0): if not (i==0 and j==0):
max_ac_component= \ max_ac_component = max(max_ac_component,abs(component[0]),
max(max_ac_component,abs(component[0]), \
abs(component[1]),abs(component[2])) abs(component[1]),abs(component[2]))
# Encode components # Encode components
dc_value= \ dc_value = (linear_to_srgb(components[0][0]) << 16) + \
(linear_to_srgb(components[0][0]) << 16)+ \ (linear_to_srgb(components[0][1]) << 8) + \
(linear_to_srgb(components[0][1]) << 8)+ \
linear_to_srgb(components[0][2]) linear_to_srgb(components[0][2])
quant_max_ac_component= \ quant_max_ac_component = int(max(0, min(82,
int(max(0, min(82, math.floor(max_ac_component * 166 - 0.5)))) math.floor(max_ac_component *
ac_component_norm_factor= \ 166 - 0.5))))
float(quant_max_ac_component+1) / 166.0 ac_component_norm_factor = float(quant_max_ac_component + 1) / 166.0
ac_values=[] ac_values = []
for r, g, b in components[1:]: for r, g, b in components[1:]:
ac_values.append( 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(r / ac_component_norm_factor, 0.5) * 9.0 + 9.5)))) * 19 * 19 + \
@ -251,7 +258,7 @@ def blurhash_encode(image,components_x=4,components_y=4,linear=False):
) )
# Build final blurhash # Build final blurhash
blurhash="" blurhash = ""
blurhash += base83_encode((components_x - 1) + (components_y - 1) * 9, 1) blurhash += base83_encode((components_x - 1) + (components_y - 1) * 9, 1)
blurhash += base83_encode(quant_max_ac_component, 1) blurhash += base83_encode(quant_max_ac_component, 1)
blurhash += base83_encode(dc_value, 4) blurhash += base83_encode(dc_value, 4)

View File

@ -1,14 +1,12 @@
__filename__="bookmarks.py" __filename__ = "bookmarks.py"
__author__="Bob Mottram" __author__ = "Bob Mottram"
__license__="AGPL3+" __license__ = "AGPL3+"
__version__="1.1.0" __version__ = "1.1.0"
__maintainer__="Bob Mottram" __maintainer__ = "Bob Mottram"
__email__="bob@freedombone.net" __email__ = "bob@freedombone.net"
__status__="Production" __status__ = "Production"
import os import os
import json
import time
from pprint import pprint from pprint import pprint
from utils import removePostFromCache from utils import removePostFromCache
from utils import urlPermitted from utils import urlPermitted
@ -24,32 +22,35 @@ from webfinger import webfingerHandle
from auth import createBasicAuthHeader from auth import createBasicAuthHeader
from posts import getPersonBox from posts import getPersonBox
def undoBookmarksCollectionEntry(recentPostsCache: {}, \
baseDir: str,postFilename: str,objectUrl: str, \ def undoBookmarksCollectionEntry(recentPostsCache: {},
actor: str,domain: str,debug: bool) -> None: baseDir: str, postFilename: str,
objectUrl: str,
actor: str, domain: str, debug: bool) -> None:
"""Undoes a bookmark for a particular actor """Undoes a bookmark for a particular actor
""" """
postJsonObject=loadJson(postFilename) postJsonObject = loadJson(postFilename)
if not postJsonObject: if not postJsonObject:
return return
# remove any cached version of this post so that the bookmark icon is changed # remove any cached version of this post so that the
nickname=getNicknameFromActor(actor) # bookmark icon is changed
cachedPostFilename= \ nickname = getNicknameFromActor(actor)
getCachedPostFilename(baseDir,nickname,domain,postJsonObject) cachedPostFilename = getCachedPostFilename(baseDir, nickname,
domain, postJsonObject)
if cachedPostFilename: if cachedPostFilename:
if os.path.isfile(cachedPostFilename): if os.path.isfile(cachedPostFilename):
os.remove(cachedPostFilename) os.remove(cachedPostFilename)
removePostFromCache(postJsonObject,recentPostsCache) removePostFromCache(postJsonObject, recentPostsCache)
if not postJsonObject.get('type'): if not postJsonObject.get('type'):
return return
if postJsonObject['type']!='Create': if postJsonObject['type'] != 'Create':
return return
if not postJsonObject.get('object'): if not postJsonObject.get('object'):
if debug: if debug:
pprint(postJsonObject) pprint(postJsonObject)
print('DEBUG: post '+objectUrl+' has no object') print('DEBUG: post ' + objectUrl + ' has no object')
return return
if not isinstance(postJsonObject['object'], dict): if not isinstance(postJsonObject['object'], dict):
return return
@ -59,64 +60,67 @@ def undoBookmarksCollectionEntry(recentPostsCache: {}, \
return return
if not postJsonObject['object']['bookmarks'].get('items'): if not postJsonObject['object']['bookmarks'].get('items'):
return return
totalItems=0 totalItems = 0
if postJsonObject['object']['bookmarks'].get('totalItems'): if postJsonObject['object']['bookmarks'].get('totalItems'):
totalItems=postJsonObject['object']['bookmarks']['totalItems'] totalItems = postJsonObject['object']['bookmarks']['totalItems']
itemFound=False itemFound = False
for bookmarkItem in postJsonObject['object']['bookmarks']['items']: for bookmarkItem in postJsonObject['object']['bookmarks']['items']:
if bookmarkItem.get('actor'): if bookmarkItem.get('actor'):
if bookmarkItem['actor']==actor: if bookmarkItem['actor'] == actor:
if debug: if debug:
print('DEBUG: bookmark was removed for '+actor) print('DEBUG: bookmark was removed for ' + actor)
postJsonObject['object']['bookmarks']['items'].remove(bookmarkItem) bmIt = bookmarkItem
itemFound=True postJsonObject['object']['bookmarks']['items'].remove(bmIt)
itemFound = True
break break
if not itemFound: if not itemFound:
return return
if totalItems==1: if totalItems == 1:
if debug: if debug:
print('DEBUG: bookmarks was removed from post') print('DEBUG: bookmarks was removed from post')
del postJsonObject['object']['bookmarks'] del postJsonObject['object']['bookmarks']
else: else:
postJsonObject['object']['bookmarks']['totalItems']= \ bmItLen = len(postJsonObject['object']['bookmarks']['items'])
len(postJsonObject['bookmarks']['items']) postJsonObject['object']['bookmarks']['totalItems'] = bmItLen
saveJson(postJsonObject,postFilename) saveJson(postJsonObject, postFilename)
# remove from the index # remove from the index
bookmarksIndexFilename= \ bookmarksIndexFilename = baseDir + '/accounts/' + \
baseDir+'/accounts/'+nickname+'@'+domain+'/bookmarks.index' nickname + '@' + domain + '/bookmarks.index'
if not os.path.isfile(bookmarksIndexFilename): if not os.path.isfile(bookmarksIndexFilename):
return return
if '/' in postFilename: if '/' in postFilename:
bookmarkIndex=postFilename.split('/')[-1].strip() bookmarkIndex = postFilename.split('/')[-1].strip()
else: else:
bookmarkIndex=postFilename.strip() bookmarkIndex = postFilename.strip()
if bookmarkIndex not in open(bookmarksIndexFilename).read(): if bookmarkIndex not in open(bookmarksIndexFilename).read():
return return
indexStr='' indexStr = ''
indexStrChanged=False indexStrChanged = False
with open(bookmarksIndexFilename, 'r') as indexFile: with open(bookmarksIndexFilename, 'r') as indexFile:
indexStr=indexFile.read().replace(bookmarkIndex+'\n','') indexStr = indexFile.read().replace(bookmarkIndex + '\n', '')
indexStrChanged=True indexStrChanged = True
if indexStrChanged: if indexStrChanged:
bookmarksIndexFile=open(bookmarksIndexFilename,'w') bookmarksIndexFile = open(bookmarksIndexFilename, 'w')
if bookmarksIndexFile: if bookmarksIndexFile:
bookmarksIndexFile.write(indexStr) bookmarksIndexFile.write(indexStr)
bookmarksIndexFile.close() bookmarksIndexFile.close()
def bookmarkedByPerson(postJsonObject: {}, nickname: str,domain: str) -> bool:
def bookmarkedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool:
"""Returns True if the given post is bookmarked by the given person """Returns True if the given post is bookmarked by the given person
""" """
if noOfBookmarks(postJsonObject)==0: if noOfBookmarks(postJsonObject) == 0:
return False return False
actorMatch=domain+'/users/'+nickname actorMatch = domain + '/users/' + nickname
for item in postJsonObject['object']['bookmarks']['items']: for item in postJsonObject['object']['bookmarks']['items']:
if item['actor'].endswith(actorMatch): if item['actor'].endswith(actorMatch):
return True return True
return False return False
def noOfBookmarks(postJsonObject: {}) -> int: def noOfBookmarks(postJsonObject: {}) -> int:
"""Returns the number of bookmarks ona given post """Returns the number of bookmarks ona given post
""" """
@ -129,38 +133,40 @@ def noOfBookmarks(postJsonObject: {}) -> int:
if not isinstance(postJsonObject['object']['bookmarks'], dict): if not isinstance(postJsonObject['object']['bookmarks'], dict):
return 0 return 0
if not postJsonObject['object']['bookmarks'].get('items'): if not postJsonObject['object']['bookmarks'].get('items'):
postJsonObject['object']['bookmarks']['items']=[] postJsonObject['object']['bookmarks']['items'] = []
postJsonObject['object']['bookmarks']['totalItems']=0 postJsonObject['object']['bookmarks']['totalItems'] = 0
return len(postJsonObject['object']['bookmarks']['items']) return len(postJsonObject['object']['bookmarks']['items'])
def updateBookmarksCollection(recentPostsCache: {}, \
baseDir: str,postFilename: str, \ def updateBookmarksCollection(recentPostsCache: {},
objectUrl: str, \ baseDir: str, postFilename: str,
actor: str,domain: str,debug: bool) -> None: objectUrl: str,
actor: str, domain: str, debug: bool) -> None:
"""Updates the bookmarks collection within a post """Updates the bookmarks collection within a post
""" """
postJsonObject=loadJson(postFilename) postJsonObject = loadJson(postFilename)
if postJsonObject: if postJsonObject:
# remove any cached version of this post so that the bookmark icon is changed # remove any cached version of this post so that the
nickname=getNicknameFromActor(actor) # bookmark icon is changed
cachedPostFilename= \ nickname = getNicknameFromActor(actor)
getCachedPostFilename(baseDir,nickname,domain,postJsonObject) cachedPostFilename = getCachedPostFilename(baseDir, nickname,
domain, postJsonObject)
if cachedPostFilename: if cachedPostFilename:
if os.path.isfile(cachedPostFilename): if os.path.isfile(cachedPostFilename):
os.remove(cachedPostFilename) os.remove(cachedPostFilename)
removePostFromCache(postJsonObject,recentPostsCache) removePostFromCache(postJsonObject, recentPostsCache)
if not postJsonObject.get('object'): if not postJsonObject.get('object'):
if debug: if debug:
pprint(postJsonObject) pprint(postJsonObject)
print('DEBUG: post '+objectUrl+' has no object') print('DEBUG: post ' + objectUrl + ' has no object')
return return
if not objectUrl.endswith('/bookmarks'): if not objectUrl.endswith('/bookmarks'):
objectUrl=objectUrl+'/bookmarks' objectUrl = objectUrl + '/bookmarks'
if not postJsonObject['object'].get('bookmarks'): if not postJsonObject['object'].get('bookmarks'):
if debug: if debug:
print('DEBUG: Adding initial bookmarks to '+objectUrl) print('DEBUG: Adding initial bookmarks to ' + objectUrl)
bookmarksJson={ bookmarksJson = {
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
'id': objectUrl, 'id': objectUrl,
'type': 'Collection', 'type': 'Collection',
@ -170,190 +176,180 @@ def updateBookmarksCollection(recentPostsCache: {}, \
'actor': actor 'actor': actor
}] }]
} }
postJsonObject['object']['bookmarks']=bookmarksJson postJsonObject['object']['bookmarks'] = bookmarksJson
else: else:
if not postJsonObject['object']['bookmarks'].get('items'): if not postJsonObject['object']['bookmarks'].get('items'):
postJsonObject['object']['bookmarks']['items']=[] postJsonObject['object']['bookmarks']['items'] = []
for bookmarkItem in postJsonObject['object']['bookmarks']['items']: for bookmarkItem in postJsonObject['object']['bookmarks']['items']:
if bookmarkItem.get('actor'): if bookmarkItem.get('actor'):
if bookmarkItem['actor']==actor: if bookmarkItem['actor'] == actor:
return return
newBookmark={ newBookmark = {
'type': 'Bookmark', 'type': 'Bookmark',
'actor': actor 'actor': actor
} }
postJsonObject['object']['bookmarks']['items'].append(newBookmark) nb = newBookmark
postJsonObject['object']['bookmarks']['totalItems']= \ bmIt = len(postJsonObject['object']['bookmarks']['items'])
len(postJsonObject['object']['bookmarks']['items']) postJsonObject['object']['bookmarks']['items'].append(nb)
postJsonObject['object']['bookmarks']['totalItems'] = bmIt
if debug: if debug:
print('DEBUG: saving post with bookmarks added') print('DEBUG: saving post with bookmarks added')
pprint(postJsonObject) pprint(postJsonObject)
saveJson(postJsonObject,postFilename) saveJson(postJsonObject, postFilename)
# prepend to the index # prepend to the index
bookmarksIndexFilename= \ bookmarksIndexFilename = baseDir + '/accounts/' + \
baseDir+'/accounts/'+nickname+'@'+domain+'/bookmarks.index' nickname + '@' + domain + '/bookmarks.index'
bookmarkIndex=postFilename.split('/')[-1] bookmarkIndex = postFilename.split('/')[-1]
if os.path.isfile(bookmarksIndexFilename): if os.path.isfile(bookmarksIndexFilename):
if bookmarkIndex not in open(bookmarksIndexFilename).read(): if bookmarkIndex not in open(bookmarksIndexFilename).read():
try: try:
with open(bookmarksIndexFilename, 'r+') as bookmarksIndexFile: with open(bookmarksIndexFilename, 'r+') as bmIndexFile:
content=bookmarksIndexFile.read() content = bmIndexFile.read()
bookmarksIndexFile.seek(0, 0) bmIndexFile.seek(0, 0)
bookmarksIndexFile.write(bookmarkIndex+'\n'+content) bmIndexFile.write(bookmarkIndex + '\n' + content)
if debug: if debug:
print('DEBUG: bookmark added to index') print('DEBUG: bookmark added to index')
except Exception as e: except Exception as e:
print('WARN: Failed to write entry to bookmarks index '+ \ print('WARN: Failed to write entry to bookmarks index ' +
bookmarksIndexFilename+' '+str(e)) bookmarksIndexFilename + ' ' + str(e))
else: else:
bookmarksIndexFile=open(bookmarksIndexFilename,'w') bookmarksIndexFile = open(bookmarksIndexFilename, 'w')
if bookmarksIndexFile: if bookmarksIndexFile:
bookmarksIndexFile.write(bookmarkIndex+'\n') bookmarksIndexFile.write(bookmarkIndex + '\n')
bookmarksIndexFile.close() bookmarksIndexFile.close()
def bookmark(recentPostsCache: {}, \
session,baseDir: str,federationList: [], \ def bookmark(recentPostsCache: {},
nickname: str,domain: str,port: int, \ session, baseDir: str, federationList: [],
ccList: [],httpPrefix: str, \ nickname: str, domain: str, port: int,
objectUrl: str,actorBookmarked: str, \ ccList: [], httpPrefix: str,
clientToServer: bool, \ objectUrl: str, actorBookmarked: str,
sendThreads: [],postLog: [], \ clientToServer: bool,
personCache: {},cachedWebfingers: {}, \ sendThreads: [], postLog: [],
debug: bool,projectVersion: str) -> {}: personCache: {}, cachedWebfingers: {},
debug: bool, projectVersion: str) -> {}:
"""Creates a bookmark """Creates a bookmark
actor is the person doing the bookmarking actor is the person doing the bookmarking
'to' might be a specific person (actor) whose post was bookmarked 'to' might be a specific person (actor) whose post was bookmarked
object is typically the url of the message which was bookmarked object is typically the url of the message which was bookmarked
""" """
if not urlPermitted(objectUrl,federationList,"inbox:write"): if not urlPermitted(objectUrl, federationList, "inbox:write"):
return None return None
fullDomain=domain fullDomain = domain
if port: if port:
if port!=80 and port!=443: if port != 80 and port != 443:
if ':' not in domain: if ':' not in domain:
fullDomain=domain+':'+str(port) fullDomain = domain + ':' + str(port)
bookmarkTo=[] newBookmarkJson = {
if '/statuses/' in objectUrl:
bookmarkTo=[objectUrl.split('/statuses/')[0]]
newBookmarkJson={
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
'type': 'Bookmark', 'type': 'Bookmark',
'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname,
'object': objectUrl 'object': objectUrl
} }
if ccList: if ccList:
if len(ccList)>0: if len(ccList) > 0:
newBookmarkJson['cc']=ccList newBookmarkJson['cc'] = ccList
# Extract the domain and nickname from a statuses link # Extract the domain and nickname from a statuses link
bookmarkedPostNickname=None bookmarkedPostNickname = None
bookmarkedPostDomain=None bookmarkedPostDomain = None
bookmarkedPostPort=None bookmarkedPostPort = None
if actorBookmarked: if actorBookmarked:
bookmarkedPostNickname=getNicknameFromActor(actorBookmarked) acBm = actorBookmarked
bookmarkedPostDomain,bookmarkedPostPort= \ bookmarkedPostNickname = getNicknameFromActor(acBm)
getDomainFromActor(actorBookmarked) bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(acBm)
else: else:
if '/users/' in objectUrl or \ if '/users/' in objectUrl or \
'/channel/' in objectUrl or \ '/channel/' in objectUrl or \
'/profile/' in objectUrl: '/profile/' in objectUrl:
bookmarkedPostNickname=getNicknameFromActor(objectUrl) ou = objectUrl
bookmarkedPostDomain,bookmarkedPostPort= \ bookmarkedPostNickname = getNicknameFromActor(ou)
getDomainFromActor(objectUrl) bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(ou)
if bookmarkedPostNickname: if bookmarkedPostNickname:
postFilename=locatePost(baseDir,nickname,domain,objectUrl) postFilename = locatePost(baseDir, nickname, domain, objectUrl)
if not postFilename: if not postFilename:
print('DEBUG: bookmark baseDir: '+baseDir) print('DEBUG: bookmark baseDir: ' + baseDir)
print('DEBUG: bookmark nickname: '+nickname) print('DEBUG: bookmark nickname: ' + nickname)
print('DEBUG: bookmark domain: '+domain) print('DEBUG: bookmark domain: ' + domain)
print('DEBUG: bookmark objectUrl: '+objectUrl) print('DEBUG: bookmark objectUrl: ' + objectUrl)
return None return None
updateBookmarksCollection(recentPostsCache, \ updateBookmarksCollection(recentPostsCache,
baseDir,postFilename,objectUrl, \ baseDir, postFilename, objectUrl,
newBookmarkJson['actor'],domain,debug) newBookmarkJson['actor'], domain, debug)
sendSignedJson(newBookmarkJson,session,baseDir, \ sendSignedJson(newBookmarkJson, session, baseDir,
nickname,domain,port, \ nickname, domain, port,
bookmarkedPostNickname, \ bookmarkedPostNickname,
bookmarkedPostDomain,bookmarkedPostPort, \ bookmarkedPostDomain, bookmarkedPostPort,
'https://www.w3.org/ns/activitystreams#Public', \ 'https://www.w3.org/ns/activitystreams#Public',
httpPrefix,True,clientToServer,federationList, \ httpPrefix, True, clientToServer, federationList,
sendThreads,postLog,cachedWebfingers,personCache, \ sendThreads, postLog, cachedWebfingers, personCache,
debug,projectVersion) debug, projectVersion)
return newBookmarkJson return newBookmarkJson
def bookmarkPost(recentPostsCache: {}, \
session,baseDir: str,federationList: [], \ def bookmarkPost(recentPostsCache: {},
nickname: str,domain: str,port: int,httpPrefix: str, \ session, baseDir: str, federationList: [],
bookmarkNickname: str,bookmarkedomain: str,bookmarkPort: int, \ nickname: str, domain: str, port: int, httpPrefix: str,
ccList: [], \ bookmarkNickname: str, bookmarkedomain: str,
bookmarkStatusNumber: int,clientToServer: bool, \ bookmarkPort: int,
sendThreads: [],postLog: [], \ ccList: [],
personCache: {},cachedWebfingers: {}, \ bookmarkStatusNumber: int, clientToServer: bool,
debug: bool,projectVersion: str) -> {}: sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
debug: bool, projectVersion: str) -> {}:
"""Bookmarks a given status post. This is only used by unit tests """Bookmarks a given status post. This is only used by unit tests
""" """
bookmarkedomain=bookmarkedomain bookmarkedomain = bookmarkedomain
if bookmarkPort: if bookmarkPort:
if bookmarkPort!=80 and bookmarkPort!=443: if bookmarkPort != 80 and bookmarkPort != 443:
if ':' not in bookmarkedomain: if ':' not in bookmarkedomain:
bookmarkedomain=bookmarkedomain+':'+str(bookmarkPort) bookmarkedomain = bookmarkedomain + ':' + str(bookmarkPort)
actorBookmarked= \ actorBookmarked = httpPrefix + '://' + bookmarkedomain + \
httpPrefix + '://'+bookmarkedomain+'/users/'+bookmarkNickname '/users/' + bookmarkNickname
objectUrl=actorBookmarked+'/statuses/'+str(bookmarkStatusNumber) objectUrl = actorBookmarked + '/statuses/' + str(bookmarkStatusNumber)
ccUrl=httpPrefix+'://'+bookmarkedomain+'/users/'+bookmarkNickname return bookmark(recentPostsCache,
if bookmarkPort: session, baseDir, federationList, nickname, domain, port,
if bookmarkPort!=80 and bookmarkPort!=443: ccList, httpPrefix, objectUrl, actorBookmarked,
if ':' not in bookmarkedomain: clientToServer,
ccUrl= \ sendThreads, postLog, personCache, cachedWebfingers,
httpPrefix+'://'+bookmarkedomain+':'+ \ debug, projectVersion)
str(bookmarkPort)+'/users/'+bookmarkNickname
return bookmark(recentPostsCache, \
session,baseDir,federationList,nickname,domain,port, \
ccList,httpPrefix,objectUrl,actorBookmarked,clientToServer, \
sendThreads,postLog,personCache,cachedWebfingers, \
debug,projectVersion)
def undoBookmark(recentPostsCache: {}, \ def undoBookmark(recentPostsCache: {},
session,baseDir: str,federationList: [], \ session, baseDir: str, federationList: [],
nickname: str,domain: str,port: int, \ nickname: str, domain: str, port: int,
ccList: [],httpPrefix: str, \ ccList: [], httpPrefix: str,
objectUrl: str,actorBookmarked: str, \ objectUrl: str, actorBookmarked: str,
clientToServer: bool, \ clientToServer: bool,
sendThreads: [],postLog: [], \ sendThreads: [], postLog: [],
personCache: {},cachedWebfingers: {}, \ personCache: {}, cachedWebfingers: {},
debug: bool,projectVersion: str) -> {}: debug: bool, projectVersion: str) -> {}:
"""Removes a bookmark """Removes a bookmark
actor is the person doing the bookmarking actor is the person doing the bookmarking
'to' might be a specific person (actor) whose post was bookmarked 'to' might be a specific person (actor) whose post was bookmarked
object is typically the url of the message which was bookmarked object is typically the url of the message which was bookmarked
""" """
if not urlPermitted(objectUrl,federationList,"inbox:write"): if not urlPermitted(objectUrl, federationList, "inbox:write"):
return None return None
fullDomain=domain fullDomain = domain
if port: if port:
if port!=80 and port!=443: if port != 80 and port != 443:
if ':' not in domain: if ':' not in domain:
fullDomain=domain+':'+str(port) fullDomain = domain + ':' + str(port)
bookmarkTo=[] newUndoBookmarkJson = {
if '/statuses/' in objectUrl:
bookmarkTo=[objectUrl.split('/statuses/')[0]]
newUndoBookmarkJson={
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
'type': 'Undo', 'type': 'Undo',
'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname,
@ -364,181 +360,171 @@ def undoBookmark(recentPostsCache: {}, \
} }
} }
if ccList: if ccList:
if len(ccList)>0: if len(ccList) > 0:
newUndoBookmarkJson['cc']=ccList newUndoBookmarkJson['cc'] = ccList
newUndoBookmarkJson['object']['cc']=ccList newUndoBookmarkJson['object']['cc'] = ccList
# Extract the domain and nickname from a statuses link # Extract the domain and nickname from a statuses link
bookmarkedPostNickname=None bookmarkedPostNickname = None
bookmarkedPostDomain=None bookmarkedPostDomain = None
bookmarkedPostPort=None bookmarkedPostPort = None
if actorBookmarked: if actorBookmarked:
bookmarkedPostNickname=getNicknameFromActor(actorBookmarked) acBm = actorBookmarked
bookmarkedPostDomain,bookmarkedPostPort= \ bookmarkedPostNickname = getNicknameFromActor(acBm)
getDomainFromActor(actorBookmarked) bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(acBm)
else: else:
if '/users/' in objectUrl or \ if '/users/' in objectUrl or \
'/channel/' in objectUrl or \ '/channel/' in objectUrl or \
'/profile/' in objectUrl: '/profile/' in objectUrl:
bookmarkedPostNickname=getNicknameFromActor(objectUrl) ou = objectUrl
bookmarkedPostDomain,bookmarkedPostPort= \ bookmarkedPostNickname = getNicknameFromActor(ou)
getDomainFromActor(objectUrl) bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(ou)
if bookmarkedPostNickname: if bookmarkedPostNickname:
postFilename=locatePost(baseDir,nickname,domain,objectUrl) postFilename = locatePost(baseDir, nickname, domain, objectUrl)
if not postFilename: if not postFilename:
return None return None
undoBookmarksCollectionEntry(recentPostsCache, \ undoBookmarksCollectionEntry(recentPostsCache,
baseDir,postFilename,objectUrl, \ baseDir, postFilename, objectUrl,
newBookmarkJson['actor'],domain,debug) newUndoBookmarkJson['actor'],
domain, debug)
sendSignedJson(newUndoBookmarkJson,session,baseDir, \ sendSignedJson(newUndoBookmarkJson, session, baseDir,
nickname,domain,port, \ nickname, domain, port,
bookmarkedPostNickname,bookmarkedPostDomain,bookmarkedPostPort, \ bookmarkedPostNickname, bookmarkedPostDomain,
'https://www.w3.org/ns/activitystreams#Public', \ bookmarkedPostPort,
httpPrefix,True,clientToServer,federationList, \ 'https://www.w3.org/ns/activitystreams#Public',
sendThreads,postLog,cachedWebfingers,personCache, \ httpPrefix, True, clientToServer, federationList,
debug,projectVersion) sendThreads, postLog, cachedWebfingers, personCache,
debug, projectVersion)
else: else:
return None return None
return newUndoBookmarkJson return newUndoBookmarkJson
def undoBookmarkPost(session,baseDir: str,federationList: [], \
nickname: str,domain: str,port: int,httpPrefix: str, \ def undoBookmarkPost(session, baseDir: str, federationList: [],
bookmarkNickname: str,bookmarkedomain: str, \ nickname: str, domain: str, port: int, httpPrefix: str,
bookmarkPort: int,ccList: [], \ bookmarkNickname: str, bookmarkedomain: str,
bookmarkStatusNumber: int,clientToServer: bool, \ bookmarkPort: int, ccList: [],
sendThreads: [],postLog: [], \ bookmarkStatusNumber: int, clientToServer: bool,
personCache: {},cachedWebfingers: {}, \ sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
debug: bool) -> {}: debug: bool) -> {}:
"""Removes a bookmarked post """Removes a bookmarked post
""" """
bookmarkedomain=bookmarkedomain bookmarkedomain = bookmarkedomain
if bookmarkPort: if bookmarkPort:
if bookmarkPort!=80 and bookmarkPort!=443: if bookmarkPort != 80 and bookmarkPort != 443:
if ':' not in bookmarkedomain: if ':' not in bookmarkedomain:
bookmarkedomain=bookmarkedomain+':'+str(bookmarkPort) bookmarkedomain = bookmarkedomain + ':' + str(bookmarkPort)
objectUrl= \ objectUrl = httpPrefix + '://' + bookmarkedomain + \
httpPrefix+'://'+bookmarkedomain+'/users/'+bookmarkNickname+ \ '/users/' + bookmarkNickname + \
'/statuses/'+str(bookmarkStatusNumber) '/statuses/' + str(bookmarkStatusNumber)
ccUrl=httpPrefix+'://'+bookmarkedomain+'/users/'+bookmarkNickname return undoBookmark(session, baseDir, federationList,
if bookmarkPort: nickname, domain, port,
if bookmarkPort!=80 and bookmarkPort!=443: ccList, httpPrefix, objectUrl, clientToServer,
if ':' not in bookmarkedomain: sendThreads, postLog, personCache,
ccUrl= \ cachedWebfingers, debug)
httpPrefix+'://'+bookmarkedomain+':'+ \
str(bookmarkPort)+'/users/'+bookmarkNickname
return undoBookmark(session,baseDir,federationList,nickname,domain,port, \
ccList,httpPrefix,objectUrl,clientToServer, \
sendThreads,postLog,personCache,cachedWebfingers,debug)
def sendBookmarkViaServer(baseDir: str,session, \ def sendBookmarkViaServer(baseDir: str, session,
fromNickname: str,password: str, fromNickname: str, password: str,
fromDomain: str,fromPort: int, \ fromDomain: str, fromPort: int,
httpPrefix: str,bookmarkUrl: str, \ httpPrefix: str, bookmarkUrl: str,
cachedWebfingers: {},personCache: {}, \ cachedWebfingers: {}, personCache: {},
debug: bool,projectVersion: str) -> {}: debug: bool, projectVersion: str) -> {}:
"""Creates a bookmark via c2s """Creates a bookmark via c2s
""" """
if not session: if not session:
print('WARN: No session for sendBookmarkViaServer') print('WARN: No session for sendBookmarkViaServer')
return 6 return 6
fromDomainFull=fromDomain fromDomainFull = fromDomain
if fromPort: if fromPort:
if fromPort!=80 and fromPort!=443: if fromPort != 80 and fromPort != 443:
if ':' not in fromDomain: if ':' not in fromDomain:
fromDomainFull=fromDomain+':'+str(fromPort) fromDomainFull = fromDomain + ':' + str(fromPort)
toUrl=['https://www.w3.org/ns/activitystreams#Public'] newBookmarkJson = {
ccUrl=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers'
if '/statuses/' in bookmarkUrl:
toUrl=[bookmarkUrl.split('/statuses/')[0]]
newBookmarkJson={
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
'type': 'Bookmark', 'type': 'Bookmark',
'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname,
'object': bookmarkUrl 'object': bookmarkUrl
} }
handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname handle = httpPrefix + '://' + fromDomainFull + '/@' + fromNickname
# lookup the inbox for the To handle # lookup the inbox for the To handle
wfRequest=webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ wfRequest = webfingerHandle(session, handle, httpPrefix,
fromDomain,projectVersion) cachedWebfingers,
fromDomain, projectVersion)
if not wfRequest: if not wfRequest:
if debug: if debug:
print('DEBUG: announce webfinger failed for '+handle) print('DEBUG: announce webfinger failed for ' + handle)
return 1 return 1
postToBox='outbox' postToBox = 'outbox'
# get the actor inbox for the To handle # get the actor inbox for the To handle
inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ (inboxUrl, pubKeyId, pubKey,
getPersonBox(baseDir,session,wfRequest,personCache, \ fromPersonId, sharedInbox,
projectVersion,httpPrefix,fromNickname, \ capabilityAcquisition, avatarUrl,
fromDomain,postToBox) displayName) = getPersonBox(baseDir, session, wfRequest, personCache,
projectVersion, httpPrefix, fromNickname,
fromDomain, postToBox)
if not inboxUrl: if not inboxUrl:
if debug: if debug:
print('DEBUG: No '+postToBox+' was found for '+handle) print('DEBUG: No ' + postToBox + ' was found for ' + handle)
return 3 return 3
if not fromPersonId: if not fromPersonId:
if debug: if debug:
print('DEBUG: No actor was found for '+handle) print('DEBUG: No actor was found for ' + handle)
return 4 return 4
authHeader=createBasicAuthHeader(fromNickname,password) authHeader = createBasicAuthHeader(fromNickname, password)
headers={ headers = {
'host': fromDomain, \ 'host': fromDomain,
'Content-type': 'application/json', \ 'Content-type': 'application/json',
'Authorization': authHeader 'Authorization': authHeader
} }
postResult= \ postResult = postJson(session, newBookmarkJson, [],
postJson(session,newBookmarkJson,[],inboxUrl,headers,"inbox:write") inboxUrl, headers, "inbox:write")
#if not postResult: if not postResult:
# if debug: if debug:
# print('DEBUG: POST announce failed for c2s to '+inboxUrl) print('DEBUG: POST announce failed for c2s to ' + inboxUrl)
# return 5 return 5
if debug: if debug:
print('DEBUG: c2s POST bookmark success') print('DEBUG: c2s POST bookmark success')
return newBookmarkJson return newBookmarkJson
def sendUndoBookmarkViaServer(baseDir: str,session, \
fromNickname: str,password: str, \ def sendUndoBookmarkViaServer(baseDir: str, session,
fromDomain: str,fromPort: int, \ fromNickname: str, password: str,
httpPrefix: str,bookmarkUrl: str, \ fromDomain: str, fromPort: int,
cachedWebfingers: {},personCache: {}, \ httpPrefix: str, bookmarkUrl: str,
debug: bool,projectVersion: str) -> {}: cachedWebfingers: {}, personCache: {},
debug: bool, projectVersion: str) -> {}:
"""Undo a bookmark via c2s """Undo a bookmark via c2s
""" """
if not session: if not session:
print('WARN: No session for sendUndoBookmarkViaServer') print('WARN: No session for sendUndoBookmarkViaServer')
return 6 return 6
fromDomainFull=fromDomain fromDomainFull = fromDomain
if fromPort: if fromPort:
if fromPort!=80 and fromPort!=443: if fromPort != 80 and fromPort != 443:
if ':' not in fromDomain: if ':' not in fromDomain:
fromDomainFull=fromDomain+':'+str(fromPort) fromDomainFull = fromDomain + ':' + str(fromPort)
toUrl=['https://www.w3.org/ns/activitystreams#Public'] newUndoBookmarkJson = {
ccUrl=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers'
if '/statuses/' in bookmarkUrl:
toUrl=[bookmarkUrl.split('/statuses/')[0]]
newUndoBookmarkJson={
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
'type': 'Undo', 'type': 'Undo',
'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, 'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname,
@ -549,63 +535,66 @@ def sendUndoBookmarkViaServer(baseDir: str,session, \
} }
} }
handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname handle = httpPrefix + '://' + fromDomainFull + '/@' + fromNickname
# lookup the inbox for the To handle # lookup the inbox for the To handle
wfRequest=webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ wfRequest = webfingerHandle(session, handle, httpPrefix, cachedWebfingers,
fromDomain,projectVersion) fromDomain, projectVersion)
if not wfRequest: if not wfRequest:
if debug: if debug:
print('DEBUG: announce webfinger failed for '+handle) print('DEBUG: announce webfinger failed for ' + handle)
return 1 return 1
postToBox='outbox' postToBox = 'outbox'
# get the actor inbox for the To handle # get the actor inbox for the To handle
inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ (inboxUrl, pubKeyId, pubKey,
getPersonBox(baseDir,session,wfRequest,personCache, \ fromPersonId, sharedInbox,
projectVersion,httpPrefix,fromNickname, \ capabilityAcquisition, avatarUrl,
fromDomain,postToBox) displayName) = getPersonBox(baseDir, session, wfRequest, personCache,
projectVersion, httpPrefix, fromNickname,
fromDomain, postToBox)
if not inboxUrl: if not inboxUrl:
if debug: if debug:
print('DEBUG: No '+postToBox+' was found for '+handle) print('DEBUG: No ' + postToBox + ' was found for ' + handle)
return 3 return 3
if not fromPersonId: if not fromPersonId:
if debug: if debug:
print('DEBUG: No actor was found for '+handle) print('DEBUG: No actor was found for ' + handle)
return 4 return 4
authHeader=createBasicAuthHeader(fromNickname,password) authHeader = createBasicAuthHeader(fromNickname, password)
headers={ headers = {
'host': fromDomain, \ 'host': fromDomain,
'Content-type': 'application/json', \ 'Content-type': 'application/json',
'Authorization': authHeader 'Authorization': authHeader
} }
postResult= \ postResult = postJson(session, newUndoBookmarkJson, [],
postJson(session,newUndoBookmarkJson,[],inboxUrl,headers,"inbox:write") inboxUrl, headers, "inbox:write")
#if not postResult: if not postResult:
# if debug: if debug:
# print('DEBUG: POST announce failed for c2s to '+inboxUrl) print('DEBUG: POST announce failed for c2s to ' + inboxUrl)
# return 5 return 5
if debug: if debug:
print('DEBUG: c2s POST undo bookmark success') print('DEBUG: c2s POST undo bookmark success')
return newUndoBookmarkJson return newUndoBookmarkJson
def outboxBookmark(recentPostsCache: {}, \
baseDir: str,httpPrefix: str, \ def outboxBookmark(recentPostsCache: {},
nickname: str,domain: str,port: int, \ baseDir: str, httpPrefix: str,
messageJson: {},debug: bool) -> None: nickname: str, domain: str, port: int,
messageJson: {}, debug: bool) -> None:
""" When a bookmark request is received by the outbox from c2s """ When a bookmark request is received by the outbox from c2s
""" """
if not messageJson.get('type'): if not messageJson.get('type'):
if debug: if debug:
print('DEBUG: bookmark - no type') print('DEBUG: bookmark - no type')
return return
if not messageJson['type']=='Bookmark': if not messageJson['type'] == 'Bookmark':
if debug: if debug:
print('DEBUG: not a bookmark') print('DEBUG: not a bookmark')
return return
@ -620,39 +609,40 @@ def outboxBookmark(recentPostsCache: {}, \
if messageJson.get('to'): if messageJson.get('to'):
if not isinstance(messageJson['to'], list): if not isinstance(messageJson['to'], list):
return return
if len(messageJson['to'])!=1: if len(messageJson['to']) != 1:
print('WARN: Bookmark should only be sent to one recipient') print('WARN: Bookmark should only be sent to one recipient')
return return
if messageJson['to'][0]!=messageJson['actor']: if messageJson['to'][0] != messageJson['actor']:
print('WARN: Bookmark should be addressed to the same actor') print('WARN: Bookmark should be addressed to the same actor')
return return
if debug: if debug:
print('DEBUG: c2s bookmark request arrived in outbox') print('DEBUG: c2s bookmark request arrived in outbox')
messageId=messageJson['object'].replace('/activity','') messageId = messageJson['object'].replace('/activity', '')
if ':' in domain: if ':' in domain:
domain=domain.split(':')[0] domain = domain.split(':')[0]
postFilename=locatePost(baseDir,nickname,domain,messageId) postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename: if not postFilename:
if debug: if debug:
print('DEBUG: c2s bookmark post not found in inbox or outbox') print('DEBUG: c2s bookmark post not found in inbox or outbox')
print(messageId) print(messageId)
return True return True
updateBookmarksCollection(recentPostsCache, \ updateBookmarksCollection(recentPostsCache,
baseDir,postFilename,messageId, \ baseDir, postFilename, messageId,
messageJson['actor'],domain,debug) messageJson['actor'], domain, debug)
if debug: if debug:
print('DEBUG: post bookmarked via c2s - '+postFilename) print('DEBUG: post bookmarked via c2s - ' + postFilename)
def outboxUndoBookmark(recentPostsCache: {}, \
baseDir: str,httpPrefix: str, \ def outboxUndoBookmark(recentPostsCache: {},
nickname: str,domain: str,port: int, \ baseDir: str, httpPrefix: str,
messageJson: {},debug: bool) -> None: nickname: str, domain: str, port: int,
messageJson: {}, debug: bool) -> None:
""" When an undo bookmark request is received by the outbox from c2s """ When an undo bookmark request is received by the outbox from c2s
""" """
if not messageJson.get('type'): if not messageJson.get('type'):
return return
if not messageJson['type']=='Undo': if not messageJson['type'] == 'Undo':
return return
if not messageJson.get('object'): if not messageJson.get('object'):
return return
@ -664,7 +654,7 @@ def outboxUndoBookmark(recentPostsCache: {}, \
if debug: if debug:
print('DEBUG: undo bookmark - no type') print('DEBUG: undo bookmark - no type')
return return
if not messageJson['object']['type']=='Bookmark': if not messageJson['object']['type'] == 'Bookmark':
if debug: if debug:
print('DEBUG: not a undo bookmark') print('DEBUG: not a undo bookmark')
return return
@ -679,26 +669,26 @@ def outboxUndoBookmark(recentPostsCache: {}, \
if messageJson.get('to'): if messageJson.get('to'):
if not isinstance(messageJson['to'], list): if not isinstance(messageJson['to'], list):
return return
if len(messageJson['to'])!=1: if len(messageJson['to']) != 1:
print('WARN: Bookmark should only be sent to one recipient') print('WARN: Bookmark should only be sent to one recipient')
return return
if messageJson['to'][0]!=messageJson['actor']: if messageJson['to'][0] != messageJson['actor']:
print('WARN: Bookmark should be addressed to the same actor') print('WARN: Bookmark should be addressed to the same actor')
return return
if debug: if debug:
print('DEBUG: c2s undo bookmark request arrived in outbox') print('DEBUG: c2s undo bookmark request arrived in outbox')
messageId=messageJson['object']['object'].replace('/activity','') messageId = messageJson['object']['object'].replace('/activity', '')
if ':' in domain: if ':' in domain:
domain=domain.split(':')[0] domain = domain.split(':')[0]
postFilename=locatePost(baseDir,nickname,domain,messageId) postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename: if not postFilename:
if debug: if debug:
print('DEBUG: c2s undo bookmark post not found in inbox or outbox') print('DEBUG: c2s undo bookmark post not found in inbox or outbox')
print(messageId) print(messageId)
return True return True
undoBookmarksCollectionEntry(recentPostsCache, \ undoBookmarksCollectionEntry(recentPostsCache,
baseDir,postFilename,messageId, \ baseDir, postFilename, messageId,
messageJson['actor'],domain,debug) messageJson['actor'], domain, debug)
if debug: if debug:
print('DEBUG: post undo bookmarked via c2s - '+postFilename) print('DEBUG: post undo bookmarked via c2s - ' + postFilename)