Setting availability via c2s

master
Bob Mottram 2019-07-19 12:38:37 +01:00
parent 6b484251cb
commit 81b0207c2a
5 changed files with 173 additions and 32 deletions

137
availability.py 100644
View File

@ -0,0 +1,137 @@
__filename__ = "availability.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "0.0.1"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
import json
import commentjson
import os
from webfinger import webfingerHandle
from auth import createBasicAuthHeader
from posts import getPersonBox
from session import postJson
from utils import getNicknameFromActor
from utils import getDomainFromActor
def setAvailability(baseDir: str,nickname: str,domain: str, \
status: str) -> bool:
"""Set an availability status
"""
# avoid giant strings
if len(status)>128:
return False
actorFilename=baseDir+'/accounts/'+nickname+'@'+domain+'.json'
if not os.path.isfile(actorFilename):
return False
with open(actorFilename, 'r') as fp:
actorJson=commentjson.load(fp)
actorJson['availability']=status
with open(actorFilename, 'w') as fp:
commentjson.dump(actorJson, fp, indent=4, sort_keys=False)
return True
def getAvailability(baseDir: str,nickname: str,domain: str) -> str:
"""Returns the availability for a given person
"""
actorFilename=baseDir+'/accounts/'+nickname+'@'+domain+'.json'
if not os.path.isfile(actorFilename):
return False
with open(actorFilename, 'r') as fp:
actorJson=commentjson.load(fp)
if not actorJson.get('availability'):
return None
return actorJson['availability']
return None
def outboxAvailability(baseDir: str,nickname: str,messageJson: {},debug: bool) -> bool:
"""Handles receiving an availability update
"""
if not messageJson.get('type'):
return False
if not messageJson['type']=='Availability':
return False
if not messageJson.get('actor'):
return False
if not messageJson.get('object'):
return False
if not isinstance(messageJson['object'], str):
return False
actorNickname=getNicknameFromActor(messageJson['actor'])
if actorNickname!=nickname:
return False
domain,port=getDomainFromActor(messageJson['actor'])
status=messageJson['object'].replace('"','')
return setAvailability(baseDir,nickname,domain,status)
def sendAvailabilityViaServer(session,nickname: str,password: str,
domain: str,port: int, \
httpPrefix: str, \
status: str, \
cachedWebfingers: {},personCache: {}, \
debug: bool) -> {}:
"""Sets the availability for a person via c2s
"""
if not session:
print('WARN: No session for sendAvailabilityViaServer')
return 6
domainFull=domain
if port!=80 and port!=443:
domainFull=domain+':'+str(port)
toUrl = httpPrefix+'://'+domainFull+'/users/'+nickname
ccUrl = httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers'
newAvailabilityJson = {
'type': 'Availability',
'actor': httpPrefix+'://'+domainFull+'/users/'+nickname,
'object': '"'+status+'"',
'to': [toUrl],
'cc': [ccUrl]
}
handle=httpPrefix+'://'+domainFull+'/@'+nickname
# lookup the inbox for the To handle
wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers)
if not wfRequest:
if debug:
print('DEBUG: announce webfinger failed for '+handle)
return 1
postToBox='outbox'
# get the actor inbox for the To handle
inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition = \
getPersonBox(session,wfRequest,personCache,postToBox)
if not inboxUrl:
if debug:
print('DEBUG: No '+postToBox+' was found for '+handle)
return 3
if not fromPersonId:
if debug:
print('DEBUG: No actor was found for '+handle)
return 4
authHeader=createBasicAuthHeader(Nickname,password)
headers = {'host': domain, \
'Content-type': 'application/json', \
'Authorization': authHeader}
postResult = \
postJson(session,newAvailabilityJson,[],inboxUrl,headers,"inbox:write")
#if not postResult:
# if debug:
# print('DEBUG: POST announce failed for c2s to '+inboxUrl)
# return 5
if debug:
print('DEBUG: c2s POST availability success')
return newAvailabilityJson

View File

@ -43,6 +43,7 @@ from blocking import outboxUndoBlock
from config import setConfigParam
from roles import outboxDelegate
from skills import outboxSkills
from availability import outboxAvailability
import os
import sys
@ -225,8 +226,11 @@ class PubServer(BaseHTTPRequestHandler):
print('DEBUG: handle delegation requests')
outboxDelegate(self.server.baseDir,self.postToNickname,messageJson,self.server.debug)
if self.server.debug:
print('DEBUG: handle skills changes requestsw')
print('DEBUG: handle skills changes requests')
outboxSkills(self.server.baseDir,self.postToNickname,messageJson,self.server.debug)
if self.server.debug:
print('DEBUG: handle availability changes requests')
outboxAvailability(self.server.baseDir,self.postToNickname,messageJson,self.server.debug)
if self.server.debug:
print('DEBUG: handle any like requests')
outboxLike(self.server.baseDir,self.server.httpPrefix, \

View File

@ -6,7 +6,6 @@ __maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
from person import createPerson
from person import createSharedInbox
from person import createCapabilitiesInbox
@ -16,7 +15,6 @@ from person import validNickname
from person import setProfileImage
from skills import setSkillLevel
from roles import setRole
from person import setAvailability
from person import setOrganizationScheme
from webfinger import webfingerHandle
from posts import getPosts
@ -69,6 +67,8 @@ from blocking import sendBlockViaServer
from blocking import sendUndoBlockViaServer
from roles import sendRoleViaServer
from skills import sendSkillViaServer
from availability import setAvailability
from availability import sendAvailabilityViaServer
import argparse
def str2bool(v):
@ -727,14 +727,6 @@ if args.backgroundImage:
print('Background image was not added for '+args.nickname)
sys.exit()
if args.availability:
if not nickname:
print('No nickname given')
sys.exit()
if setAvailability(baseDir,nickname,domain,args.availability):
print('Availablity set to '+args.availability)
sys.exit()
if args.project:
if not args.delegate and not args.undelegate:
if not nickname:
@ -786,6 +778,31 @@ if args.skill:
time.sleep(1)
sys.exit()
if args.availability:
if not nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
session = createSession(domain,port,useTor)
personCache={}
cachedWebfingers={}
print('Sending availability status of '+nickname+' as '+args.availability)
sendAvailabilityViaServer(session,nickname,args.password,
domain,port, \
httpPrefix, \
args.availability, \
cachedWebfingers,personCache, \
True)
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
if federationList:
print('Federating with: '+str(federationList))

View File

@ -106,23 +106,6 @@ def setOrganizationScheme(baseDir: str,nickname: str,domain: str, \
commentjson.dump(actorJson, fp, indent=4, sort_keys=False)
return True
def setAvailability(baseDir: str,nickname: str,domain: str, \
status: str) -> bool:
"""Set an availability status
"""
# avoid giant strings
if len(status)>128:
return False
actorFilename=baseDir+'/accounts/'+nickname+'@'+domain+'.json'
if not os.path.isfile(actorFilename):
return False
with open(actorFilename, 'r') as fp:
actorJson=commentjson.load(fp)
actorJson['availability']=status
with open(actorFilename, 'w') as fp:
commentjson.dump(actorJson, fp, indent=4, sort_keys=False)
return True
def createPersonBase(baseDir: str,nickname: str,domain: str,port: int, \
httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}):
"""Returns the private key, public key, actor and webfinger endpoint

View File

@ -69,8 +69,8 @@ def outboxSkills(baseDir: str,nickname: str,messageJson: {},debug: bool) -> bool
if actorNickname!=nickname:
return False
domain,port=getDomainFromActor(messageJson['actor'])
skill=messageJson['object'].split(';')[0].strip()
skillLevelPercent=messageJson['object'].split(';')[1].strip()
skill=messageJson['object'].replace('"','').split(';')[0].strip()
skillLevelPercent=int(messageJson['object'].replace('"','').split(';')[1].strip())
return setSkillLevel(baseDir,nickname,domain, \
skill,skillLevelPercent)
@ -92,7 +92,7 @@ def sendSkillViaServer(session,nickname: str,password: str,
domainFull=domain+':'+str(port)
toUrl = httpPrefix+'://'+domainFull+'/users/'+nickname
ccUrl = httpPrefix+'://'+domainFull+'/users/'+Nickname+'/followers'
ccUrl = httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers'
if skillLevelPercent:
skillStr=skill+';'+str(skillLevelPercent)
@ -101,7 +101,7 @@ def sendSkillViaServer(session,nickname: str,password: str,
newSkillJson = {
'type': 'Skill',
'actor': httpPrefix+'://'+domainFull+'/users/'+nickname,
'object': skill+';'+str(skillLevelPercent),
'object': '"'+skillStr+'"',
'to': [toUrl],
'cc': [ccUrl]
}