epicyon/bookmarks.py

661 lines
24 KiB
Python
Raw Normal View History

2020-04-01 22:22:51 +00:00
__filename__ = "bookmarks.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
2021-01-26 10:07:42 +00:00
__version__ = "1.2.0"
2020-04-01 22:22:51 +00:00
__maintainer__ = "Bob Mottram"
2021-09-10 16:14:50 +00:00
__email__ = "bob@libreserver.org"
2020-04-01 22:22:51 +00:00
__status__ = "Production"
2021-06-15 15:08:12 +00:00
__module_group__ = "Timeline"
2019-11-17 14:01:49 +00:00
import os
from pprint import pprint
2021-03-19 22:04:57 +00:00
from webfinger import webfingerHandle
from auth import createBasicAuthHeader
2021-06-26 14:21:24 +00:00
from utils import removeDomainPort
2020-12-23 10:57:44 +00:00
from utils import hasUsersPath
2020-12-16 10:30:54 +00:00
from utils import getFullDomain
2020-08-23 11:13:35 +00:00
from utils import removeIdEnding
2019-11-24 21:50:18 +00:00
from utils import removePostFromCache
2019-11-17 14:01:49 +00:00
from utils import urlPermitted
from utils import getNicknameFromActor
from utils import getDomainFromActor
from utils import locatePost
from utils import getCachedPostFilename
from utils import loadJson
from utils import saveJson
from utils import hasObjectDict
2021-07-13 21:59:53 +00:00
from utils import acctDir
2021-08-14 11:13:39 +00:00
from utils import localActorUrl
from utils import hasActor
2021-10-13 10:11:02 +00:00
from utils import hasObjectStringType
2021-03-19 22:04:57 +00:00
from posts import getPersonBox
from session import postJson
2019-11-17 14:01:49 +00:00
2020-04-01 22:22:51 +00:00
def undoBookmarksCollectionEntry(recentPostsCache: {},
2021-12-25 16:17:53 +00:00
base_dir: str, postFilename: str,
2020-04-01 22:22:51 +00:00
objectUrl: str,
actor: str, domain: str, debug: bool) -> None:
2019-11-17 14:01:49 +00:00
"""Undoes a bookmark for a particular actor
"""
2020-04-01 22:22:51 +00:00
postJsonObject = loadJson(postFilename)
2019-11-18 15:21:35 +00:00
if not postJsonObject:
return
2019-11-17 14:01:49 +00:00
2020-04-01 22:22:51 +00:00
# remove any cached version of this post so that the
# bookmark icon is changed
nickname = getNicknameFromActor(actor)
2021-12-25 16:17:53 +00:00
cachedPostFilename = getCachedPostFilename(base_dir, nickname,
2020-04-01 22:22:51 +00:00
domain, postJsonObject)
2019-11-29 23:04:37 +00:00
if cachedPostFilename:
if os.path.isfile(cachedPostFilename):
try:
os.remove(cachedPostFilename)
2021-11-25 18:42:38 +00:00
except OSError:
2021-10-29 16:31:20 +00:00
if debug:
print('EX: undoBookmarksCollectionEntry ' +
'unable to delete cached post file ' +
str(cachedPostFilename))
2020-04-01 22:22:51 +00:00
removePostFromCache(postJsonObject, recentPostsCache)
2019-11-18 15:21:35 +00:00
2020-05-21 22:12:31 +00:00
# remove from the index
2021-07-13 21:59:53 +00:00
bookmarksIndexFilename = \
2021-12-25 16:17:53 +00:00
acctDir(base_dir, nickname, domain) + '/bookmarks.index'
2020-05-21 22:12:31 +00:00
if not os.path.isfile(bookmarksIndexFilename):
return
if '/' in postFilename:
bookmarkIndex = postFilename.split('/')[-1].strip()
else:
bookmarkIndex = postFilename.strip()
2020-05-22 11:32:38 +00:00
bookmarkIndex = bookmarkIndex.replace('\n', '').replace('\r', '')
2020-05-21 22:12:31 +00:00
if bookmarkIndex not in open(bookmarksIndexFilename).read():
return
indexStr = ''
2021-11-26 12:28:20 +00:00
try:
with open(bookmarksIndexFilename, 'r') as indexFile:
indexStr = indexFile.read().replace(bookmarkIndex + '\n', '')
except OSError:
print('EX: unable to read ' + bookmarksIndexFilename)
if indexStr:
2021-11-25 18:42:38 +00:00
try:
with open(bookmarksIndexFilename, 'w+') as bookmarksIndexFile:
bookmarksIndexFile.write(indexStr)
except OSError:
2021-11-25 22:22:54 +00:00
print('EX: unable to write bookmarks index ' +
2021-11-25 18:42:38 +00:00
bookmarksIndexFilename)
2019-11-18 15:21:35 +00:00
if not postJsonObject.get('type'):
return
2020-04-01 22:22:51 +00:00
if postJsonObject['type'] != 'Create':
2019-11-18 15:21:35 +00:00
return
if not hasObjectDict(postJsonObject):
2019-11-18 15:21:35 +00:00
if debug:
2021-03-20 10:13:59 +00:00
print('DEBUG: bookmarked post has no object ' +
str(postJsonObject))
2019-11-18 15:21:35 +00:00
return
if not postJsonObject['object'].get('bookmarks'):
return
if not isinstance(postJsonObject['object']['bookmarks'], dict):
return
if not postJsonObject['object']['bookmarks'].get('items'):
return
2020-04-01 22:22:51 +00:00
totalItems = 0
2019-11-18 15:21:35 +00:00
if postJsonObject['object']['bookmarks'].get('totalItems'):
2020-04-01 22:22:51 +00:00
totalItems = postJsonObject['object']['bookmarks']['totalItems']
itemFound = False
2019-11-18 15:21:35 +00:00
for bookmarkItem in postJsonObject['object']['bookmarks']['items']:
if bookmarkItem.get('actor'):
2020-04-01 22:22:51 +00:00
if bookmarkItem['actor'] == actor:
2019-11-17 14:01:49 +00:00
if debug:
2020-04-01 22:22:51 +00:00
print('DEBUG: bookmark was removed for ' + actor)
bmIt = bookmarkItem
postJsonObject['object']['bookmarks']['items'].remove(bmIt)
itemFound = True
2019-11-18 15:21:35 +00:00
break
if not itemFound:
return
2020-04-01 22:22:51 +00:00
if totalItems == 1:
2019-11-18 15:21:35 +00:00
if debug:
print('DEBUG: bookmarks was removed from post')
del postJsonObject['object']['bookmarks']
else:
2020-04-01 22:22:51 +00:00
bmItLen = len(postJsonObject['object']['bookmarks']['items'])
postJsonObject['object']['bookmarks']['totalItems'] = bmItLen
saveJson(postJsonObject, postFilename)
2019-11-17 14:01:49 +00:00
2020-04-01 22:22:51 +00:00
def bookmarkedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool:
2019-11-17 14:01:49 +00:00
"""Returns True if the given post is bookmarked by the given person
"""
if _noOfBookmarks(postJsonObject) == 0:
2019-11-17 14:01:49 +00:00
return False
2020-04-01 22:22:51 +00:00
actorMatch = domain + '/users/' + nickname
2019-11-17 14:01:49 +00:00
for item in postJsonObject['object']['bookmarks']['items']:
if item['actor'].endswith(actorMatch):
return True
return False
2020-04-01 22:22:51 +00:00
def _noOfBookmarks(postJsonObject: {}) -> int:
2019-11-17 14:01:49 +00:00
"""Returns the number of bookmarks ona given post
"""
if not hasObjectDict(postJsonObject):
2019-11-17 14:01:49 +00:00
return 0
if not postJsonObject['object'].get('bookmarks'):
return 0
if not isinstance(postJsonObject['object']['bookmarks'], dict):
return 0
if not postJsonObject['object']['bookmarks'].get('items'):
2020-04-01 22:22:51 +00:00
postJsonObject['object']['bookmarks']['items'] = []
postJsonObject['object']['bookmarks']['totalItems'] = 0
2019-11-17 14:01:49 +00:00
return len(postJsonObject['object']['bookmarks']['items'])
2020-04-01 22:22:51 +00:00
def updateBookmarksCollection(recentPostsCache: {},
2021-12-25 16:17:53 +00:00
base_dir: str, postFilename: str,
2020-04-01 22:22:51 +00:00
objectUrl: str,
actor: str, domain: str, debug: bool) -> None:
2019-11-17 14:01:49 +00:00
"""Updates the bookmarks collection within a post
"""
2020-04-01 22:22:51 +00:00
postJsonObject = loadJson(postFilename)
2019-11-17 14:01:49 +00:00
if postJsonObject:
2020-04-01 22:22:51 +00:00
# remove any cached version of this post so that the
# bookmark icon is changed
nickname = getNicknameFromActor(actor)
2021-12-25 16:17:53 +00:00
cachedPostFilename = getCachedPostFilename(base_dir, nickname,
2020-04-01 22:22:51 +00:00
domain, postJsonObject)
2019-11-29 23:04:37 +00:00
if cachedPostFilename:
if os.path.isfile(cachedPostFilename):
try:
os.remove(cachedPostFilename)
2021-11-25 18:42:38 +00:00
except OSError:
2021-10-29 16:31:20 +00:00
if debug:
print('EX: updateBookmarksCollection ' +
'unable to delete cached post ' +
str(cachedPostFilename))
2020-04-01 22:22:51 +00:00
removePostFromCache(postJsonObject, recentPostsCache)
2019-11-17 14:01:49 +00:00
if not postJsonObject.get('object'):
if debug:
2021-03-20 10:13:59 +00:00
print('DEBUG: no object in bookmarked post ' +
str(postJsonObject))
2019-11-17 14:01:49 +00:00
return
if not objectUrl.endswith('/bookmarks'):
2020-04-01 22:22:51 +00:00
objectUrl = objectUrl + '/bookmarks'
2021-03-20 10:13:59 +00:00
# does this post have bookmarks on it from differenent actors?
2019-11-17 14:01:49 +00:00
if not postJsonObject['object'].get('bookmarks'):
if debug:
2020-04-01 22:22:51 +00:00
print('DEBUG: Adding initial bookmarks to ' + objectUrl)
bookmarksJson = {
2019-11-18 16:03:54 +00:00
"@context": "https://www.w3.org/ns/activitystreams",
'id': objectUrl,
'type': 'Collection',
"totalItems": 1,
'items': [{
'type': 'Bookmark',
'actor': actor
2020-03-22 21:16:02 +00:00
}]
2019-11-18 16:03:54 +00:00
}
2020-04-01 22:22:51 +00:00
postJsonObject['object']['bookmarks'] = bookmarksJson
2019-11-17 14:01:49 +00:00
else:
if not postJsonObject['object']['bookmarks'].get('items'):
2020-04-01 22:22:51 +00:00
postJsonObject['object']['bookmarks']['items'] = []
2019-11-17 14:01:49 +00:00
for bookmarkItem in postJsonObject['object']['bookmarks']['items']:
if bookmarkItem.get('actor'):
2020-04-01 22:22:51 +00:00
if bookmarkItem['actor'] == actor:
2019-11-17 14:01:49 +00:00
return
newBookmark = {
'type': 'Bookmark',
'actor': actor
}
nb = newBookmark
bmIt = len(postJsonObject['object']['bookmarks']['items'])
postJsonObject['object']['bookmarks']['items'].append(nb)
postJsonObject['object']['bookmarks']['totalItems'] = bmIt
2019-11-17 14:01:49 +00:00
if debug:
print('DEBUG: saving post with bookmarks added')
pprint(postJsonObject)
2020-04-01 22:22:51 +00:00
saveJson(postJsonObject, postFilename)
2019-11-17 14:01:49 +00:00
# prepend to the index
2021-07-13 21:59:53 +00:00
bookmarksIndexFilename = \
2021-12-25 16:17:53 +00:00
acctDir(base_dir, nickname, domain) + '/bookmarks.index'
2020-04-01 22:22:51 +00:00
bookmarkIndex = postFilename.split('/')[-1]
2019-11-17 14:01:49 +00:00
if os.path.isfile(bookmarksIndexFilename):
if bookmarkIndex not in open(bookmarksIndexFilename).read():
try:
2020-04-01 22:22:51 +00:00
with open(bookmarksIndexFilename, 'r+') as bmIndexFile:
content = bmIndexFile.read()
if bookmarkIndex + '\n' not in content:
bmIndexFile.seek(0, 0)
bmIndexFile.write(bookmarkIndex + '\n' + content)
if debug:
print('DEBUG: bookmark added to index')
2021-12-25 15:28:52 +00:00
except Exception as ex:
2020-04-01 22:22:51 +00:00
print('WARN: Failed to write entry to bookmarks index ' +
2021-12-25 15:28:52 +00:00
bookmarksIndexFilename + ' ' + str(ex))
2019-11-17 14:01:49 +00:00
else:
2021-11-25 18:42:38 +00:00
try:
with open(bookmarksIndexFilename, 'w+') as bookmarksIndexFile:
bookmarksIndexFile.write(bookmarkIndex + '\n')
except OSError:
2021-11-25 22:22:54 +00:00
print('EX: unable to write bookmarks index ' +
2021-11-25 18:42:38 +00:00
bookmarksIndexFilename)
2019-11-17 14:01:49 +00:00
2020-04-01 22:22:51 +00:00
def bookmark(recentPostsCache: {},
2021-12-25 16:17:53 +00:00
session, base_dir: str, federationList: [],
2020-04-01 22:22:51 +00:00
nickname: str, domain: str, port: int,
2021-12-25 17:09:22 +00:00
ccList: [], http_prefix: str,
2020-04-01 22:22:51 +00:00
objectUrl: str, actorBookmarked: str,
clientToServer: bool,
sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
2021-12-25 20:34:38 +00:00
debug: bool, project_version: str) -> {}:
2019-11-17 14:01:49 +00:00
"""Creates a bookmark
actor is the person doing the bookmarking
'to' might be a specific person (actor) whose post was bookmarked
object is typically the url of the message which was bookmarked
"""
2020-09-27 19:27:24 +00:00
if not urlPermitted(objectUrl, federationList):
2019-11-17 14:01:49 +00:00
return None
2020-12-16 10:30:54 +00:00
fullDomain = getFullDomain(domain, port)
2019-11-17 14:01:49 +00:00
2020-04-01 22:22:51 +00:00
newBookmarkJson = {
2019-11-17 14:01:49 +00:00
"@context": "https://www.w3.org/ns/activitystreams",
'type': 'Bookmark',
2021-12-25 17:09:22 +00:00
'actor': localActorUrl(http_prefix, nickname, fullDomain),
2019-11-17 14:01:49 +00:00
'object': objectUrl
}
if ccList:
2020-04-01 22:22:51 +00:00
if len(ccList) > 0:
newBookmarkJson['cc'] = ccList
2019-11-17 14:01:49 +00:00
# Extract the domain and nickname from a statuses link
2020-04-01 22:22:51 +00:00
bookmarkedPostNickname = None
bookmarkedPostDomain = None
bookmarkedPostPort = None
2019-11-17 14:01:49 +00:00
if actorBookmarked:
2020-04-01 22:22:51 +00:00
acBm = actorBookmarked
bookmarkedPostNickname = getNicknameFromActor(acBm)
bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(acBm)
2019-11-17 14:01:49 +00:00
else:
2020-12-23 10:57:44 +00:00
if hasUsersPath(objectUrl):
2020-04-01 22:22:51 +00:00
ou = objectUrl
bookmarkedPostNickname = getNicknameFromActor(ou)
bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(ou)
2019-11-17 14:01:49 +00:00
if bookmarkedPostNickname:
2021-12-25 16:17:53 +00:00
postFilename = locatePost(base_dir, nickname, domain, objectUrl)
2019-11-17 14:01:49 +00:00
if not postFilename:
2021-12-25 16:17:53 +00:00
print('DEBUG: bookmark base_dir: ' + base_dir)
2020-04-01 22:22:51 +00:00
print('DEBUG: bookmark nickname: ' + nickname)
print('DEBUG: bookmark domain: ' + domain)
print('DEBUG: bookmark objectUrl: ' + objectUrl)
2019-11-17 14:01:49 +00:00
return None
2020-03-22 21:16:02 +00:00
2020-04-01 22:22:51 +00:00
updateBookmarksCollection(recentPostsCache,
2021-12-25 16:17:53 +00:00
base_dir, postFilename, objectUrl,
2020-04-01 22:22:51 +00:00
newBookmarkJson['actor'], domain, debug)
2019-11-17 14:01:49 +00:00
return newBookmarkJson
2020-04-01 22:22:51 +00:00
def undoBookmark(recentPostsCache: {},
2021-12-25 16:17:53 +00:00
session, base_dir: str, federationList: [],
2020-04-01 22:22:51 +00:00
nickname: str, domain: str, port: int,
2021-12-25 17:09:22 +00:00
ccList: [], http_prefix: str,
2020-04-01 22:22:51 +00:00
objectUrl: str, actorBookmarked: str,
clientToServer: bool,
sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
2021-12-25 20:34:38 +00:00
debug: bool, project_version: str) -> {}:
2019-11-17 14:01:49 +00:00
"""Removes a bookmark
actor is the person doing the bookmarking
'to' might be a specific person (actor) whose post was bookmarked
object is typically the url of the message which was bookmarked
"""
2020-09-27 19:27:24 +00:00
if not urlPermitted(objectUrl, federationList):
2019-11-17 14:01:49 +00:00
return None
2020-12-16 10:30:54 +00:00
fullDomain = getFullDomain(domain, port)
2019-11-17 14:01:49 +00:00
2020-04-01 22:22:51 +00:00
newUndoBookmarkJson = {
2019-11-17 14:01:49 +00:00
"@context": "https://www.w3.org/ns/activitystreams",
'type': 'Undo',
2021-12-25 17:09:22 +00:00
'actor': localActorUrl(http_prefix, nickname, fullDomain),
2019-11-17 14:01:49 +00:00
'object': {
'type': 'Bookmark',
2021-12-25 17:09:22 +00:00
'actor': localActorUrl(http_prefix, nickname, fullDomain),
2019-11-17 14:01:49 +00:00
'object': objectUrl
}
}
if ccList:
2020-04-01 22:22:51 +00:00
if len(ccList) > 0:
newUndoBookmarkJson['cc'] = ccList
newUndoBookmarkJson['object']['cc'] = ccList
2019-11-17 14:01:49 +00:00
# Extract the domain and nickname from a statuses link
2020-04-01 22:22:51 +00:00
bookmarkedPostNickname = None
bookmarkedPostDomain = None
bookmarkedPostPort = None
2019-11-17 14:01:49 +00:00
if actorBookmarked:
2020-04-01 22:22:51 +00:00
acBm = actorBookmarked
bookmarkedPostNickname = getNicknameFromActor(acBm)
bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(acBm)
2019-11-17 14:01:49 +00:00
else:
2020-12-23 10:57:44 +00:00
if hasUsersPath(objectUrl):
2020-04-01 22:22:51 +00:00
ou = objectUrl
bookmarkedPostNickname = getNicknameFromActor(ou)
bookmarkedPostDomain, bookmarkedPostPort = getDomainFromActor(ou)
2019-11-17 14:01:49 +00:00
if bookmarkedPostNickname:
2021-12-25 16:17:53 +00:00
postFilename = locatePost(base_dir, nickname, domain, objectUrl)
2019-11-17 14:01:49 +00:00
if not postFilename:
return None
2020-04-01 22:22:51 +00:00
undoBookmarksCollectionEntry(recentPostsCache,
2021-12-25 16:17:53 +00:00
base_dir, postFilename, objectUrl,
2020-04-01 22:22:51 +00:00
newUndoBookmarkJson['actor'],
domain, debug)
2019-11-17 14:01:49 +00:00
else:
return None
return newUndoBookmarkJson
2020-04-01 22:22:51 +00:00
2021-12-25 16:17:53 +00:00
def sendBookmarkViaServer(base_dir: str, session,
2021-03-19 22:04:57 +00:00
nickname: str, password: str,
domain: str, fromPort: int,
2021-12-25 17:09:22 +00:00
http_prefix: str, bookmarkUrl: str,
2021-03-19 22:04:57 +00:00
cachedWebfingers: {}, personCache: {},
2021-12-25 20:34:38 +00:00
debug: bool, project_version: str,
signingPrivateKeyPem: str) -> {}:
2021-03-19 22:04:57 +00:00
"""Creates a bookmark via c2s
"""
if not session:
print('WARN: No session for sendBookmarkViaServer')
return 6
domainFull = getFullDomain(domain, fromPort)
2021-12-25 17:09:22 +00:00
actor = localActorUrl(http_prefix, nickname, domainFull)
2021-03-19 22:04:57 +00:00
newBookmarkJson = {
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Add",
"actor": actor,
2021-03-20 12:20:17 +00:00
"to": [actor],
2021-03-19 22:04:57 +00:00
"object": {
"type": "Document",
2021-03-20 12:20:17 +00:00
"url": bookmarkUrl,
"to": [actor]
2021-03-19 22:04:57 +00:00
},
"target": actor + "/tlbookmarks"
}
2021-12-25 17:09:22 +00:00
handle = http_prefix + '://' + domainFull + '/@' + nickname
2021-03-19 22:04:57 +00:00
# lookup the inbox for the To handle
2021-12-25 17:09:22 +00:00
wfRequest = webfingerHandle(session, handle, http_prefix,
2021-03-19 22:04:57 +00:00
cachedWebfingers,
2021-12-25 20:34:38 +00:00
domain, project_version, debug, False,
signingPrivateKeyPem)
2021-03-19 22:04:57 +00:00
if not wfRequest:
if debug:
print('DEBUG: bookmark webfinger failed for ' + handle)
return 1
if not isinstance(wfRequest, dict):
print('WARN: bookmark webfinger for ' + handle +
' did not return a dict. ' + str(wfRequest))
return 1
postToBox = 'outbox'
# get the actor inbox for the To handle
2021-09-15 14:05:08 +00:00
originDomain = domain
(inboxUrl, pubKeyId, pubKey, fromPersonId, sharedInbox, avatarUrl,
displayName, _) = getPersonBox(signingPrivateKeyPem,
originDomain,
2021-12-25 16:17:53 +00:00
base_dir, session, wfRequest,
personCache,
2021-12-25 20:34:38 +00:00
project_version, http_prefix,
nickname, domain,
postToBox, 58391)
2021-03-19 22:04:57 +00:00
if not inboxUrl:
if debug:
print('DEBUG: bookmark no ' + postToBox +
' was found for ' + handle)
return 3
if not fromPersonId:
if debug:
print('DEBUG: bookmark no actor was found for ' + handle)
return 4
authHeader = createBasicAuthHeader(nickname, password)
headers = {
'host': domain,
'Content-type': 'application/json',
'Authorization': authHeader
}
2021-12-25 17:09:22 +00:00
postResult = postJson(http_prefix, domainFull,
2021-06-20 13:39:53 +00:00
session, newBookmarkJson, [], inboxUrl,
2021-03-21 13:17:59 +00:00
headers, 3, True)
2021-03-19 22:04:57 +00:00
if not postResult:
if debug:
print('WARN: POST bookmark failed for c2s to ' + inboxUrl)
return 5
if debug:
print('DEBUG: c2s POST bookmark success')
return newBookmarkJson
2021-03-19 22:11:45 +00:00
2021-12-25 16:17:53 +00:00
def sendUndoBookmarkViaServer(base_dir: str, session,
2021-03-19 22:11:45 +00:00
nickname: str, password: str,
domain: str, fromPort: int,
2021-12-25 17:09:22 +00:00
http_prefix: str, bookmarkUrl: str,
2021-03-19 22:11:45 +00:00
cachedWebfingers: {}, personCache: {},
2021-12-25 20:34:38 +00:00
debug: bool, project_version: str,
signingPrivateKeyPem: str) -> {}:
2021-03-19 22:11:45 +00:00
"""Removes a bookmark via c2s
"""
if not session:
print('WARN: No session for sendUndoBookmarkViaServer')
return 6
domainFull = getFullDomain(domain, fromPort)
2021-12-25 17:09:22 +00:00
actor = localActorUrl(http_prefix, nickname, domainFull)
2021-03-19 22:11:45 +00:00
newBookmarkJson = {
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Remove",
"actor": actor,
2021-03-20 14:32:25 +00:00
"to": [actor],
2021-03-19 22:11:45 +00:00
"object": {
"type": "Document",
2021-03-20 14:32:25 +00:00
"url": bookmarkUrl,
"to": [actor]
2021-03-19 22:11:45 +00:00
},
"target": actor + "/tlbookmarks"
}
2021-12-25 17:09:22 +00:00
handle = http_prefix + '://' + domainFull + '/@' + nickname
2021-03-19 22:11:45 +00:00
# lookup the inbox for the To handle
2021-12-25 17:09:22 +00:00
wfRequest = webfingerHandle(session, handle, http_prefix,
2021-03-19 22:11:45 +00:00
cachedWebfingers,
2021-12-25 20:34:38 +00:00
domain, project_version, debug, False,
signingPrivateKeyPem)
2021-03-19 22:11:45 +00:00
if not wfRequest:
if debug:
print('DEBUG: unbookmark webfinger failed for ' + handle)
return 1
if not isinstance(wfRequest, dict):
print('WARN: unbookmark webfinger for ' + handle +
' did not return a dict. ' + str(wfRequest))
return 1
postToBox = 'outbox'
# get the actor inbox for the To handle
2021-09-15 14:05:08 +00:00
originDomain = domain
(inboxUrl, pubKeyId, pubKey, fromPersonId, sharedInbox, avatarUrl,
displayName, _) = getPersonBox(signingPrivateKeyPem,
originDomain,
2021-12-25 16:17:53 +00:00
base_dir, session, wfRequest,
personCache,
2021-12-25 20:34:38 +00:00
project_version, http_prefix,
nickname, domain,
postToBox, 52594)
2021-03-19 22:11:45 +00:00
if not inboxUrl:
if debug:
print('DEBUG: unbookmark no ' + postToBox +
' was found for ' + handle)
return 3
if not fromPersonId:
if debug:
print('DEBUG: unbookmark no actor was found for ' + handle)
return 4
authHeader = createBasicAuthHeader(nickname, password)
headers = {
'host': domain,
'Content-type': 'application/json',
'Authorization': authHeader
}
2021-12-25 17:09:22 +00:00
postResult = postJson(http_prefix, domainFull,
2021-06-20 13:39:53 +00:00
session, newBookmarkJson, [], inboxUrl,
2021-03-21 13:17:59 +00:00
headers, 3, True)
2021-03-19 22:11:45 +00:00
if not postResult:
if debug:
print('WARN: POST unbookmark failed for c2s to ' + inboxUrl)
return 5
if debug:
print('DEBUG: c2s POST unbookmark success')
return newBookmarkJson
2021-03-20 09:49:43 +00:00
def outboxBookmark(recentPostsCache: {},
2021-12-25 17:09:22 +00:00
base_dir: str, http_prefix: str,
2021-03-20 09:49:43 +00:00
nickname: str, domain: str, port: int,
messageJson: {}, debug: bool) -> None:
""" When a bookmark request is received by the outbox from c2s
"""
if not messageJson.get('type'):
return
2021-03-20 14:09:07 +00:00
if messageJson['type'] != 'Add':
2021-03-20 09:49:43 +00:00
return
if not hasActor(messageJson, debug):
2021-03-20 09:49:43 +00:00
return
if not messageJson.get('target'):
if debug:
print('DEBUG: no target in bookmark Add')
return
2021-10-13 10:11:02 +00:00
if not hasObjectStringType(messageJson, debug):
2021-03-20 09:49:43 +00:00
return
if not isinstance(messageJson['target'], str):
if debug:
print('DEBUG: bookmark Add target is not string')
return
domainFull = getFullDomain(domain, port)
if not messageJson['target'].endswith('://' + domainFull +
'/users/' + nickname +
'/tlbookmarks'):
if debug:
print('DEBUG: bookmark Add target invalid ' +
messageJson['target'])
return
if messageJson['object']['type'] != 'Document':
if debug:
print('DEBUG: bookmark Add type is not Document')
return
if not messageJson['object'].get('url'):
if debug:
print('DEBUG: bookmark Add missing url')
return
if debug:
print('DEBUG: c2s bookmark Add request arrived in outbox')
messageUrl = removeIdEnding(messageJson['object']['url'])
domain = removeDomainPort(domain)
2021-12-25 16:17:53 +00:00
postFilename = locatePost(base_dir, nickname, domain, messageUrl)
2021-03-20 09:49:43 +00:00
if not postFilename:
if debug:
print('DEBUG: c2s like post not found in inbox or outbox')
print(messageUrl)
return True
updateBookmarksCollection(recentPostsCache,
2021-12-25 16:17:53 +00:00
base_dir, postFilename, messageUrl,
2021-03-20 09:49:43 +00:00
messageJson['actor'], domain, debug)
if debug:
print('DEBUG: post bookmarked via c2s - ' + postFilename)
def outboxUndoBookmark(recentPostsCache: {},
2021-12-25 17:09:22 +00:00
base_dir: str, http_prefix: str,
2021-03-20 09:49:43 +00:00
nickname: str, domain: str, port: int,
messageJson: {}, debug: bool) -> None:
""" When an undo bookmark request is received by the outbox from c2s
"""
if not messageJson.get('type'):
return
2021-03-20 14:09:07 +00:00
if messageJson['type'] != 'Remove':
2021-03-20 09:49:43 +00:00
return
if not hasActor(messageJson, debug):
2021-03-20 09:49:43 +00:00
return
if not messageJson.get('target'):
if debug:
print('DEBUG: no target in unbookmark Remove')
return
2021-10-13 10:11:02 +00:00
if not hasObjectStringType(messageJson, debug):
2021-03-20 09:49:43 +00:00
return
if not isinstance(messageJson['target'], str):
if debug:
print('DEBUG: unbookmark Remove target is not string')
return
domainFull = getFullDomain(domain, port)
if not messageJson['target'].endswith('://' + domainFull +
'/users/' + nickname +
'/tlbookmarks'):
if debug:
print('DEBUG: unbookmark Remove target invalid ' +
messageJson['target'])
return
if messageJson['object']['type'] != 'Document':
if debug:
print('DEBUG: unbookmark Remove type is not Document')
return
if not messageJson['object'].get('url'):
if debug:
print('DEBUG: unbookmark Remove missing url')
return
if debug:
print('DEBUG: c2s unbookmark Remove request arrived in outbox')
messageUrl = removeIdEnding(messageJson['object']['url'])
domain = removeDomainPort(domain)
2021-12-25 16:17:53 +00:00
postFilename = locatePost(base_dir, nickname, domain, messageUrl)
2021-03-20 09:49:43 +00:00
if not postFilename:
if debug:
print('DEBUG: c2s unbookmark post not found in inbox or outbox')
print(messageUrl)
return True
updateBookmarksCollection(recentPostsCache,
2021-12-25 16:17:53 +00:00
base_dir, postFilename, messageUrl,
2021-03-20 09:49:43 +00:00
messageJson['actor'], domain, debug)
if debug:
print('DEBUG: post unbookmarked via c2s - ' + postFilename)