Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main

main
Bob Mottram 2020-10-05 23:04:54 +01:00
commit 4f1396b9ac
23 changed files with 193 additions and 19 deletions

View File

@ -4,6 +4,8 @@ Add issues on https://gitlab.com/bashrc2/epicyon/-/issues
<blockquote><b>Epicyon</b>, meaning <i>"more than a dog"</i>. Largest of the <i>Borophaginae</i> which lived in North America 20-5 million years ago.</blockquote> <blockquote><b>Epicyon</b>, meaning <i>"more than a dog"</i>. Largest of the <i>Borophaginae</i> which lived in North America 20-5 million years ago.</blockquote>
<img src="https://code.freedombone.net/bashrc/epicyon/raw/master/img/screenshot_indymedia.jpg?raw=true" width="80%"/>
<img src="https://code.freedombone.net/bashrc/epicyon/raw/master/img/mobile.jpg?raw=true" width="30%"/> <img src="https://code.freedombone.net/bashrc/epicyon/raw/master/img/mobile.jpg?raw=true" width="30%"/>
Epicyon is a modern [ActivityPub](https://www.w3.org/TR/activitypub) compliant server implementing both S2S and C2S protocols and sutable for installation on single board computers. It includes features such as moderation tools, post expiry, content warnings, image descriptions and perimeter defense against adversaries. It contains *no javascript* and uses HTML+CSS with a Python backend. Epicyon is a modern [ActivityPub](https://www.w3.org/TR/activitypub) compliant server implementing both S2S and C2S protocols and sutable for installation on single board computers. It includes features such as moderation tools, post expiry, content warnings, image descriptions and perimeter defense against adversaries. It contains *no javascript* and uses HTML+CSS with a Python backend.

View File

@ -2893,6 +2893,19 @@ class PubServer(BaseHTTPRequestHandler):
if os.path.isfile(newswireFilename): if os.path.isfile(newswireFilename):
os.remove(newswireFilename) os.remove(newswireFilename)
newswireTrustedFilename = baseDir + '/accounts/newswiretrusted.txt'
if fields.get('trustedNewswire'):
newswireTrusted = fields['trustedNewswire']
if not newswireTrusted.endswith('\n'):
newswireTrusted += '\n'
trustFile = open(newswireTrustedFilename, "w+")
if trustFile:
trustFile.write(newswireTrusted)
trustFile.close()
else:
if os.path.isfile(newswireTrustedFilename):
os.remove(newswireTrustedFilename)
# redirect back to the default timeline # redirect back to the default timeline
if callingDomain.endswith('.onion') and \ if callingDomain.endswith('.onion') and \
onionDomain: onionDomain:

View File

@ -67,6 +67,7 @@
--quote-font-size: 120%; --quote-font-size: 120%;
--line-spacing: 130%; --line-spacing: 130%;
--line-spacing-newswire: 100%; --line-spacing-newswire: 100%;
--newswire-moderate-color: yellow;
--column-left-width: 10vw; --column-left-width: 10vw;
--column-center-width: 80vw; --column-center-width: 80vw;
--column-right-width: 10vw; --column-right-width: 10vw;
@ -231,6 +232,13 @@ a:focus {
line-height: var(--line-spacing-newswire); line-height: var(--line-spacing-newswire);
} }
.newswireItemModerate {
font-size: var(--font-size-newswire);
color: var(--newswire-moderate-color);
font-weight: bold;
line-height: var(--line-spacing-newswire);
}
.newswireDate { .newswireDate {
font-size: var(--font-size-newswire); font-size: var(--font-size-newswire);
color: var(--newswire-date-color); color: var(--newswire-date-color);

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -13,6 +13,8 @@ from socket import error as SocketError
import errno import errno
from datetime import datetime from datetime import datetime
from collections import OrderedDict from collections import OrderedDict
from utils import locatePost
from utils import loadJson
def rss2Header(httpPrefix: str, def rss2Header(httpPrefix: str,
@ -162,6 +164,107 @@ def getRSSfromDict(baseDir: str, newswire: {},
return rssStr return rssStr
def addAccountBlogsToNewswire(baseDir: str, nickname: str, domain: str,
newswire: {},
maxBlogsPerAccount: int,
indexFilename: str) -> None:
"""Adds blogs for the given account to the newswire
"""
if not os.path.isfile(indexFilename):
return
with open(indexFilename, 'r') as indexFile:
postFilename = 'start'
ctr = 0
while postFilename:
postFilename = indexFile.readline()
if postFilename:
# if this is a full path then remove the directories
if '/' in postFilename:
postFilename = postFilename.split('/')[-1]
# filename of the post without any extension or path
# This should also correspond to any index entry in
# the posts cache
postUrl = \
postFilename.replace('\n', '').replace('\r', '')
postUrl = postUrl.replace('.json', '').strip()
# read the post from file
fullPostFilename = \
locatePost(baseDir, nickname,
domain, postUrl, False)
isAPost = False
postJsonObject = None
if fullPostFilename:
postJsonObject = loadJson(fullPostFilename)
if postJsonObject:
if postJsonObject.get('object'):
if isinstance(postJsonObject['object'], dict):
isAPost = True
if isAPost:
if postJsonObject['object'].get('summary') and \
postJsonObject['object'].get('url') and \
postJsonObject['object'].get('published'):
published = postJsonObject['object']['published']
published = published.replace('T', ' ')
published = published.replace('Z', '+00:00')
newswire[published] = \
[postJsonObject['object']['summary'],
postJsonObject['object']['url']]
ctr += 1
if ctr >= maxBlogsPerAccount:
break
def addLocalBlogsToNewswire(baseDir: str, newswire: {},
maxBlogsPerAccount: int) -> None:
"""Adds blogs from this instance into the newswire
"""
# get the list of handles who are trusted to post to the newswire
newswireTrusted = ''
newswireTrustedFilename = baseDir + '/accounts/newswiretrusted.txt'
if os.path.isfile(newswireTrustedFilename):
with open(newswireTrustedFilename, "r") as trustFile:
newswireTrusted = trustFile.read()
# file containing suspended account nicknames
suspendedFilename = baseDir + '/accounts/suspended.txt'
# go through each account
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for handle in dirs:
if '@' not in handle:
continue
if 'inbox@' in handle:
continue
if handle not in newswireTrusted:
if handle.split('@')[0] + '\n' not in newswireTrusted:
continue
accountDir = os.path.join(baseDir + '/accounts', handle)
# has this account been suspended?
nickname = handle.split('@')[0]
if os.path.isfile(suspendedFilename):
with open(suspendedFilename, "r") as f:
lines = f.readlines()
foundSuspended = False
for nick in lines:
if nick == nickname + '\n':
foundSuspended = True
break
if foundSuspended:
continue
# is there a blogs timeline for this account?
blogsIndex = accountDir + '/tlblogs.index'
if os.path.isfile(blogsIndex):
domain = handle.split('@')[1]
addAccountBlogsToNewswire(baseDir, nickname, domain,
newswire, maxBlogsPerAccount,
blogsIndex)
def getDictFromNewswire(session, baseDir: str) -> {}: def getDictFromNewswire(session, baseDir: str) -> {}:
"""Gets rss feeds as a dictionary from newswire file """Gets rss feeds as a dictionary from newswire file
""" """
@ -169,6 +272,7 @@ def getDictFromNewswire(session, baseDir: str) -> {}:
if not os.path.isfile(subscriptionsFilename): if not os.path.isfile(subscriptionsFilename):
return {} return {}
# add rss feeds
rssFeed = [] rssFeed = []
with open(subscriptionsFilename, 'r') as fp: with open(subscriptionsFilename, 'r') as fp:
rssFeed = fp.readlines() rssFeed = fp.readlines()
@ -182,6 +286,11 @@ def getDictFromNewswire(session, baseDir: str) -> {}:
itemsList = getRSS(session, url) itemsList = getRSS(session, url)
for dateStr, item in itemsList.items(): for dateStr, item in itemsList.items():
result[dateStr] = item result[dateStr] = item
# add local content
addLocalBlogsToNewswire(baseDir, result, 5)
# sort into chronological order, latest first
sortedResult = OrderedDict(sorted(result.items(), reverse=True)) sortedResult = OrderedDict(sorted(result.items(), reverse=True))
return sortedResult return sortedResult

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "تغذية RSS لهذا الموقع", "RSS feed for this site": "تغذية RSS لهذا الموقع",
"Edit newswire": "تحرير الأخبار", "Edit newswire": "تحرير الأخبار",
"Add RSS feed links below.": "إضافة روابط تغذية RSS أدناه.", "Add RSS feed links below.": "إضافة روابط تغذية RSS أدناه.",
"Newswire RSS Feed": "Newswire موجز RSS" "Newswire RSS Feed": "Newswire موجز RSS",
"Nicknames whose blog entries appear on the newswire.": "الألقاب التي تظهر إدخالات المدونة الخاصة بها على موقع الأخبار."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "Feed RSS per a aquest lloc", "RSS feed for this site": "Feed RSS per a aquest lloc",
"Edit newswire": "Editeu newswire", "Edit newswire": "Editeu newswire",
"Add RSS feed links below.": "Afegiu enllaços de canals RSS a continuació.", "Add RSS feed links below.": "Afegiu enllaços de canals RSS a continuació.",
"Newswire RSS Feed": "Feed RSS de Newswire" "Newswire RSS Feed": "Feed RSS de Newswire",
"Nicknames whose blog entries appear on the newswire.": "Sobrenoms les entrades del bloc apareixen a newswire."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "Porthiant RSS ar gyfer y wefan hon", "RSS feed for this site": "Porthiant RSS ar gyfer y wefan hon",
"Edit newswire": "Golygu newyddion", "Edit newswire": "Golygu newyddion",
"Add RSS feed links below.": "Ychwanegwch ddolenni porthiant RSS isod.", "Add RSS feed links below.": "Ychwanegwch ddolenni porthiant RSS isod.",
"Newswire RSS Feed": "Newswire RSS Feed" "Newswire RSS Feed": "Newswire RSS Feed",
"Nicknames whose blog entries appear on the newswire.": "Llysenwau y mae eu cofnodion blog yn ymddangos ar y we newyddion."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "RSS-Feed für diese Site", "RSS feed for this site": "RSS-Feed für diese Site",
"Edit newswire": "Newswire bearbeiten", "Edit newswire": "Newswire bearbeiten",
"Add RSS feed links below.": "Fügen Sie unten RSS-Feed-Links hinzu.", "Add RSS feed links below.": "Fügen Sie unten RSS-Feed-Links hinzu.",
"Newswire RSS Feed": "Newswire RSS Feed" "Newswire RSS Feed": "Newswire RSS Feed",
"Nicknames whose blog entries appear on the newswire.": "Spitznamen, deren Blogeinträge im Newswire erscheinen."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "RSS feed for this site", "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.", "Add RSS feed links below.": "Add RSS feed links below.",
"Newswire RSS Feed": "Newswire RSS Feed" "Newswire RSS Feed": "Newswire RSS Feed",
"Nicknames whose blog entries appear on the newswire.": "Nicknames whose blog entries appear on the newswire."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "Fuente RSS para este sitio", "RSS feed for this site": "Fuente RSS para este sitio",
"Edit newswire": "Editar newswire", "Edit newswire": "Editar newswire",
"Add RSS feed links below.": "Agregue los enlaces de fuentes RSS a continuación.", "Add RSS feed links below.": "Agregue los enlaces de fuentes RSS a continuación.",
"Newswire RSS Feed": "Canal RSS de Newswire" "Newswire RSS Feed": "Canal RSS de Newswire",
"Nicknames whose blog entries appear on the newswire.": "Apodos cuyas entradas de blog aparecen en el newswire."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "Flux RSS de ce site", "RSS feed for this site": "Flux RSS de ce site",
"Edit newswire": "Modifier le fil d'actualité", "Edit newswire": "Modifier le fil d'actualité",
"Add RSS feed links below.": "Ajoutez des liens de flux RSS ci-dessous.", "Add RSS feed links below.": "Ajoutez des liens de flux RSS ci-dessous.",
"Newswire RSS Feed": "Flux RSS de Newswire" "Newswire RSS Feed": "Flux RSS de Newswire",
"Nicknames whose blog entries appear on the newswire.": "Surnoms dont les entrées de blog apparaissent sur le fil de presse."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "Fotha RSS don láithreán seo", "RSS feed for this site": "Fotha RSS don láithreán seo",
"Edit newswire": "Cuir sreang nuachta in eagar", "Edit newswire": "Cuir sreang nuachta in eagar",
"Add RSS feed links below.": "Cuir naisc beatha RSS thíos.", "Add RSS feed links below.": "Cuir naisc beatha RSS thíos.",
"Newswire RSS Feed": "Newswire RSS Feed" "Newswire RSS Feed": "Newswire RSS Feed",
"Nicknames whose blog entries appear on the newswire.": "Leasainmneacha a bhfuil a n-iontrálacha blag le feiceáil ar an sreang nuachta."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "इस साइट के लिए आरएसएस फ़ीड", "RSS feed for this site": "इस साइट के लिए आरएसएस फ़ीड",
"Edit newswire": "नवांश संपादित करें", "Edit newswire": "नवांश संपादित करें",
"Add RSS feed links below.": "नीचे आरएसएस फ़ीड लिंक जोड़ें।", "Add RSS feed links below.": "नीचे आरएसएस फ़ीड लिंक जोड़ें।",
"Newswire RSS Feed": "Newswire RSS फ़ीड" "Newswire RSS Feed": "Newswire RSS फ़ीड",
"Nicknames whose blog entries appear on the newswire.": "उपनाम जिनकी ब्लॉग प्रविष्टियाँ न्यूज़वायर पर दिखाई देती हैं।"
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "Feed RSS per questo sito", "RSS feed for this site": "Feed RSS per questo sito",
"Edit newswire": "Modifica newswire", "Edit newswire": "Modifica newswire",
"Add RSS feed links below.": "Aggiungi i link ai feed RSS di seguito.", "Add RSS feed links below.": "Aggiungi i link ai feed RSS di seguito.",
"Newswire RSS Feed": "Feed RSS di Newswire" "Newswire RSS Feed": "Feed RSS di Newswire",
"Nicknames whose blog entries appear on the newswire.": "Soprannomi le cui voci di blog compaiono nel newswire."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "このサイトのRSSフィード", "RSS feed for this site": "このサイトのRSSフィード",
"Edit newswire": "ニュースワイヤーを編集", "Edit newswire": "ニュースワイヤーを編集",
"Add RSS feed links below.": "以下にRSSフィードリンクを追加します。", "Add RSS feed links below.": "以下にRSSフィードリンクを追加します。",
"Newswire RSS Feed": "NewswireRSSフィード" "Newswire RSS Feed": "NewswireRSSフィード",
"Nicknames whose blog entries appear on the newswire.": "ブログエントリがニュースワイヤーに表示されるニックネーム。"
} }

View File

@ -292,5 +292,6 @@
"RSS feed for this site": "RSS feed for this site", "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.", "Add RSS feed links below.": "Add RSS feed links below.",
"Newswire RSS Feed": "Newswire RSS Feed" "Newswire RSS Feed": "Newswire RSS Feed",
"Nicknames whose blog entries appear on the newswire.": "Nicknames whose blog entries appear on the newswire."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "Feed RSS para este site", "RSS feed for this site": "Feed RSS para este site",
"Edit newswire": "Editar notícias", "Edit newswire": "Editar notícias",
"Add RSS feed links below.": "Adicione links de feed RSS abaixo.", "Add RSS feed links below.": "Adicione links de feed RSS abaixo.",
"Newswire RSS Feed": "Feed RSS da Newswire" "Newswire RSS Feed": "Feed RSS da Newswire",
"Nicknames whose blog entries appear on the newswire.": "Apelidos cujas entradas de blog aparecem nos jornais."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "RSS-канал для этого сайта", "RSS feed for this site": "RSS-канал для этого сайта",
"Edit newswire": "Редактировать ленту новостей", "Edit newswire": "Редактировать ленту новостей",
"Add RSS feed links below.": "Добавьте ссылки на RSS-канал ниже.", "Add RSS feed links below.": "Добавьте ссылки на RSS-канал ниже.",
"Newswire RSS Feed": "Лента новостей RSS" "Newswire RSS Feed": "Лента новостей RSS",
"Nicknames whose blog entries appear on the newswire.": "Псевдонимы, чьи записи блога появляются в ленте новостей."
} }

View File

@ -296,5 +296,6 @@
"RSS feed for this site": "该站点的RSS feed", "RSS feed for this site": "该站点的RSS feed",
"Edit newswire": "编辑新闻专线", "Edit newswire": "编辑新闻专线",
"Add RSS feed links below.": "在下面添加RSS feed链接。", "Add RSS feed links below.": "在下面添加RSS feed链接。",
"Newswire RSS Feed": "Newswire RSS提要" "Newswire RSS Feed": "Newswire RSS提要",
"Nicknames whose blog entries appear on the newswire.": "博客条目出现在新闻专线上的昵称。"
} }

View File

@ -687,7 +687,7 @@ def htmlModerationInfo(translate: {}, baseDir: str, httpPrefix: str) -> str:
translate[msgStr1] translate[msgStr1]
infoForm += \ infoForm += \
' <textarea id="message" ' + \ ' <textarea id="message" ' + \
'name="blocked" style="height:400px">' + \ 'name="blocked" style="height:700px">' + \
blockedStr + '</textarea>' blockedStr + '</textarea>'
infoForm += '</div>' infoForm += '</div>'
infoShown = True infoShown = True
@ -1326,6 +1326,13 @@ def htmlEditNewswire(translate: {}, baseDir: str, path: str,
with open(newswireFilename, 'r') as fp: with open(newswireFilename, 'r') as fp:
newswireStr = fp.read() newswireStr = fp.read()
# get the list of handles who are trusted to post to the newswire
newswireTrusted = ''
newswireTrustedFilename = baseDir + '/accounts/newswiretrusted.txt'
if os.path.isfile(newswireTrustedFilename):
with open(newswireTrustedFilename, "r") as trustFile:
newswireTrusted = trustFile.read()
editNewswireForm += \ editNewswireForm += \
'<div class="container">' '<div class="container">'
editNewswireForm += \ editNewswireForm += \
@ -1335,6 +1342,15 @@ def htmlEditNewswire(translate: {}, baseDir: str, path: str,
editNewswireForm += \ editNewswireForm += \
' <textarea id="message" name="editedNewswire" ' + \ ' <textarea id="message" name="editedNewswire" ' + \
'style="height:500px">' + newswireStr + '</textarea>' 'style="height:500px">' + newswireStr + '</textarea>'
editNewswireForm += \
' ' + \
translate['Nicknames whose blog entries appear on the newswire.'] + \
'<br>'
editNewswireForm += \
' <textarea id="message" name="trustedNewswire" ' + \
'style="height:500px">' + newswireTrusted + '</textarea>'
editNewswireForm += \ editNewswireForm += \
'</div>' '</div>'
@ -5342,8 +5358,19 @@ def htmlNewswire(newswire: str) -> str:
""" """
htmlStr = '' htmlStr = ''
for dateStr, item in newswire.items(): for dateStr, item in newswire.items():
htmlStr += '<p class="newswireItem">' + \ # if the item is to be moderated then show it in a different style
'<a href="' + item[1] + '">' + item[0] + '</a>' shown = False
if len(item) > 2:
if item[2].startswith('moderate'):
moderationUrl = '/moderate?' + item[1]
htmlStr += '<p class="newswireItemModerate">' + \
'<a href="' + moderationUrl + '">' + item[0] + '</a>'
shown = True
if not shown:
# unmoderated item
htmlStr += '<p class="newswireItem">' + \
'<a href="' + item[1] + '">' + item[0] + '</a>'
htmlStr += ' <label class="newswireDate">' htmlStr += ' <label class="newswireDate">'
htmlStr += dateStr.replace('+00:00', '') + '</label></p>' htmlStr += dateStr.replace('+00:00', '') + '</label></p>'
return htmlStr return htmlStr

View File

@ -1168,7 +1168,7 @@
<th><a href="img/screenshot_hacker.jpg"><img width="90%" src="img/screenshot_hacker.jpg" alt="hacker theme profile page" /></a></th> <th><a href="img/screenshot_hacker.jpg"><img width="90%" src="img/screenshot_hacker.jpg" alt="hacker theme profile page" /></a></th>
</tr> </tr>
<tr> <tr>
<th><img width="90%" src="img/screenshots.jpg" alt="various screenshots" /></th> <th><a href="img/screenshot_indymedia.jpg"><img width="120%" src="img/screenshots.jpg" alt="various screenshots" /></a></th>
<th><img width="50%" src="img/mobile.jpg" alt="mobile screenshot" /></th> <th><img width="50%" src="img/mobile.jpg" alt="mobile screenshot" /></th>
</tr> </tr>
<tr> <tr>