From 6862c1930beddd81fe6677847c2f891341faf574 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 27 Aug 2019 23:50:40 +0100 Subject: [PATCH] Skills search --- daemon.py | 13 +++++++ webinterface.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index a73381779..f0de35b73 100644 --- a/daemon.py +++ b/daemon.py @@ -101,6 +101,7 @@ from webinterface import htmlProfileAfterSearch from webinterface import htmlEditProfile from webinterface import htmlTermsOfService from webinterface import htmlHashtagSearch +from webinterface import htmlSkillsSearch from webinterface import htmlModerationInfo from webinterface import htmlSearchSharedItems from webinterface import htmlHashtagBlocked @@ -2508,6 +2509,18 @@ class PubServer(BaseHTTPRequestHandler): self.wfile.write(msg) self.server.POSTbusy=False return + elif searchStr.startswith('*'): + # skill search + searchStr=searchStr.replace('*','').strip() + skillStr= \ + htmlSkillSearch(self.server.baseDir,searchStr, \ + maxPostsInFeed) + if skillStr: + msg=skillStr.encode('utf-8') + self._login_headers('text/html',len(msg)) + self.wfile.write(msg) + self.server.POSTbusy=False + return elif '@' in searchStr: # profile search nickname=getNicknameFromActor(self.path) diff --git a/webinterface.py b/webinterface.py index 896191190..d354e07ac 100644 --- a/webinterface.py +++ b/webinterface.py @@ -284,6 +284,94 @@ def htmlHashtagSearch(baseDir: str,hashtag: str,pageNumber: int,postsPerPage: in hashtagSearchForm+=htmlFooter() return hashtagSearchForm +def htmlSkillsSearch(baseDir: str,skillsearch: str,postsPerPage: int) -> str: + """Show a page containing search results for a skill + """ + if skillsearch.startswith('*'): + skillsearch=skillsearch[1:].strip() + + skillsearch=skillsearch.lower().strip('\n') + + results=[] + # search instance accounts + for subdir, dirs, files in os.walk(baseDir+'/accounts/'): + for f in files: + if not f.endswith('.json'): + continue + if '@' not in f: + continue + if f.startswith('inbox@'): + continue + actor=f.replace('.json','').replace('#','/') + actorFilename = os.path.join(subdir, f) + with open(actorFilename, 'r') as fp: + actorJson=commentjson.load(fp) + if actorJson.get('skills') and actorJson.get('name') and actorJson.get('icon'): + for skillName,skillLevel in actorJson['skills'].items(): + if skillName.lower() in skillsearch: + skillLevelStr=str(skillLevel) + if skillLevel<100: + skillLevelStr='0'+skillLevelStr + if skillLevel<10: + skillLevelStr='0'+skillLevelStr + indexStr=skillLevelStr+';'+actor+';'+actorJson['name']+';'+actorJson['icon']['url'] + if indexStr not in results: + results.append() + # search actor cache + for subdir, dirs, files in os.walk(baseDir+'/cache/actors/'): + for f in files: + if not f.endswith('.json'): + continue + if '@' not in f: + continue + if f.startswith('inbox@'): + continue + actor=f.replace('.json','').replace('#','/') + actorFilename = os.path.join(subdir, f) + with open(actorFilename, 'r') as fp: + cachedActorJson=commentjson.load(fp) + if cachedActorJson.get('actor'): + actorJson=cachedActorJson['actor'] + if actorJson.get('skills') and actorJson.get('name') and actorJson.get('icon'): + for skillName,skillLevel in actorJson['skills'].items(): + if skillName.lower() in skillsearch: + skillLevelStr=str(skillLevel) + if skillLevel<100: + skillLevelStr='0'+skillLevelStr + if skillLevel<10: + skillLevelStr='0'+skillLevelStr + indexStr=skillLevelStr+';'+actor+';'+actorJson['name']+';'+actorJson['icon']['url'] + if indexStr not in results: + results.append() + + results.sort(reverse=True) + + with open(baseDir+'/epicyon-profile.css', 'r') as cssFile: + skillSearchCSS = cssFile.read() + + skillSearchForm=htmlHeader(skillSearchCSS) + skillSearchForm+='

*'+skillsearch+'

' + + if len(results)==0: + skillSearchForm+='
No matches
' + else: + skillSearchForm+='
' + ctr=0 + for skillMatch in results: + skillMatchFields=skillMatch.split(';') + if len(skillMatchFields)==4: + actor=skillMatchFields[1] + actorName=skillMatchFields[2] + avatarUrl=skillMatchFields[3] + skillSearchForm+='

' + skillSearchForm+=''+actorName+'

' + ctr+=1 + if ctr>=postsPerPage: + break + skillSearchForm+='
' + skillSearchForm+=htmlFooter() + return skillSearchForm + def htmlEditProfile(baseDir: str,path: str,domain: str,port: int) -> str: """Shows the edit profile screen """ @@ -1308,7 +1396,10 @@ def individualPostAsHtml(baseDir: str, \ publishedStr=postJsonObject['object']['published'] if '.' not in publishedStr: - datetimeObject = datetime.strptime(publishedStr,"%Y-%m-%dT%H:%M:%SZ") + if '+' not in publishedStr: + datetimeObject = datetime.strptime(publishedStr,"%Y-%m-%dT%H:%M:%SZ") + else: + datetimeObject = datetime.strptime(publishedStr.split('+')[0]+' GMT',"%Y-%m-%dT%H:%M:%SZ") else: publishedStr=publishedStr.replace('T',' ').split('.')[0] datetimeObject = parse(publishedStr) @@ -1932,7 +2023,7 @@ def htmlSearch(baseDir: str,path: str) -> str: followStr+='
' followStr+='
' followStr+='
' - followStr+='

Enter an address, shared item, #hashtag or :emoji: to search for

' + followStr+='

Enter an address, shared item, #hashtag, *skill or :emoji: to search for

' followStr+= \ '
' \ ' ' \