skills.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. __filename__ = "skills.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 commentjson
  10. import os
  11. import time
  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 setSkillLevel(baseDir: str,nickname: str,domain: str, \
  21. skill: str,skillLevelPercent: int) -> bool:
  22. """Set a skill level for a person
  23. Setting skill level to zero removes it
  24. """
  25. if skillLevelPercent<0 or skillLevelPercent>100:
  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. if not actorJson.get('skills'):
  33. actorJson['skills']={}
  34. if skillLevelPercent>0:
  35. actorJson['skills'][skill]=skillLevelPercent
  36. else:
  37. del actorJson['skills'][skill]
  38. saveJson(actorJson,actorFilename)
  39. return True
  40. def setSkills(baseDir: str,nickname: str,domain: str,skills: {}) -> None:
  41. actorFilename=baseDir+'/accounts/'+nickname+'@'+domain+'.json'
  42. if not os.path.isfile(actorFilename):
  43. return False
  44. actorJson=loadJson(actorFilename)
  45. if actorJson:
  46. actorJson['skills']=skills
  47. saveJson(actorJson,actorFilename)
  48. def getSkills(baseDir: str,nickname: str,domain: str) -> []:
  49. """Returns the skills for a given person
  50. """
  51. actorFilename=baseDir+'/accounts/'+nickname+'@'+domain+'.json'
  52. if not os.path.isfile(actorFilename):
  53. return False
  54. actorJson=loadJson(actorFilename)
  55. if actorJson:
  56. if not actorJson.get('skills'):
  57. return None
  58. return actorJson['skills']
  59. return None
  60. def outboxSkills(baseDir: str,nickname: str,messageJson: {},debug: bool) -> bool:
  61. """Handles receiving a skills update
  62. """
  63. if not messageJson.get('type'):
  64. return False
  65. if not messageJson['type']=='Skill':
  66. return False
  67. if not messageJson.get('actor'):
  68. return False
  69. if not messageJson.get('object'):
  70. return False
  71. if not isinstance(messageJson['object'], str):
  72. return False
  73. actorNickname=getNicknameFromActor(messageJson['actor'])
  74. if actorNickname!=nickname:
  75. return False
  76. domain,port=getDomainFromActor(messageJson['actor'])
  77. skill=messageJson['object'].replace('"','').split(';')[0].strip()
  78. skillLevelPercent=int(messageJson['object'].replace('"','').split(';')[1].strip())
  79. return setSkillLevel(baseDir,nickname,domain, \
  80. skill,skillLevelPercent)
  81. def sendSkillViaServer(baseDir: str,session,nickname: str,password: str,
  82. domain: str,port: int, \
  83. httpPrefix: str, \
  84. skill: str,skillLevelPercent: int, \
  85. cachedWebfingers: {},personCache: {}, \
  86. debug: bool,projectVersion: str) -> {}:
  87. """Sets a skill for a person via c2s
  88. """
  89. if not session:
  90. print('WARN: No session for sendSkillViaServer')
  91. return 6
  92. domainFull=domain
  93. if port:
  94. if port!=80 and port!=443:
  95. if ':' not in domain:
  96. domainFull=domain+':'+str(port)
  97. toUrl = httpPrefix+'://'+domainFull+'/users/'+nickname
  98. ccUrl = httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers'
  99. if skillLevelPercent:
  100. skillStr=skill+';'+str(skillLevelPercent)
  101. else:
  102. skillStr=skill+';0'
  103. newSkillJson = {
  104. 'type': 'Skill',
  105. 'actor': httpPrefix+'://'+domainFull+'/users/'+nickname,
  106. 'object': '"'+skillStr+'"',
  107. 'to': [toUrl],
  108. 'cc': [ccUrl]
  109. }
  110. handle=httpPrefix+'://'+domainFull+'/@'+nickname
  111. # lookup the inbox for the To handle
  112. wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \
  113. domain,projectVersion)
  114. if not wfRequest:
  115. if debug:
  116. print('DEBUG: announce webfinger failed for '+handle)
  117. return 1
  118. postToBox='outbox'
  119. # get the actor inbox for the To handle
  120. inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName = \
  121. getPersonBox(baseDir,session,wfRequest,personCache, \
  122. projectVersion,httpPrefix,nickname,domain,postToBox)
  123. if not inboxUrl:
  124. if debug:
  125. print('DEBUG: No '+postToBox+' was found for '+handle)
  126. return 3
  127. if not fromPersonId:
  128. if debug:
  129. print('DEBUG: No actor was found for '+handle)
  130. return 4
  131. authHeader=createBasicAuthHeader(Nickname,password)
  132. headers = {'host': domain, \
  133. 'Content-type': 'application/json', \
  134. 'Authorization': authHeader}
  135. postResult = \
  136. postJson(session,newSkillJson,[],inboxUrl,headers,"inbox:write")
  137. #if not postResult:
  138. # if debug:
  139. # print('DEBUG: POST announce failed for c2s to '+inboxUrl)
  140. # return 5
  141. if debug:
  142. print('DEBUG: c2s POST skill success')
  143. return newSkillJson