Timeline for DMs

master
Bob Mottram 2019-08-25 17:09:56 +01:00
parent 1b66aa0077
commit 97487eeb54
4 changed files with 133 additions and 30 deletions

View File

@ -1378,6 +1378,71 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy=False
return
# get the inbox for a given person
if self.path.endswith('/dm') or '/dm?page=' in self.path:
if '/users/' in self.path:
if authorized:
inboxDMFeed=personBoxJson(self.server.baseDir, \
self.server.domain, \
self.server.port, \
self.path, \
self.server.httpPrefix, \
maxPostsInFeed, 'dm', \
True,self.server.ocapAlways)
if inboxDMFeed:
if self._requestHTTP():
nickname=self.path.replace('/users/','').replace('/dm','')
pageNumber=1
if '?page=' in nickname:
pageNumber=nickname.split('?page=')[1]
nickname=nickname.split('?page=')[0]
if pageNumber.isdigit():
pageNumber=int(pageNumber)
else:
pageNumber=1
if 'page=' not in self.path:
# if no page was specified then show the first
inboxDMFeed=personBoxJson(self.server.baseDir, \
self.server.domain, \
self.server.port, \
self.path+'?page=1', \
self.server.httpPrefix, \
maxPostsInFeed, 'dm', \
True,self.server.ocapAlways)
msg=htmlInbox(pageNumber,maxPostsInFeed, \
self.server.session, \
self.server.baseDir, \
self.server.cachedWebfingers, \
self.server.personCache, \
nickname, \
self.server.domain, \
self.server.port, \
inboxDMFeed, \
self.server.allowDeletion, \
self.server.httpPrefix, \
self.server.projectVersion).encode('utf-8')
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
else:
msg=json.dumps(inboxDMFeed).encode('utf-8')
self._set_headers('application/json',len(msg),None)
self.wfile.write(msg)
self.server.GETbusy=False
return
else:
if self.server.debug:
nickname=self.path.replace('/users/','').replace('/dm','')
print('DEBUG: '+nickname+ \
' was not authorized to access '+self.path)
if self.path!='/dm':
# not the DM inbox
if self.server.debug:
print('DEBUG: GET access to inbox is unauthorized')
self.send_response(405)
self.end_headers()
self.server.GETbusy=False
return
# get outbox feed for a person
outboxFeed=personBoxJson(self.server.baseDir,self.server.domain, \
self.server.port,self.path, \

View File

@ -18,6 +18,7 @@ from Crypto.PublicKey import RSA
from shutil import copyfile
from webfinger import createWebfingerEndpoint
from webfinger import storeWebfingerEndpoint
from posts import createDMTimeline
from posts import createInbox
from posts import createOutbox
from posts import createModeration
@ -387,7 +388,8 @@ def personBoxJson(baseDir: str,domain: str,port: int,path: str, \
authorized: bool,ocapAlways: bool) -> []:
"""Obtain the inbox/outbox/moderation feed for the given person
"""
if boxname!='inbox' and boxname!='outbox' and boxname!='moderation':
if boxname!='inbox' and boxname!='dm' and \
boxname!='outbox' and boxname!='moderation':
return None
if not '/'+boxname in path:
@ -424,6 +426,9 @@ def personBoxJson(baseDir: str,domain: str,port: int,path: str, \
if boxname=='inbox':
return createInbox(baseDir,nickname,domain,port,httpPrefix, \
noOfItems,headerOnly,ocapAlways,pageNumber)
if boxname=='dm':
return createDMTimeline(baseDir,nickname,domain,port,httpPrefix, \
noOfItems,headerOnly,ocapAlways,pageNumber)
elif boxname=='outbox':
return createOutbox(baseDir,nickname,domain,port,httpPrefix, \
noOfItems,headerOnly,authorized,pageNumber)

View File

@ -1508,6 +1508,11 @@ def createInbox(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str
return createBoxBase(baseDir,'inbox',nickname,domain,port,httpPrefix, \
itemsPerPage,headerOnly,True,ocapAlways,pageNumber)
def createDMTimeline(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \
itemsPerPage: int,headerOnly: bool,ocapAlways: bool,pageNumber=None) -> {}:
return createBoxBase(baseDir,'dm',nickname,domain,port,httpPrefix, \
itemsPerPage,headerOnly,True,ocapAlways,pageNumber)
def createOutbox(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \
itemsPerPage: int,headerOnly: bool,authorized: bool,pageNumber=None) -> {}:
return createBoxBase(baseDir,'outbox',nickname,domain,port,httpPrefix, \
@ -1581,15 +1586,41 @@ def getStatusNumberFromPostFilename(filename) -> int:
return None
return int(filename.split('#')[-1].replace('.json',''))
def isDM(postJsonObject: {}) -> bool:
"""Returns true if the given post is a DM
"""
if postJsonObject['type']!='Create':
return False
if not postJsonObject.get('object'):
return False
if not isinstance(postJsonObject['object'], dict):
return False
if postJsonObject['object']['type']!='Note':
return False
fields=['to','cc']
for f in fields:
if not postJsonObject['object'].get(f):
continue
for toAddress in postJsonObject['object'][f]:
if toAddress.endswith('#Public'):
return False
if toAddress.endswith('followers'):
return False
return True
def createBoxBase(baseDir: str,boxname: str, \
nickname: str,domain: str,port: int,httpPrefix: str, \
itemsPerPage: int,headerOnly: bool,authorized :bool, \
ocapAlways: bool,pageNumber=None) -> {}:
"""Constructs the box feed for a person with the given nickname
"""
if boxname!='inbox' and boxname!='outbox':
if boxname!='inbox' and boxname!='dm' and boxname!='outbox':
return None
boxDir = createPersonDir(nickname,domain,baseDir,boxname)
if boxname!='dm':
boxDir = createPersonDir(nickname,domain,baseDir,boxname)
else:
# extract DMs from the inbox
boxDir = createPersonDir(nickname,domain,baseDir,'inbox')
sharedBoxDir=None
if boxname=='inbox':
sharedBoxDir = createPersonDir('inbox',domain,baseDir,boxname)
@ -1709,30 +1740,32 @@ def createBoxBase(baseDir: str,boxname: str, \
with open(filePath, 'r') as fp:
p=commentjson.load(fp)
# remove any capability so that it's not displayed
if p.get('capability'):
del p['capability']
# Don't show likes or replies to unauthorized viewers
if not authorized:
if p.get('object'):
if isinstance(p['object'], dict):
if p['object'].get('likes'):
p['likes']={}
if p['object'].get('replies'):
p['replies']={}
# insert it into the box feed
if postsOnPageCtr < itemsPerPage:
if not headerOnly:
boxItems['orderedItems'].append(p)
postsOnPageCtr += 1
elif postsOnPageCtr == itemsPerPage:
# if this is the last post update the next message ID
if '/statuses/' in p['id']:
postId = p['id'].split('/statuses/')[1].replace('/activity','')
boxHeader['next']= \
httpPrefix+'://'+domain+'/users/'+ \
nickname+'/'+boxname+'?max_id='+ \
postId+'&page=true'
if boxname!='dm' or \
(boxname=='dm' and isDM(p))
# remove any capability so that it's not displayed
if p.get('capability'):
del p['capability']
# Don't show likes or replies to unauthorized viewers
if not authorized:
if p.get('object'):
if isinstance(p['object'], dict):
if p['object'].get('likes'):
p['likes']={}
if p['object'].get('replies'):
p['replies']={}
# insert it into the box feed
if postsOnPageCtr < itemsPerPage:
if not headerOnly:
boxItems['orderedItems'].append(p)
postsOnPageCtr += 1
elif postsOnPageCtr == itemsPerPage:
# if this is the last post update the next message ID
if '/statuses/' in p['id']:
postId = p['id'].split('/statuses/')[1].replace('/activity','')
boxHeader['next']= \
httpPrefix+'://'+domain+'/users/'+ \
nickname+'/'+boxname+'?max_id='+ \
postId+'&page=true'
# remember the last post filename for use with prev
prevPostFilename = postFilename
if postsOnPageCtr >= itemsPerPage:

View File

@ -271,7 +271,7 @@ def validNickname(domain: str,nickname: str) -> bool:
return False
if nickname==domain:
return False
reservedNames=['inbox','outbox','following','followers','capabilities']
reservedNames=['inbox','dm','outbox','following','public','followers','capabilities']
if nickname in reservedNames:
return False
return True