epicyon/availability.py

161 lines
5.2 KiB
Python

__filename__ = "availability.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@libreserver.org"
__status__ = "Production"
__module_group__ = "Profile Metadata"
import os
from webfinger import webfingerHandle
from auth import createBasicAuthHeader
from posts import getPersonBox
from session import postJson
from utils import hasObjectString
from utils import getFullDomain
from utils import getNicknameFromActor
from utils import getDomainFromActor
from utils import loadJson
from utils import saveJson
from utils import acctDir
from utils import local_actor_url
from utils import hasActor
def setAvailability(base_dir: str, nickname: str, domain: str,
status: str) -> bool:
"""Set an availability status
"""
# avoid giant strings
if len(status) > 128:
return False
actorFilename = acctDir(base_dir, nickname, domain) + '.json'
if not os.path.isfile(actorFilename):
return False
actor_json = loadJson(actorFilename)
if actor_json:
actor_json['availability'] = status
saveJson(actor_json, actorFilename)
return True
def getAvailability(base_dir: str, nickname: str, domain: str) -> str:
"""Returns the availability for a given person
"""
actorFilename = acctDir(base_dir, nickname, domain) + '.json'
if not os.path.isfile(actorFilename):
return False
actor_json = loadJson(actorFilename)
if actor_json:
if not actor_json.get('availability'):
return None
return actor_json['availability']
return None
def outboxAvailability(base_dir: str, nickname: str, message_json: {},
debug: bool) -> bool:
"""Handles receiving an availability update
"""
if not message_json.get('type'):
return False
if not message_json['type'] == 'Availability':
return False
if not hasActor(message_json, debug):
return False
if not hasObjectString(message_json, debug):
return False
actorNickname = getNicknameFromActor(message_json['actor'])
if actorNickname != nickname:
return False
domain, port = getDomainFromActor(message_json['actor'])
status = message_json['object'].replace('"', '')
return setAvailability(base_dir, nickname, domain, status)
def sendAvailabilityViaServer(base_dir: str, session,
nickname: str, password: str,
domain: str, port: int,
http_prefix: str,
status: str,
cached_webfingers: {}, person_cache: {},
debug: bool, project_version: str,
signing_priv_key_pem: str) -> {}:
"""Sets the availability for a person via c2s
"""
if not session:
print('WARN: No session for sendAvailabilityViaServer')
return 6
domain_full = getFullDomain(domain, port)
toUrl = local_actor_url(http_prefix, nickname, domain_full)
ccUrl = toUrl + '/followers'
newAvailabilityJson = {
'type': 'Availability',
'actor': toUrl,
'object': '"' + status + '"',
'to': [toUrl],
'cc': [ccUrl]
}
handle = http_prefix + '://' + domain_full + '/@' + nickname
# lookup the inbox for the To handle
wfRequest = webfingerHandle(session, handle, http_prefix,
cached_webfingers,
domain, project_version, debug, False,
signing_priv_key_pem)
if not wfRequest:
if debug:
print('DEBUG: availability webfinger failed for ' + handle)
return 1
if not isinstance(wfRequest, dict):
print('WARN: availability webfinger for ' + handle +
' did not return a dict. ' + str(wfRequest))
return 1
postToBox = 'outbox'
# get the actor inbox for the To handle
originDomain = domain
(inboxUrl, pubKeyId, pubKey, fromPersonId, sharedInbox, avatarUrl,
displayName, _) = getPersonBox(signing_priv_key_pem,
originDomain,
base_dir, session, wfRequest,
person_cache, project_version,
http_prefix, nickname,
domain, postToBox, 57262)
if not inboxUrl:
if debug:
print('DEBUG: availability no ' + postToBox +
' was found for ' + handle)
return 3
if not fromPersonId:
if debug:
print('DEBUG: availability no actor was found for ' + handle)
return 4
authHeader = createBasicAuthHeader(nickname, password)
headers = {
'host': domain,
'Content-type': 'application/json',
'Authorization': authHeader
}
postResult = postJson(http_prefix, domain_full,
session, newAvailabilityJson, [],
inboxUrl, headers, 30, True)
if not postResult:
print('WARN: availability failed to post')
if debug:
print('DEBUG: c2s POST availability success')
return newAvailabilityJson