availability.py 4.5 KB

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