availability.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. __filename__ = "availability.py"
  2. __author__ = "Bob Mottram"
  3. __license__ = "AGPL3+"
  4. __version__ = "1.0.0"
  5. __maintainer__ = "Bob Mottram"
  6. __email__ = "bob@freedombone.net"
  7. __status__ = "Production"
  8. import json
  9. import time
  10. import os
  11. from webfinger import webfingerHandle
  12. from auth import createBasicAuthHeader
  13. from posts import getPersonBox
  14. from session import postJson
  15. from utils import getNicknameFromActor
  16. from utils import getDomainFromActor
  17. from utils import loadJson
  18. from utils import saveJson
  19. def setAvailability(baseDir: str,nickname: str,domain: str, \
  20. status: str) -> bool:
  21. """Set an availability status
  22. """
  23. # avoid giant strings
  24. if len(status)>128:
  25. return False
  26. actorFilename=baseDir+'/accounts/'+nickname+'@'+domain+'.json'
  27. if not os.path.isfile(actorFilename):
  28. return False
  29. actorJson=loadJson(actorFilename)
  30. if actorJson:
  31. actorJson['availability']=status
  32. saveJson(actorJson,actorFilename)
  33. return True
  34. def getAvailability(baseDir: str,nickname: str,domain: str) -> str:
  35. """Returns the availability for a given person
  36. """
  37. actorFilename=baseDir+'/accounts/'+nickname+'@'+domain+'.json'
  38. if not os.path.isfile(actorFilename):
  39. return False
  40. actorJson=loadJson(actorFilename)
  41. if actorJson:
  42. if not actorJson.get('availability'):
  43. return None
  44. return actorJson['availability']
  45. return None
  46. def outboxAvailability(baseDir: str,nickname: str,messageJson: {}, \
  47. debug: bool) -> bool:
  48. """Handles receiving an availability update
  49. """
  50. if not messageJson.get('type'):
  51. return False
  52. if not messageJson['type']=='Availability':
  53. return False
  54. if not messageJson.get('actor'):
  55. return False
  56. if not messageJson.get('object'):
  57. return False
  58. if not isinstance(messageJson['object'], str):
  59. return False
  60. actorNickname=getNicknameFromActor(messageJson['actor'])
  61. if actorNickname!=nickname:
  62. return False
  63. domain,port=getDomainFromActor(messageJson['actor'])
  64. status=messageJson['object'].replace('"','')
  65. return setAvailability(baseDir,nickname,domain,status)
  66. def sendAvailabilityViaServer(baseDir: str,session, \
  67. nickname: str,password: str, \
  68. domain: str,port: int, \
  69. httpPrefix: str, \
  70. status: str, \
  71. cachedWebfingers: {},personCache: {}, \
  72. debug: bool,projectVersion: str) -> {}:
  73. """Sets the availability for a person via c2s
  74. """
  75. if not session:
  76. print('WARN: No session for sendAvailabilityViaServer')
  77. return 6
  78. domainFull=domain
  79. if port:
  80. if port!=80 and port!=443:
  81. if ':' not in domain:
  82. domainFull=domain+':'+str(port)
  83. toUrl = httpPrefix+'://'+domainFull+'/users/'+nickname
  84. ccUrl = httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers'
  85. newAvailabilityJson = {
  86. 'type': 'Availability',
  87. 'actor': httpPrefix+'://'+domainFull+'/users/'+nickname,
  88. 'object': '"'+status+'"',
  89. 'to': [toUrl],
  90. 'cc': [ccUrl]
  91. }
  92. handle=httpPrefix+'://'+domainFull+'/@'+nickname
  93. # lookup the inbox for the To handle
  94. wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \
  95. domain,projectVersion)
  96. if not wfRequest:
  97. if debug:
  98. print('DEBUG: announce webfinger failed for '+handle)
  99. return 1
  100. postToBox='outbox'
  101. # get the actor inbox for the To handle
  102. inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \
  103. getPersonBox(baseDir,session,wfRequest,personCache, \
  104. projectVersion,httpPrefix,nickname,domain,postToBox)
  105. if not inboxUrl:
  106. if debug:
  107. print('DEBUG: No '+postToBox+' was found for '+handle)
  108. return 3
  109. if not fromPersonId:
  110. if debug:
  111. print('DEBUG: No actor was found for '+handle)
  112. return 4
  113. authHeader=createBasicAuthHeader(Nickname,password)
  114. headers = {'host': domain, \
  115. 'Content-type': 'application/json', \
  116. 'Authorization': authHeader}
  117. postResult = \
  118. postJson(session,newAvailabilityJson,[],inboxUrl,headers,"inbox:write")
  119. if debug:
  120. print('DEBUG: c2s POST availability success')
  121. return newAvailabilityJson