Hashtag search on public posts

master
Bob Mottram 2019-08-10 11:54:52 +01:00
parent 209371820d
commit 5a8757d8b0
3 changed files with 126 additions and 4 deletions

View File

@ -76,6 +76,7 @@ from webinterface import htmlUnfollowConfirm
from webinterface import htmlProfileAfterSearch
from webinterface import htmlEditProfile
from webinterface import htmlTermsOfService
from webinterface import htmlHashtagSearch
from shares import getSharesFeedForPerson
from shares import outboxShareUpload
from shares import outboxUndoShareUpload
@ -436,6 +437,7 @@ class PubServer(BaseHTTPRequestHandler):
'/sharefiles/' not in self.path and \
'/statuses/' not in self.path and \
'/emoji/' not in self.path and \
'/tags/' not in self.path and \
'/icons/' not in self.path:
divertToLoginScreen=True
if self.path.startswith('/users/'):
@ -677,6 +679,30 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy=False
return
# hashtag search
if self.path.startswith('/tags/'):
pageNumber=1
if '?page=' in self.path:
pageNumberStr=self.path.split('?page=')[1]
if pageNumberStr.isdigit():
pageNumber=int(pageNumberStr)
hashtag=self.path.split('/tags/')[1]
if '?page=' in hashtag:
hashtag=hashtag.split('?page=')[0]
hashtagStr= \
htmlHashtagSearch(self.server.baseDir,hashtag,pageNumber, \
maxPostsInFeed,self.server.session, \
self.server.cachedWebfingers, \
self.server.personCache)
self._set_headers('text/html',cookie)
if hashtagStr:
self.wfile.write(hashtagStr.encode())
else:
originPathStr=self.path.split('/tags/')[0]
self._redirect_headers(originPathStr+'/search',cookie)
self.server.GETbusy=False
return
# search for a fediverse address from the web interface by selecting search icon
if '/users/' in self.path:
if self.path.endswith('/search'):
@ -1931,12 +1957,26 @@ class PubServer(BaseHTTPRequestHandler):
actorStr=self.path.replace('/searchhandle','')
length = int(self.headers['Content-length'])
searchParams=self.rfile.read(length).decode('utf-8')
#print('******************searchParams '+searchParams)
if 'searchtext=' in searchParams:
searchStr=searchParams.split('searchtext=')[1]
if '&' in searchStr:
searchStr=searchStr.split('&')[0]
searchStr=searchStr.replace('+',' ').replace('%40','@').replace('%3A',':').strip()
searchStr=searchStr.replace('+',' ').replace('%40','@').replace('%3A',':').replace('%23','#').strip()
if searchStr.startswith('#'):
# hashtag search
hashtagStr= \
htmlHashtagSearch(self.server.baseDir,searchStr[1:],1, \
maxPostsInFeed,self.server.session, \
self.server.cachedWebfingers, \
self.server.personCache)
if hashtagStr:
self._login_headers('text/html')
self.wfile.write(hashtagStr.encode('utf-8'))
self.server.POSTbusy=False
return
if '@' in searchStr:
# profile search
print('Search: '+searchStr)
nickname=getNicknameFromActor(self.path)
if not self.server.session:

View File

@ -1193,6 +1193,9 @@ if args.testdata:
password='boringpassword'
print('Generating some test data for user: '+nickname)
if os.path.isdir(baseDir+'/tags'):
shutil.rmtree(baseDir+'/tags')
setConfigParam(baseDir,'registrationsRemaining',str(maxRegistrations))
createPerson(baseDir,'maxboardroom',domain,port,httpPrefix,True,password)
@ -1231,13 +1234,13 @@ if args.testdata:
deleteAllPosts(baseDir,nickname,domain,'inbox')
deleteAllPosts(baseDir,nickname,domain,'outbox')
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"like, this is totally just a test, man",False,True,False,None,None,useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"like, this is totally just a #test, man",False,True,False,None,None,useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Zoiks!!!",False,True,False,None,None,useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Hey scoob we need like a hundred more milkshakes",False,True,False,None,None,useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Hey scoob we need like a hundred more #milkshakes",False,True,False,None,None,useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Getting kinda spooky around here",False,True,False,None,None,useBlurhash,'someone')
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"And they would have gotten away with it too if it wasn't for those pesky hackers",False,True,False,'img/logo.png','Description of image',useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"man, these centralized sites are, like, the worst!",False,True,False,None,None,useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"another mystery solved hey",False,True,False,None,None,useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"another mystery solved #test",False,True,False,None,None,useBlurhash)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"let's go bowling",False,True,False,None,None,useBlurhash)
domainFull=domain+':'+str(port)

View File

@ -33,6 +33,85 @@ from content import getMentionsFromHtml
from config import getConfigParam
from skills import getSkills
def htmlHashtagSearch(baseDir: str,hashtag: str,pageNumber: int,postsPerPage: int,
session,wfRequest: {},personCache: {}) -> str:
"""Show a page containing search results for a hashtag
"""
if hashtag.startswith('#'):
hashtag=hashtag[1:]
hashtagIndexFile=baseDir+'/tags/'+hashtag+'.txt'
if not os.path.isfile(hashtagIndexFile):
return None
# read the index
with open(hashtagIndexFile, "r") as f:
lines = f.readlines()
with open(baseDir+'/epicyon-profile.css', 'r') as cssFile:
hashtagSearchCSS = cssFile.read()
startIndex=len(lines)-1-int(pageNumber*postsPerPage)
if startIndex<0:
startIndex=len(lines)-1
endIndex=startIndex-postsPerPage
if endIndex<0:
endIndex=0
hashtagSearchForm=htmlHeader(hashtagSearchCSS)
hashtagSearchForm+='<center><h1>Results for #'+hashtag+'</h1></center>'
if startIndex!=len(lines)-1:
# previous page link
hashtagSearchForm+='<center><a href="/tags/'+hashtag+'?page='+str(pageNumber-1)+'"><img class="pageicon" src="/icons/pageup.png" title="Page up" alt="Page up"></a></center>'
index=startIndex
while index>=endIndex:
postId=lines[index].strip('\n')
nickname=getNicknameFromActor(postId)
if not nickname:
index-=1
continue
domain,port=getDomainFromActor(postId)
if not domain:
index-=1
continue
postFilename=locatePost(baseDir,nickname,domain,postId)
if not postFilename:
index-=1
continue
with open(postFilename, 'r') as fp:
postJsonObject=commentjson.load(fp)
if not postJsonObject.get('type'):
index-=1
continue
if postJsonObject['type']!='Create':
index-=1
continue
if not postJsonObject.get('object'):
index-=1
continue
if not isinstance(postJsonObject['object'], dict):
index-=1
continue
if not postJsonObject['object'].get('to'):
index-=1
continue
isPublic=False
for recipient in postJsonObject['object']['to']:
if recipient.endswith('#Public'):
isPublic=True
break
if isPublic:
hashtagSearchForm+= \
individualPostAsHtml(baseDir,session,wfRequest,personCache, \
nickname,domain,port,postJsonObject, \
None,True,False,False)
index-=1
if endIndex>0:
# next page link
hashtagSearchForm+='<center><a href="/tags/'+hashtag+'?page='+str(pageNumber+1)+'"><img class="pageicon" src="/icons/pageup.png" title="Page up" alt="Page up"></a></center>'
hashtagSearchForm+=htmlFooter()
return hashtagSearchForm
def htmlEditProfile(baseDir: str,path: str,domain: str,port: int) -> str:
"""Shows the edit profile screen
"""