From 9938be63bf88b995e3b6052b6702bfefdc2d0286 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 11 Aug 2019 12:25:27 +0100 Subject: [PATCH] Report post type --- daemon.py | 47 +++++++++++++++++++++++----- epicyon-profile.css | 5 +++ img/icons/scope_report.png | Bin 0 -> 4014 bytes posts.py | 61 +++++++++++++++++++++++++++++++++++++ roles.py | 39 ++++++++++++++++++++++++ webinterface.py | 22 +++++++++---- 6 files changed, 160 insertions(+), 14 deletions(-) create mode 100644 img/icons/scope_report.png diff --git a/daemon.py b/daemon.py index a6305de5..58b3c389 100644 --- a/daemon.py +++ b/daemon.py @@ -32,6 +32,7 @@ from posts import sendToFollowers from posts import postIsAddressedToPublic from posts import sendToNamedAddresses from posts import createPublicPost +from posts import createReportPost from posts import createUnlistedPost from posts import createFollowersOnlyPost from posts import createDirectMessagePost @@ -948,6 +949,7 @@ class PubServer(BaseHTTPRequestHandler): self.path.endswith('/newunlisted') or \ self.path.endswith('/newfollowers') or \ self.path.endswith('/newdm') or \ + self.path.endswith('/newreport') or \ self.path.endswith('/newshare')): self._set_headers('text/html',cookie) self.wfile.write(htmlNewPost(self.server.baseDir,self.path,inReplyToUrl,replyToList).encode()) @@ -1616,14 +1618,16 @@ class PubServer(BaseHTTPRequestHandler): return -1 if postType=='newdm': - messageJson= \ - createDirectMessagePost(self.server.baseDir, \ - nickname, \ - self.server.domain,self.server.port, \ - self.server.httpPrefix, \ - fields['message'],True,False,False, \ - filename,fields['imageDescription'],True, \ - fields['replyTo'],fields['replyTo'],fields['subject']) + messageJson=None + if '@' in fields['message']: + messageJson= \ + createDirectMessagePost(self.server.baseDir, \ + nickname, \ + self.server.domain,self.server.port, \ + self.server.httpPrefix, \ + fields['message'],True,False,False, \ + filename,fields['imageDescription'],True, \ + fields['replyTo'],fields['replyTo'],fields['subject']) if messageJson: self.postToNickname=nickname if self._postToOutbox(messageJson): @@ -1637,6 +1641,26 @@ class PubServer(BaseHTTPRequestHandler): else: return -1 + if postType=='newreport': + # So as to be sure that this only goes to moderators + # and not accounts being reported we disable any + # included fediverse addresses by replacing '@' with '-at-' + fields['message']=fields['message'].replace('@','-at-') + messageJson= \ + createReportPost(self.server.baseDir, \ + nickname, \ + self.server.domain,self.server.port, \ + self.server.httpPrefix, \ + fields['message'],True,False,False, \ + filename,fields['imageDescription'],True, \ + self.server.debug,fields['subject']) + if messageJson: + self.postToNickname=nickname + if self._postToOutbox(messageJson): + return 1 + else: + return -1 + if postType=='newshare': if not fields.get('itemType'): return False @@ -2164,6 +2188,13 @@ class PubServer(BaseHTTPRequestHandler): self.server.POSTbusy=False return postState=self._receiveNewPost(authorized,'newdm') + if postState!=0: + if '/' in nickname: + nickname=nickname.split('/')[0] + self._redirect_headers('/users/'+self.postToNickname+'/outbox',cookie) + self.server.POSTbusy=False + return + postState=self._receiveNewPost(authorized,'newreport') if postState!=0: if '/' in nickname: nickname=nickname.split('/')[0] diff --git a/epicyon-profile.css b/epicyon-profile.css index d77d2de2..8d55a4c5 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -92,6 +92,11 @@ a:link { padding: 4px 0; } +.new-post-subtext { + font-size: 18px; + padding: 4px 0; +} + .highlight { width: 2%; } diff --git a/img/icons/scope_report.png b/img/icons/scope_report.png new file mode 100644 index 0000000000000000000000000000000000000000..a7802ce9af9d6db27bb253fe19749cfa3c66f9a2 GIT binary patch literal 4014 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 {}: + """Send a report to moderators + """ + domainFull=domain + if port: + if port!=80 and port!=443: + domainFull=domain+':'+str(port) + + # create the list of moderators from teh moderators file + moderatorsList=[] + moderatorsFile=baseDir+'/accounts/moderators.txt' + if os.path.isfile(moderatorsFile): + with open (moderatorsFile, "r") as fileHandler: + for line in fileHandler: + line=line.strip('\n') + if line.startswith('#'): + continue + if line.startswith('/users/'): + line=line.replace('users','') + if line.startswith('@'): + line=line[1:] + if '@' in line: + moderatorActor=httpPrefix+'://'+domainFull+'/users/'+line.split('@')[0] + if moderatorActor not in moderatorList: + moderatorsList.append(moderatorActor) + continue + if line.startswith('http') or line.startswith('dat'): + # must be a local address - no remote moderators + if '://'+domainFull+'/' in line: + if line not in moderatorsList: + moderatorsList.append(line) + else: + if '/' not in line: + moderatorActor=httpPrefix+'://'+domainFull+'/users/'+line + if moderatorActor not in moderatorsList: + moderatorsList.append(moderatorActor) + if len(moderatorsList)==0: + # if there are no moderators then the admin becomes the moderator + adminNickname=getConfigParam(baseDir,'admin') + if adminNickname: + moderatorsList.append(httpPrefix+'://'+domainFull+'/users/'+adminNickname) + if not moderatorsList: + return None + if debug: + print('DEBUG: Sending report to moderators') + print(str(moderatorsList)) + postTo=moderatorsList + postCc=None + return createPostBase(baseDir,nickname, domain, port, \ + postTo,postCc, \ + httpPrefix, content, followersOnly, saveToFile, \ + clientToServer, \ + attachImageFilename,imageDescription,useBlurhash, \ + None, None, subject) + def threadSendPost(session,postJsonObject: {},federationList: [],\ inboxUrl: str, baseDir: str,signatureHeaderJson: {},postLog: [], debug :bool) -> None: diff --git a/roles.py b/roles.py index 8505862a..de60d947 100644 --- a/roles.py +++ b/roles.py @@ -16,6 +16,39 @@ from session import postJson from utils import getNicknameFromActor from utils import getDomainFromActor +def addModerator(baseDir: str,nickname: str): + """Adds a moderator nickname to the file + """ + moderatorsFile=baseDir+'/accounts/moderators.txt' + if os.path.isfile(moderatorsFile): + # is this nickname already in the file? + with open(moderatorsFile, "r") as f: + lines = f.readlines() + for moderator in lines: + moderator=moderator.strip('\n') + if line==nickname: + return + lines.append(nickname) + with open(moderatorsFile, "w") as f: + for moderator in lines: + moderator=moderator.strip('\n') + if len(moderator)>1: + f.write(moderator+'\n') + +def removeModerator(baseDir: str,nickname: str): + """Removes a moderator nickname from the file + """ + moderatorsFile=baseDir+'/accounts/moderators.txt' + if not os.path.isfile(moderatorsFile): + return + with open(moderatorsFile, "r") as f: + lines = f.readlines() + with open(moderatorsFile, "w") as f: + for moderator in lines: + moderator=moderator.strip('\n') + if len(moderator)>1 and moderator!=nickname: + f.write(moderator+'\n') + def setRole(baseDir: str,nickname: str,domain: str, \ project: str,role: str) -> bool: """Set a person's role within a project @@ -30,12 +63,18 @@ def setRole(baseDir: str,nickname: str,domain: str, \ with open(actorFilename, 'r') as fp: actorJson=commentjson.load(fp) if role: + # add the role + if project=='instance' and 'role'=='moderator': + addModerator(baseDir,nickname) if actorJson['roles'].get(project): if role not in actorJson['roles'][project]: actorJson['roles'][project].append(role) else: actorJson['roles'][project]=[role] else: + # remove the role + if project=='instance': + removeModerator(baseDir,nickname) if actorJson['roles'].get(project): actorJson['roles'][project].remove(role) # if the project contains no roles then remove it diff --git a/webinterface.py b/webinterface.py index 575cc2bb..b1904d07 100644 --- a/webinterface.py +++ b/webinterface.py @@ -319,11 +319,16 @@ def htmlTermsOfService(baseDir: str,httpPrefix: str,domainFull: str) -> str: def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: []) -> str: replyStr='' if not path.endswith('/newshare'): - if not inReplyTo: - newPostText='

Enter your post text below.

' + if not path.endswith('/newreport'): + if not inReplyTo: + newPostText='

Enter your post text below.

' + else: + newPostText='

Enter your reply to this post below.

' + replyStr='' else: - newPostText='

Enter your reply to this post below.

' - replyStr='' + newPostText= \ + '

Enter your report below.

' \ + '

This message only goes to moderators, even if it mentions other fediverse addresses.

' else: newPostText='

Enter the details for your shared item below.

' @@ -334,7 +339,7 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: []) -> str: with open(baseDir+'/epicyon-profile.css', 'r') as cssFile: newPostCSS = cssFile.read() - pathBase=path.replace('/newpost','').replace('/newshare','').replace('/newunlisted','').replace('/newfollowers','').replace('/newdm','') + pathBase=path.replace('/newreport','').replace('/newpost','').replace('/newshare','').replace('/newunlisted','').replace('/newfollowers','').replace('/newdm','') scopeIcon='scope_public.png' scopeDescription='Public' @@ -354,6 +359,10 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: []) -> str: scopeIcon='scope_dm.png' scopeDescription='Direct Message' endpoint='newdm' + if path.endswith('/newreport'): + scopeIcon='scope_report.png' + scopeDescription='Report' + endpoint='newreport' if path.endswith('/newshare'): scopeIcon='scope_share.png' scopeDescription='Shared Item' @@ -399,7 +408,8 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: []) -> str: ' Public
Visible to anyone
' \ ' Unlisted
Not on public timeline
' \ ' Followers Only
Only to followers
' \ - ' Direct Message
Only to mentioned people
'+ \ + ' Direct Message
Only to mentioned people
' \ + ' Report
Send to moderators
'+ \ shareOptionOnDropdown+ \ ' ' \ ' ' \