diff --git a/daemon.py b/daemon.py index 4b714376..eee27158 100644 --- a/daemon.py +++ b/daemon.py @@ -61,6 +61,7 @@ from person import removeAccount from person import canRemovePost from person import personSnooze from person import personUnsnooze +from posts import isModerator from posts import mutePost from posts import unmutePost from posts import createQuestionPost @@ -145,6 +146,7 @@ from webinterface import htmlUnfollowConfirm from webinterface import htmlProfileAfterSearch from webinterface import htmlEditProfile from webinterface import htmlEditLinks +from webinterface import htmlEditNewswire from webinterface import htmlTermsOfService from webinterface import htmlSkillsSearch from webinterface import htmlHistorySearch @@ -2708,7 +2710,10 @@ class PubServer(BaseHTTPRequestHandler): # get the nickname nickname = getNicknameFromActor(actorStr) - if not nickname: + moderator = None + if nickname: + moderator = isModerator(baseDir, nickname) + if not nickname or not moderator: if callingDomain.endswith('.onion') and \ onionDomain: actorStr = \ @@ -2717,7 +2722,10 @@ class PubServer(BaseHTTPRequestHandler): i2pDomain): actorStr = \ 'http://' + i2pDomain + usersPath - print('WARN: nickname not found in ' + actorStr) + if not nickname: + print('WARN: nickname not found in ' + actorStr) + else: + print('WARN: nickname is not a moderator' + actorStr) self._redirect_headers(actorStr, cookie, callingDomain) self.server.POSTbusy = False return @@ -2789,6 +2797,111 @@ class PubServer(BaseHTTPRequestHandler): cookie, callingDomain) self.server.POSTbusy = False + def _newswireUpdate(self, callingDomain: str, cookie: str, + authorized: bool, path: str, + baseDir: str, httpPrefix: str, + domain: str, domainFull: str, + onionDomain: str, i2pDomain: str, debug: bool, + defaultTimeline: str): + """Updates the right newswire column of the timeline + """ + usersPath = path.replace('/newswiredata', '') + usersPath = usersPath.replace('/editnewswire', '') + actorStr = httpPrefix + '://' + domainFull + usersPath + if ' boundary=' in self.headers['Content-type']: + boundary = self.headers['Content-type'].split('boundary=')[1] + if ';' in boundary: + boundary = boundary.split(';')[0] + + # get the nickname + nickname = getNicknameFromActor(actorStr) + moderator = None + if nickname: + moderator = isModerator(baseDir, nickname) + if not nickname or not moderator: + if callingDomain.endswith('.onion') and \ + onionDomain: + actorStr = \ + 'http://' + onionDomain + usersPath + elif (callingDomain.endswith('.i2p') and + i2pDomain): + actorStr = \ + 'http://' + i2pDomain + usersPath + if not nickname: + print('WARN: nickname not found in ' + actorStr) + else: + print('WARN: nickname is not a moderator' + actorStr) + self._redirect_headers(actorStr, cookie, callingDomain) + self.server.POSTbusy = False + return + + length = int(self.headers['Content-length']) + + # check that the POST isn't too large + if length > self.server.maxPostLength: + if callingDomain.endswith('.onion') and \ + onionDomain: + actorStr = \ + 'http://' + onionDomain + usersPath + elif (callingDomain.endswith('.i2p') and + i2pDomain): + actorStr = \ + 'http://' + i2pDomain + usersPath + print('Maximum newswire data length exceeded ' + str(length)) + self._redirect_headers(actorStr, cookie, callingDomain) + self.server.POSTbusy = False + return + + try: + # read the bytes of the http form POST + postBytes = self.rfile.read(length) + except SocketError as e: + if e.errno == errno.ECONNRESET: + print('WARN: connection was reset while ' + + 'reading bytes from http form POST') + else: + print('WARN: error while reading bytes ' + + 'from http form POST') + self.send_response(400) + self.end_headers() + self.server.POSTbusy = False + return + except ValueError as e: + print('ERROR: failed to read bytes for POST') + print(e) + self.send_response(400) + self.end_headers() + self.server.POSTbusy = False + return + + newswireFilename = baseDir + '/accounts/newswire.txt' + + # extract all of the text fields into a dict + fields = \ + extractTextFieldsInPOST(postBytes, boundary, debug) + if fields.get('editedNewswire'): + newswireStr = fields['editedNewswire'] + newswireFile = open(newswireFilename, "w+") + if newswireFile: + newswireFile.write(newswireStr) + newswireFile.close() + else: + if os.path.isfile(newswireFilename): + os.remove(newswireFilename) + + # redirect back to the default timeline + if callingDomain.endswith('.onion') and \ + onionDomain: + actorStr = \ + 'http://' + onionDomain + usersPath + elif (callingDomain.endswith('.i2p') and + i2pDomain): + actorStr = \ + 'http://' + i2pDomain + usersPath + self._redirect_headers(actorStr + '/' + defaultTimeline, + cookie, callingDomain) + self.server.POSTbusy = False + def _profileUpdate(self, callingDomain: str, cookie: str, authorized: bool, path: str, baseDir: str, httpPrefix: str, @@ -7478,6 +7591,28 @@ class PubServer(BaseHTTPRequestHandler): return True return False + def _editNewswire(self, callingDomain: str, path: str, + translate: {}, baseDir: str, + httpPrefix: str, domain: str, port: int, + cookie: str) -> bool: + """Show the newswire from the right column + """ + if '/users/' in path and path.endswith('/editnewswire'): + msg = htmlEditNewswire(translate, + baseDir, + path, domain, + port, + httpPrefix).encode('utf-8') + if msg: + self._set_headers('text/html', len(msg), + cookie, callingDomain) + self._write(msg) + else: + self._404() + self.server.GETbusy = False + return True + return False + def _editEvent(self, callingDomain: str, path: str, httpPrefix: str, domain: str, domainFull: str, baseDir: str, translate: {}, @@ -8798,6 +8933,16 @@ class PubServer(BaseHTTPRequestHandler): cookie): return + # edit newswire from the right column of the timeline + if self._editNewswire(callingDomain, self.path, + self.server.translate, + self.server.baseDir, + self.server.httpPrefix, + self.server.domain, + self.server.port, + cookie): + return + if self._showNewPost(callingDomain, self.path, self.server.mediaInstance, self.server.translate, @@ -10256,6 +10401,16 @@ class PubServer(BaseHTTPRequestHandler): self.server.defaultTimeline) return + if authorized and self.path.endswith('/newswiredata'): + self._newswireUpdate(callingDomain, cookie, authorized, self.path, + self.server.baseDir, self.server.httpPrefix, + self.server.domain, + self.server.domainFull, + self.server.onionDomain, + self.server.i2pDomain, self.server.debug, + self.server.defaultTimeline) + return + self._benchmarkPOSTtimings(POSTstartTime, POSTtimings, 3) # moderator action buttons diff --git a/translations/ar.json b/translations/ar.json index 81bc9f8c..0228d7e9 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -294,5 +294,6 @@ "Left column image": "صورة العمود الأيسر", "Right column image": "صورة العمود الأيمن", "RSS feed for this site": "تغذية RSS لهذا الموقع", - "Edit newswire": "" + "Edit newswire": "تحرير الأخبار", + "Add RSS feed links below.": "إضافة روابط تغذية RSS أدناه." } diff --git a/translations/ca.json b/translations/ca.json index 6333ff48..131d19ae 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -294,5 +294,6 @@ "Left column image": "Imatge de la columna esquerra", "Right column image": "Imatge de la columna dreta", "RSS feed for this site": "Feed RSS per a aquest lloc", - "Edit newswire": "" + "Edit newswire": "Editeu newswire", + "Add RSS feed links below.": "Afegiu enllaços de canals RSS a continuació." } diff --git a/translations/cy.json b/translations/cy.json index 588f9ee3..4a09e9ea 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -294,5 +294,6 @@ "Left column image": "Delwedd colofn chwith", "Right column image": "Delwedd colofn dde", "RSS feed for this site": "Porthiant RSS ar gyfer y wefan hon", - "Edit newswire": "" + "Edit newswire": "Golygu newyddion", + "Add RSS feed links below.": "Ychwanegwch ddolenni porthiant RSS isod." } diff --git a/translations/de.json b/translations/de.json index 87f8367b..b6ae2ee3 100644 --- a/translations/de.json +++ b/translations/de.json @@ -294,5 +294,6 @@ "Left column image": "Bild in der linken Spalte", "Right column image": "Bild in der rechten Spalte", "RSS feed for this site": "RSS-Feed für diese Site", - "Edit newswire": "" + "Edit newswire": "Newswire bearbeiten", + "Add RSS feed links below.": "Fügen Sie unten RSS-Feed-Links hinzu." } diff --git a/translations/en.json b/translations/en.json index 99fb0dbf..68d59aea 100644 --- a/translations/en.json +++ b/translations/en.json @@ -294,5 +294,6 @@ "Left column image": "Left column image", "Right column image": "Right column image", "RSS feed for this site": "RSS feed for this site", - "Edit newswire": "Edit newswire" + "Edit newswire": "Edit newswire", + "Add RSS feed links below.": "Add RSS feed links below." } diff --git a/translations/es.json b/translations/es.json index 4ec152b5..5c0bb8e8 100644 --- a/translations/es.json +++ b/translations/es.json @@ -294,5 +294,6 @@ "Left column image": "Imagen de la columna izquierda", "Right column image": "Imagen de la columna derecha", "RSS feed for this site": "Fuente RSS para este sitio", - "Edit newswire": "" + "Edit newswire": "Editar newswire", + "Add RSS feed links below.": "Agregue los enlaces de fuentes RSS a continuación." } diff --git a/translations/fr.json b/translations/fr.json index 33f55691..d462555d 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -294,5 +294,6 @@ "Left column image": "Image de la colonne de gauche", "Right column image": "Image de la colonne de droite", "RSS feed for this site": "Flux RSS de ce site", - "Edit newswire": "" + "Edit newswire": "Modifier le fil d'actualité", + "Add RSS feed links below.": "Ajoutez des liens de flux RSS ci-dessous." } diff --git a/translations/ga.json b/translations/ga.json index 29be130b..6fdfb59d 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -294,5 +294,6 @@ "Left column image": "Íomhá colún ar chlé", "Right column image": "Íomhá colún ar dheis", "RSS feed for this site": "Fotha RSS don láithreán seo", - "Edit newswire": "" + "Edit newswire": "Cuir sreang nuachta in eagar", + "Add RSS feed links below.": "Cuir naisc beatha RSS thíos." } diff --git a/translations/hi.json b/translations/hi.json index cb3082de..e5d851f7 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -294,5 +294,6 @@ "Left column image": "बाएं स्तंभ की छवि", "Right column image": "राइट कॉलम छवि", "RSS feed for this site": "इस साइट के लिए आरएसएस फ़ीड", - "Edit newswire": "" + "Edit newswire": "नवांश संपादित करें", + "Add RSS feed links below.": "नीचे आरएसएस फ़ीड लिंक जोड़ें।" } diff --git a/translations/it.json b/translations/it.json index 6d9b7b97..2e08cba0 100644 --- a/translations/it.json +++ b/translations/it.json @@ -294,5 +294,6 @@ "Left column image": "Immagine della colonna di sinistra", "Right column image": "Immagine della colonna di destra", "RSS feed for this site": "Feed RSS per questo sito", - "Edit newswire": "" + "Edit newswire": "Modifica newswire", + "Add RSS feed links below.": "Aggiungi i link ai feed RSS di seguito." } diff --git a/translations/ja.json b/translations/ja.json index 1346e407..51c53b7a 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -294,5 +294,6 @@ "Left column image": "左の列の画像", "Right column image": "右の列の画像", "RSS feed for this site": "このサイトのRSSフィード", - "Edit newswire": "" + "Edit newswire": "ニュースワイヤーを編集", + "Add RSS feed links below.": "以下にRSSフィードリンクを追加します。" } diff --git a/translations/oc.json b/translations/oc.json index d2ab2b3d..00ad53ff 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -290,5 +290,6 @@ "Left column image": "Left column image", "Right column image": "Right column image", "RSS feed for this site": "RSS feed for this site", - "Edit newswire": "Edit newswire" + "Edit newswire": "Edit newswire", + "Add RSS feed links below.": "Add RSS feed links below." } diff --git a/translations/pt.json b/translations/pt.json index 51efe428..e7baec2e 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -294,5 +294,6 @@ "Left column image": "Imagem da coluna esquerda", "Right column image": "Imagem da coluna direita", "RSS feed for this site": "Feed RSS para este site", - "Edit newswire": "" + "Edit newswire": "Editar notícias", + "Add RSS feed links below.": "Adicione links de feed RSS abaixo." } diff --git a/translations/ru.json b/translations/ru.json index 9235258a..dd0cf04d 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -294,5 +294,6 @@ "Left column image": "Изображение в левом столбце", "Right column image": "Изображение в правом столбце", "RSS feed for this site": "RSS-канал для этого сайта", - "Edit newswire": "" + "Edit newswire": "Редактировать ленту новостей", + "Add RSS feed links below.": "Добавьте ссылки на RSS-канал ниже." } diff --git a/translations/zh.json b/translations/zh.json index 7e099336..32f57294 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -294,5 +294,6 @@ "Left column image": "左栏图片", "Right column image": "右栏图片", "RSS feed for this site": "该站点的RSS feed", - "Edit newswire": "" + "Edit newswire": "编辑新闻专线", + "Add RSS feed links below.": "在下面添加RSS feed链接。" } diff --git a/webinterface.py b/webinterface.py index cdffc71f..f0f96e0f 100644 --- a/webinterface.py +++ b/webinterface.py @@ -1274,6 +1274,74 @@ def htmlEditLinks(translate: {}, baseDir: str, path: str, return editLinksForm +def htmlEditNewswire(translate: {}, baseDir: str, path: str, + domain: str, port: int, httpPrefix: str) -> str: + """Shows the edit newswire screen + """ + if '/users/' not in path: + return '' + pathOriginal = path + path = path.replace('/inbox', '').replace('/outbox', '') + path = path.replace('/shares', '') + + nickname = getNicknameFromActor(path) + if not nickname: + return '' + + # is the user a moderator? + if not isModerator(baseDir, nickname): + return '' + + cssFilename = baseDir + '/epicyon-links.css' + if os.path.isfile(baseDir + '/links.css'): + cssFilename = baseDir + '/links.css' + with open(cssFilename, 'r') as cssFile: + editCSS = cssFile.read() + if httpPrefix != 'https': + editCSS = \ + editCSS.replace('https://', httpPrefix + '://') + + editNewswireForm = htmlHeader(cssFilename, editCSS) + editNewswireForm += \ + '