More standards compliant representation of skills

merge-requests/30/head
Bob Mottram 2021-05-13 14:27:35 +01:00
parent ccd02acfeb
commit 0cc86dc131
5 changed files with 132 additions and 45 deletions

View File

@ -98,6 +98,11 @@ from follow import getFollowingFeed
from follow import sendFollowRequest from follow import sendFollowRequest
from follow import unfollowAccount from follow import unfollowAccount
from follow import createInitialLastSeen from follow import createInitialLastSeen
from skills import getSkillsFromString
from skills import noOfActorSkills
from skills import actorHasSkill
from skills import actorSkillValue
from skills import setActorSkillLevel
from auth import authorize from auth import authorize
from auth import createPassword from auth import createPassword
from auth import createBasicAuthHeader from auth import createBasicAuthHeader
@ -4191,7 +4196,7 @@ class PubServer(BaseHTTPRequestHandler):
# set skill levels # set skill levels
skillCtr = 1 skillCtr = 1
newSkills = {} actorSkillsCtr = noOfActorSkills(actorJson)
while skillCtr < 10: while skillCtr < 10:
skillName = \ skillName = \
fields.get('skillName' + str(skillCtr)) fields.get('skillName' + str(skillCtr))
@ -4206,21 +4211,20 @@ class PubServer(BaseHTTPRequestHandler):
if not skillValue: if not skillValue:
skillCtr += 1 skillCtr += 1
continue continue
if not actorJson['skills'].get(skillName): if not actorHasSkill(actorJson, skillName):
actorChanged = True actorChanged = True
else: else:
if actorJson['skills'][skillName] != \ if actorSkillValue(actorJson, skillName) != \
int(skillValue): int(skillValue):
actorChanged = True actorChanged = True
newSkills[skillName] = int(skillValue) setActorSkillLevel(actorJson, skillName, skillValue)
skillsStr = self.server.translate['Skills'] skillsStr = self.server.translate['Skills']
setHashtagCategory(baseDir, skillName, setHashtagCategory(baseDir, skillName,
skillsStr.lower()) skillsStr.lower())
skillCtr += 1 skillCtr += 1
if len(actorJson['skills'].items()) != \ if noOfActorSkills(actorJson) != \
len(newSkills.items()): actorSkillsCtr:
actorChanged = True actorChanged = True
actorJson['skills'] = newSkills
# change password # change password
if fields.get('password'): if fields.get('password'):
@ -7461,7 +7465,7 @@ class PubServer(BaseHTTPRequestHandler):
if os.path.isfile(actorFilename): if os.path.isfile(actorFilename):
actorJson = loadJson(actorFilename) actorJson = loadJson(actorFilename)
if actorJson: if actorJson:
if actorJson.get('skills'): if noOfActorSkills(actorJson) > 0:
if self._requestHTTP(): if self._requestHTTP():
getPerson = \ getPerson = \
personLookup(domain, personLookup(domain,
@ -7486,6 +7490,9 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.keyShortcuts.get(nickname): if self.server.keyShortcuts.get(nickname):
accessKeys = \ accessKeys = \
self.server.keyShortcuts[nickname] self.server.keyShortcuts[nickname]
actorSkillsStr = \
actorJson['hasOccupation']['skills']
skills = getSkillsFromString(actorSkillsStr)
msg = \ msg = \
htmlProfile(self.server.rssIconAtTop, htmlProfile(self.server.rssIconAtTop,
self.server.cssCache, self.server.cssCache,
@ -7509,8 +7516,7 @@ class PubServer(BaseHTTPRequestHandler):
allowLocalNetworkAccess, allowLocalNetworkAccess,
self.server.textModeBanner, self.server.textModeBanner,
self.server.debug, self.server.debug,
accessKeys, accessKeys, skills,
actorJson['skills'],
None, None) None, None)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
msglen = len(msg) msglen = len(msg)
@ -7523,7 +7529,10 @@ class PubServer(BaseHTTPRequestHandler):
'show skills') 'show skills')
else: else:
if self._fetchAuthenticated(): if self._fetchAuthenticated():
msg = json.dumps(actorJson['skills'], actorSkillsStr = \
actorJson['hasOccupation']['skills']
skills = getSkillsFromString(actorSkillsStr)
msg = json.dumps(skills,
ensure_ascii=False) ensure_ascii=False)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
msglen = len(msg) msglen = len(msg)

View File

@ -279,9 +279,8 @@ def _createPersonBase(baseDir: str, nickname: str, domain: str, port: int,
'hasOccupation': { 'hasOccupation': {
'@type': 'Occupation', '@type': 'Occupation',
'name': "", 'name': "",
'skills': "", 'skills': ""
}, },
'skills': {},
'roles': {}, 'roles': {},
'availability': None, 'availability': None,
'icon': { 'icon': {
@ -317,7 +316,8 @@ def _createPersonBase(baseDir: str, nickname: str, domain: str, port: int,
del newPerson['outbox'] del newPerson['outbox']
del newPerson['icon'] del newPerson['icon']
del newPerson['image'] del newPerson['image']
del newPerson['skills'] if newPerson.get('skills'):
del newPerson['skills']
del newPerson['shares'] del newPerson['shares']
del newPerson['roles'] del newPerson['roles']
del newPerson['tag'] del newPerson['tag']
@ -574,10 +574,14 @@ def personUpgradeActor(baseDir: str, personJson: {},
personJson['hasOccupation'] = { personJson['hasOccupation'] = {
'@type': 'Occupation', '@type': 'Occupation',
'name': occupationName, 'name': occupationName,
'skills': "", 'skills': ""
} }
updateActor = True updateActor = True
if personJson.get('skills'):
del personJson['skills']
updateActor = True
if updateActor: if updateActor:
personJson['@context'] = [ personJson['@context'] = [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',

101
skills.py
View File

@ -15,7 +15,89 @@ from utils import getFullDomain
from utils import getNicknameFromActor from utils import getNicknameFromActor
from utils import getDomainFromActor from utils import getDomainFromActor
from utils import loadJson from utils import loadJson
from utils import saveJson
def _setSkillsFromDict(actorJson: {}, skills: {}) -> None:
"""Converts a dict containing skills to a string
"""
skillsStr = ''
for name, value in skills.items():
if skillsStr:
skillsStr += ', '
skillsStr += name + ':' + str(value)
return skillsStr
def getSkillsFromString(skillsStr: str) -> {}:
"""Returns a dict of skills from a string
"""
skillsList = skillsStr.split(',')
skills = {}
for skill in skillsList:
if ':' not in skill:
continue
name = skill.split(':')[0].strip().lower()
valueStr = skill.split(':')[1]
if not valueStr.isdigit():
continue
skills[name] = int(valueStr)
return skills
def actorHasSkill(actorJson: {}, skillName: str) -> bool:
"""Returns true if the actor has the given skill
"""
skills = getSkillsFromString(actorJson['hasOccupation']['skills'])
if not skills:
return False
return skills.get(skillName.lower())
def actorSkillValue(actorJson: {}, skillName: str) -> int:
"""Returns The skill level from an actor
"""
skills = getSkillsFromString(actorJson['hasOccupation']['skills'])
if not skills:
return 0
skillName = skillName.lower()
if skills.get(skillName):
return skills[skillName]
return 0
def noOfActorSkills(actorJson: {}) -> int:
"""Returns the number of skills that an actor has
"""
if actorJson.get('hasOccupation'):
skillsList = actorJson['hasOccupation']['skills'].split(',')
if skillsList:
return int(skillsList)
return 0
def setActorSkillLevel(actorJson: {},
skill: str, skillLevelPercent: int) -> bool:
"""Set a skill level for a person
Setting skill level to zero removes it
"""
if skillLevelPercent < 0 or skillLevelPercent > 100:
return False
if actorJson:
if not actorJson.get('hasOccupation'):
actorJson['hasOccupation'] = {
'@type': 'Occupation',
'name': '',
'skills': ''
}
skills = getSkillsFromString(actorJson['hasOccupation']['skills'])
if skillLevelPercent > 0:
skills[skill] = skillLevelPercent
else:
if skills.get(skill):
del skills[skill]
_setSkillsFromDict(actorJson, skills)
return True
def setSkillLevel(baseDir: str, nickname: str, domain: str, def setSkillLevel(baseDir: str, nickname: str, domain: str,
@ -30,15 +112,8 @@ def setSkillLevel(baseDir: str, nickname: str, domain: str,
return False return False
actorJson = loadJson(actorFilename) actorJson = loadJson(actorFilename)
if actorJson: return setActorSkillLevel(actorJson,
if not actorJson.get('skills'): skill, skillLevelPercent)
actorJson['skills'] = {}
if skillLevelPercent > 0:
actorJson['skills'][skill] = skillLevelPercent
else:
del actorJson['skills'][skill]
saveJson(actorJson, actorFilename)
return True
def getSkills(baseDir: str, nickname: str, domain: str) -> []: def getSkills(baseDir: str, nickname: str, domain: str) -> []:
@ -50,9 +125,9 @@ def getSkills(baseDir: str, nickname: str, domain: str) -> []:
actorJson = loadJson(actorFilename) actorJson = loadJson(actorFilename)
if actorJson: if actorJson:
if not actorJson.get('skills'): if not actorJson.get('hasOccupation'):
return None return None
return actorJson['skills'] return getSkillsFromString(actorJson['hasOccupation']['skills'])
return None return None
@ -112,7 +187,7 @@ def sendSkillViaServer(baseDir: str, session, nickname: str, password: str,
newSkillJson = { newSkillJson = {
'type': 'Skill', 'type': 'Skill',
'actor': actor, 'actor': actor,
'object': '"'+skillStr+'"', 'object': '"' + skillStr + '"',
'to': [toUrl], 'to': [toUrl],
'cc': [ccUrl] 'cc': [ccUrl]
} }

View File

@ -20,6 +20,8 @@ from utils import locatePost
from utils import isPublicPost from utils import isPublicPost
from utils import firstParagraphFromString from utils import firstParagraphFromString
from utils import searchBoxPosts from utils import searchBoxPosts
from skills import noOfActorSkills
from skills import getSkillsFromString
from categories import getHashtagCategory from categories import getHashtagCategory
from feeds import rss2TagHeader from feeds import rss2TagHeader
from feeds import rss2TagFooter from feeds import rss2TagFooter
@ -414,11 +416,13 @@ def htmlSkillsSearch(actor: str,
actorJson = loadJson(actorFilename) actorJson = loadJson(actorFilename)
if actorJson: if actorJson:
if actorJson.get('id') and \ if actorJson.get('id') and \
actorJson.get('skills') and \ noOfActorSkills(actorJson) > 0 and \
actorJson.get('name') and \ actorJson.get('name') and \
actorJson.get('icon'): actorJson.get('icon'):
actor = actorJson['id'] actor = actorJson['id']
for skillName, skillLevel in actorJson['skills'].items(): actorSkillsStr = actorJson['hasOccupation']['skills']
skills = getSkillsFromString(actorSkillsStr)
for skillName, skillLevel in skills.items():
skillName = skillName.lower() skillName = skillName.lower()
if not (skillName in skillsearch or if not (skillName in skillsearch or
skillsearch in skillName): skillsearch in skillName):
@ -453,12 +457,14 @@ def htmlSkillsSearch(actor: str,
if cachedActorJson.get('actor'): if cachedActorJson.get('actor'):
actorJson = cachedActorJson['actor'] actorJson = cachedActorJson['actor']
if actorJson.get('id') and \ if actorJson.get('id') and \
actorJson.get('skills') and \ noOfActorSkills(actorJson) > 0 and \
actorJson.get('name') and \ actorJson.get('name') and \
actorJson.get('icon'): actorJson.get('icon'):
actor = actorJson['id'] actor = actorJson['id']
for skillName, skillLevel in \ actorSkillsStr = \
actorJson['skills'].items(): actorJson['hasOccupation']['skills']
skills = getSkillsFromString(actorSkillsStr)
for skillName, skillLevel in skills.items():
skillName = skillName.lower() skillName = skillName.lower()
if not (skillName in skillsearch or if not (skillName in skillsearch or
skillsearch in skillName): skillsearch in skillName):

View File

@ -720,18 +720,11 @@ def htmlHeaderWithPersonMarkup(cssFilename: str, instanceTitle: str,
return htmlStr return htmlStr
skillsMarkup = '' skillsMarkup = ''
if actorJson.get('skills'): if actorJson.get('hasOccupation'):
skillsStr = '' skillsStr = actorJson['hasOccupation']['skills']
for skillName, skillValue in actorJson['skills'].items(): if actorJson['hasOccupation'].get('name'):
if skillsStr: occupationName = actorJson['hasOccupation']['name']
skillsStr += ', ' + skillName occupationStr = ' "name": "' + occupationName + '",\n'
else:
skillsStr += skillName
if skillsStr:
occupationStr = ''
if actorJson.get('occupationName'):
occupationName = actorJson['occupationName']
occupationStr = ' "name": "' + occupationName + '",\n'
skillsMarkup = \ skillsMarkup = \
' "hasOccupation": {\n' + \ ' "hasOccupation": {\n' + \
' "@type": "Occupation",\n' + \ ' "@type": "Occupation",\n' + \