mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main
commit
4f1396b9ac
|
|
@ -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>
|
||||
|
||||
<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%"/>
|
||||
|
||||
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.
|
||||
|
|
|
|||
13
daemon.py
13
daemon.py
|
|
@ -2893,6 +2893,19 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
if os.path.isfile(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
|
||||
if callingDomain.endswith('.onion') and \
|
||||
onionDomain:
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
--quote-font-size: 120%;
|
||||
--line-spacing: 130%;
|
||||
--line-spacing-newswire: 100%;
|
||||
--newswire-moderate-color: yellow;
|
||||
--column-left-width: 10vw;
|
||||
--column-center-width: 80vw;
|
||||
--column-right-width: 10vw;
|
||||
|
|
@ -231,6 +232,13 @@ a:focus {
|
|||
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 {
|
||||
font-size: var(--font-size-newswire);
|
||||
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 |
109
newswire.py
109
newswire.py
|
|
@ -13,6 +13,8 @@ from socket import error as SocketError
|
|||
import errno
|
||||
from datetime import datetime
|
||||
from collections import OrderedDict
|
||||
from utils import locatePost
|
||||
from utils import loadJson
|
||||
|
||||
|
||||
def rss2Header(httpPrefix: str,
|
||||
|
|
@ -162,6 +164,107 @@ def getRSSfromDict(baseDir: str, newswire: {},
|
|||
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) -> {}:
|
||||
"""Gets rss feeds as a dictionary from newswire file
|
||||
"""
|
||||
|
|
@ -169,6 +272,7 @@ def getDictFromNewswire(session, baseDir: str) -> {}:
|
|||
if not os.path.isfile(subscriptionsFilename):
|
||||
return {}
|
||||
|
||||
# add rss feeds
|
||||
rssFeed = []
|
||||
with open(subscriptionsFilename, 'r') as fp:
|
||||
rssFeed = fp.readlines()
|
||||
|
|
@ -182,6 +286,11 @@ def getDictFromNewswire(session, baseDir: str) -> {}:
|
|||
itemsList = getRSS(session, url)
|
||||
for dateStr, item in itemsList.items():
|
||||
result[dateStr] = item
|
||||
|
||||
# add local content
|
||||
addLocalBlogsToNewswire(baseDir, result, 5)
|
||||
|
||||
# sort into chronological order, latest first
|
||||
sortedResult = OrderedDict(sorted(result.items(), reverse=True))
|
||||
return sortedResult
|
||||
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "تغذية RSS لهذا الموقع",
|
||||
"Edit newswire": "تحرير الأخبار",
|
||||
"Add RSS feed links below.": "إضافة روابط تغذية RSS أدناه.",
|
||||
"Newswire RSS Feed": "Newswire موجز RSS"
|
||||
"Newswire RSS Feed": "Newswire موجز RSS",
|
||||
"Nicknames whose blog entries appear on the newswire.": "الألقاب التي تظهر إدخالات المدونة الخاصة بها على موقع الأخبار."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "Feed RSS per a aquest lloc",
|
||||
"Edit newswire": "Editeu newswire",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "Porthiant RSS ar gyfer y wefan hon",
|
||||
"Edit newswire": "Golygu newyddion",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "RSS-Feed für diese Site",
|
||||
"Edit newswire": "Newswire bearbeiten",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 Feed"
|
||||
"Newswire RSS Feed": "Newswire RSS Feed",
|
||||
"Nicknames whose blog entries appear on the newswire.": "Nicknames whose blog entries appear on the newswire."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "Fuente RSS para este sitio",
|
||||
"Edit newswire": "Editar newswire",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "Flux RSS de ce site",
|
||||
"Edit newswire": "Modifier le fil d'actualité",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "Fotha RSS don láithreán seo",
|
||||
"Edit newswire": "Cuir sreang nuachta in eagar",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "इस साइट के लिए आरएसएस फ़ीड",
|
||||
"Edit newswire": "नवांश संपादित करें",
|
||||
"Add RSS feed links below.": "नीचे आरएसएस फ़ीड लिंक जोड़ें।",
|
||||
"Newswire RSS Feed": "Newswire RSS फ़ीड"
|
||||
"Newswire RSS Feed": "Newswire RSS फ़ीड",
|
||||
"Nicknames whose blog entries appear on the newswire.": "उपनाम जिनकी ब्लॉग प्रविष्टियाँ न्यूज़वायर पर दिखाई देती हैं।"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "Feed RSS per questo sito",
|
||||
"Edit newswire": "Modifica newswire",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "このサイトのRSSフィード",
|
||||
"Edit newswire": "ニュースワイヤーを編集",
|
||||
"Add RSS feed links below.": "以下にRSSフィードリンクを追加します。",
|
||||
"Newswire RSS Feed": "NewswireRSSフィード"
|
||||
"Newswire RSS Feed": "NewswireRSSフィード",
|
||||
"Nicknames whose blog entries appear on the newswire.": "ブログエントリがニュースワイヤーに表示されるニックネーム。"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -292,5 +292,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 Feed"
|
||||
"Newswire RSS Feed": "Newswire RSS Feed",
|
||||
"Nicknames whose blog entries appear on the newswire.": "Nicknames whose blog entries appear on the newswire."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "Feed RSS para este site",
|
||||
"Edit newswire": "Editar notícias",
|
||||
"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."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "RSS-канал для этого сайта",
|
||||
"Edit newswire": "Редактировать ленту новостей",
|
||||
"Add RSS feed links below.": "Добавьте ссылки на RSS-канал ниже.",
|
||||
"Newswire RSS Feed": "Лента новостей RSS"
|
||||
"Newswire RSS Feed": "Лента новостей RSS",
|
||||
"Nicknames whose blog entries appear on the newswire.": "Псевдонимы, чьи записи блога появляются в ленте новостей."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,5 +296,6 @@
|
|||
"RSS feed for this site": "该站点的RSS feed",
|
||||
"Edit newswire": "编辑新闻专线",
|
||||
"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.": "博客条目出现在新闻专线上的昵称。"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -687,7 +687,7 @@ def htmlModerationInfo(translate: {}, baseDir: str, httpPrefix: str) -> str:
|
|||
translate[msgStr1]
|
||||
infoForm += \
|
||||
' <textarea id="message" ' + \
|
||||
'name="blocked" style="height:400px">' + \
|
||||
'name="blocked" style="height:700px">' + \
|
||||
blockedStr + '</textarea>'
|
||||
infoForm += '</div>'
|
||||
infoShown = True
|
||||
|
|
@ -1326,6 +1326,13 @@ def htmlEditNewswire(translate: {}, baseDir: str, path: str,
|
|||
with open(newswireFilename, 'r') as fp:
|
||||
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 += \
|
||||
'<div class="container">'
|
||||
editNewswireForm += \
|
||||
|
|
@ -1335,6 +1342,15 @@ def htmlEditNewswire(translate: {}, baseDir: str, path: str,
|
|||
editNewswireForm += \
|
||||
' <textarea id="message" name="editedNewswire" ' + \
|
||||
'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 += \
|
||||
'</div>'
|
||||
|
||||
|
|
@ -5342,6 +5358,17 @@ def htmlNewswire(newswire: str) -> str:
|
|||
"""
|
||||
htmlStr = ''
|
||||
for dateStr, item in newswire.items():
|
||||
# if the item is to be moderated then show it in a different style
|
||||
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">'
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
</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>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
|||
Loading…
Reference in New Issue