mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main
commit
f38cbd22b8
|
|
@ -53,7 +53,7 @@ sudo apt install -y \
|
||||||
|
|
||||||
In the most common case you'll be using systemd to set up a daemon to run the server.
|
In the most common case you'll be using systemd to set up a daemon to run the server.
|
||||||
|
|
||||||
The following instructions install Epicyon to the **/etc** directory. It's not essential that it be installed there, and it could be in any other preferred directory.
|
The following instructions install Epicyon to the **/opt** directory. It's not essential that it be installed there, and it could be in any other preferred directory.
|
||||||
|
|
||||||
Add a dedicated user so that we don't have to run as root.
|
Add a dedicated user so that we don't have to run as root.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12222,7 +12222,8 @@ def loadTokens(baseDir: str, tokensDict: {}, tokensLookup: {}) -> None:
|
||||||
tokensLookup[token] = nickname
|
tokensLookup[token] = nickname
|
||||||
|
|
||||||
|
|
||||||
def runDaemon(publishButtonAtTop: bool,
|
def runDaemon(maxFeedItemSizeKb: int,
|
||||||
|
publishButtonAtTop: bool,
|
||||||
rssIconAtTop: bool,
|
rssIconAtTop: bool,
|
||||||
iconsAsButtons: bool,
|
iconsAsButtons: bool,
|
||||||
fullWidthTimelineButtonHeader: bool,
|
fullWidthTimelineButtonHeader: bool,
|
||||||
|
|
@ -12400,6 +12401,9 @@ def runDaemon(publishButtonAtTop: bool,
|
||||||
# above the header image
|
# above the header image
|
||||||
httpd.publishButtonAtTop = publishButtonAtTop
|
httpd.publishButtonAtTop = publishButtonAtTop
|
||||||
|
|
||||||
|
# maximum size of individual RSS feed items, in K
|
||||||
|
httpd.maxFeedItemSizeKb = maxFeedItemSizeKb
|
||||||
|
|
||||||
if registration == 'open':
|
if registration == 'open':
|
||||||
httpd.registration = True
|
httpd.registration = True
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
15
epicyon.py
15
epicyon.py
|
|
@ -118,8 +118,13 @@ parser.add_argument('--postsPerSource',
|
||||||
help='Maximum newswire posts per feed or account')
|
help='Maximum newswire posts per feed or account')
|
||||||
parser.add_argument('--maxFeedSize',
|
parser.add_argument('--maxFeedSize',
|
||||||
dest='maxNewswireFeedSizeKb', type=int,
|
dest='maxNewswireFeedSizeKb', type=int,
|
||||||
default=2048,
|
default=10240,
|
||||||
help='Maximum newswire rss/atom feed size in K')
|
help='Maximum newswire rss/atom feed size in K')
|
||||||
|
parser.add_argument('--maxFeedItemSizeKb',
|
||||||
|
dest='maxFeedItemSizeKb', type=int,
|
||||||
|
default=2048,
|
||||||
|
help='Maximum size of an individual rss/atom ' +
|
||||||
|
'feed item in K')
|
||||||
parser.add_argument('--maxMirroredArticles',
|
parser.add_argument('--maxMirroredArticles',
|
||||||
dest='maxMirroredArticles', type=int,
|
dest='maxMirroredArticles', type=int,
|
||||||
default=100,
|
default=100,
|
||||||
|
|
@ -2010,6 +2015,11 @@ maxFollowers = \
|
||||||
if maxFollowers is not None:
|
if maxFollowers is not None:
|
||||||
args.maxFollowers = int(maxFollowers)
|
args.maxFollowers = int(maxFollowers)
|
||||||
|
|
||||||
|
maxFeedItemSizeKb = \
|
||||||
|
getConfigParam(baseDir, 'maxFeedItemSizeKb')
|
||||||
|
if maxFeedItemSizeKb is not None:
|
||||||
|
args.maxFeedItemSizeKb = int(maxFeedItemSizeKb)
|
||||||
|
|
||||||
allowNewsFollowers = \
|
allowNewsFollowers = \
|
||||||
getConfigParam(baseDir, 'allowNewsFollowers')
|
getConfigParam(baseDir, 'allowNewsFollowers')
|
||||||
if allowNewsFollowers is not None:
|
if allowNewsFollowers is not None:
|
||||||
|
|
@ -2053,7 +2063,8 @@ if setTheme(baseDir, themeName, domain):
|
||||||
print('Theme set to ' + themeName)
|
print('Theme set to ' + themeName)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
runDaemon(args.publishButtonAtTop,
|
runDaemon(args.maxFeedItemSizeKb,
|
||||||
|
args.publishButtonAtTop,
|
||||||
args.rssIconAtTop,
|
args.rssIconAtTop,
|
||||||
args.iconsAsButtons,
|
args.iconsAsButtons,
|
||||||
args.fullWidthTimelineButtonHeader,
|
args.fullWidthTimelineButtonHeader,
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ from utils import saveJson
|
||||||
from utils import getStatusNumber
|
from utils import getStatusNumber
|
||||||
from utils import clearFromPostCaches
|
from utils import clearFromPostCaches
|
||||||
from inbox import storeHashTags
|
from inbox import storeHashTags
|
||||||
|
from session import createSession
|
||||||
|
|
||||||
|
|
||||||
def updateFeedsOutboxIndex(baseDir: str, domain: str, postId: str) -> None:
|
def updateFeedsOutboxIndex(baseDir: str, domain: str, postId: str) -> None:
|
||||||
|
|
@ -471,6 +472,9 @@ def convertRSStoActivityPub(baseDir: str, httpPrefix: str,
|
||||||
maxMirroredArticles: int) -> None:
|
maxMirroredArticles: int) -> None:
|
||||||
"""Converts rss items in a newswire into posts
|
"""Converts rss items in a newswire into posts
|
||||||
"""
|
"""
|
||||||
|
if not newswire:
|
||||||
|
return
|
||||||
|
|
||||||
basePath = baseDir + '/accounts/news@' + domain + '/outbox'
|
basePath = baseDir + '/accounts/news@' + domain + '/outbox'
|
||||||
if not os.path.isdir(basePath):
|
if not os.path.isdir(basePath):
|
||||||
os.mkdir(basePath)
|
os.mkdir(basePath)
|
||||||
|
|
@ -669,6 +673,9 @@ def mergeWithPreviousNewswire(oldNewswire: {}, newNewswire: {}) -> None:
|
||||||
"""Preserve any votes or generated activitypub post filename
|
"""Preserve any votes or generated activitypub post filename
|
||||||
as rss feeds are updated
|
as rss feeds are updated
|
||||||
"""
|
"""
|
||||||
|
if not oldNewswire:
|
||||||
|
return
|
||||||
|
|
||||||
for published, fields in oldNewswire.items():
|
for published, fields in oldNewswire.items():
|
||||||
if not newNewswire.get(published):
|
if not newNewswire.get(published):
|
||||||
continue
|
continue
|
||||||
|
|
@ -689,8 +696,13 @@ def runNewswireDaemon(baseDir: str, httpd,
|
||||||
# has the session been created yet?
|
# has the session been created yet?
|
||||||
if not httpd.session:
|
if not httpd.session:
|
||||||
print('Newswire daemon waiting for session')
|
print('Newswire daemon waiting for session')
|
||||||
time.sleep(60)
|
httpd.session = createSession(httpd.proxyType)
|
||||||
continue
|
if not httpd.session:
|
||||||
|
print('Newswire daemon has no session')
|
||||||
|
time.sleep(60)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
print('Newswire daemon session established')
|
||||||
|
|
||||||
# try to update the feeds
|
# try to update the feeds
|
||||||
newNewswire = None
|
newNewswire = None
|
||||||
|
|
@ -699,7 +711,8 @@ def runNewswireDaemon(baseDir: str, httpd,
|
||||||
getDictFromNewswire(httpd.session, baseDir, domain,
|
getDictFromNewswire(httpd.session, baseDir, domain,
|
||||||
httpd.maxNewswirePostsPerSource,
|
httpd.maxNewswirePostsPerSource,
|
||||||
httpd.maxNewswireFeedSizeKb,
|
httpd.maxNewswireFeedSizeKb,
|
||||||
httpd.maxTags)
|
httpd.maxTags,
|
||||||
|
httpd.maxFeedItemSizeKb)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('WARN: unable to update newswire ' + str(e))
|
print('WARN: unable to update newswire ' + str(e))
|
||||||
time.sleep(120)
|
time.sleep(120)
|
||||||
|
|
|
||||||
41
newswire.py
41
newswire.py
|
|
@ -126,7 +126,8 @@ def addNewswireDictEntry(baseDir: str, domain: str,
|
||||||
|
|
||||||
def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
|
def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
|
||||||
moderated: bool, mirrored: bool,
|
moderated: bool, mirrored: bool,
|
||||||
maxPostsPerSource: int) -> {}:
|
maxPostsPerSource: int,
|
||||||
|
maxFeedItemSizeKb: int) -> {}:
|
||||||
"""Converts an xml 2.0 string to a dictionary
|
"""Converts an xml 2.0 string to a dictionary
|
||||||
"""
|
"""
|
||||||
if '<item>' not in xmlStr:
|
if '<item>' not in xmlStr:
|
||||||
|
|
@ -134,7 +135,11 @@ def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
|
||||||
result = {}
|
result = {}
|
||||||
rssItems = xmlStr.split('<item>')
|
rssItems = xmlStr.split('<item>')
|
||||||
postCtr = 0
|
postCtr = 0
|
||||||
|
maxBytes = maxFeedItemSizeKb * 1024
|
||||||
for rssItem in rssItems:
|
for rssItem in rssItems:
|
||||||
|
if len(rssItem) > maxBytes:
|
||||||
|
print('WARN: rss feed item is too big')
|
||||||
|
continue
|
||||||
if '<title>' not in rssItem:
|
if '<title>' not in rssItem:
|
||||||
continue
|
continue
|
||||||
if '</title>' not in rssItem:
|
if '</title>' not in rssItem:
|
||||||
|
|
@ -205,7 +210,8 @@ def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
|
||||||
|
|
||||||
def atomFeedToDict(baseDir: str, domain: str, xmlStr: str,
|
def atomFeedToDict(baseDir: str, domain: str, xmlStr: str,
|
||||||
moderated: bool, mirrored: bool,
|
moderated: bool, mirrored: bool,
|
||||||
maxPostsPerSource: int) -> {}:
|
maxPostsPerSource: int,
|
||||||
|
maxFeedItemSizeKb: int) -> {}:
|
||||||
"""Converts an atom feed string to a dictionary
|
"""Converts an atom feed string to a dictionary
|
||||||
"""
|
"""
|
||||||
if '<entry>' not in xmlStr:
|
if '<entry>' not in xmlStr:
|
||||||
|
|
@ -213,7 +219,11 @@ def atomFeedToDict(baseDir: str, domain: str, xmlStr: str,
|
||||||
result = {}
|
result = {}
|
||||||
rssItems = xmlStr.split('<entry>')
|
rssItems = xmlStr.split('<entry>')
|
||||||
postCtr = 0
|
postCtr = 0
|
||||||
|
maxBytes = maxFeedItemSizeKb * 1024
|
||||||
for rssItem in rssItems:
|
for rssItem in rssItems:
|
||||||
|
if len(rssItem) > maxBytes:
|
||||||
|
print('WARN: atom feed item is too big')
|
||||||
|
continue
|
||||||
if '<title>' not in rssItem:
|
if '<title>' not in rssItem:
|
||||||
continue
|
continue
|
||||||
if '</title>' not in rssItem:
|
if '</title>' not in rssItem:
|
||||||
|
|
@ -283,21 +293,25 @@ def atomFeedToDict(baseDir: str, domain: str, xmlStr: str,
|
||||||
|
|
||||||
def xmlStrToDict(baseDir: str, domain: str, xmlStr: str,
|
def xmlStrToDict(baseDir: str, domain: str, xmlStr: str,
|
||||||
moderated: bool, mirrored: bool,
|
moderated: bool, mirrored: bool,
|
||||||
maxPostsPerSource: int) -> {}:
|
maxPostsPerSource: int,
|
||||||
|
maxFeedItemSizeKb: int) -> {}:
|
||||||
"""Converts an xml string to a dictionary
|
"""Converts an xml string to a dictionary
|
||||||
"""
|
"""
|
||||||
if 'rss version="2.0"' in xmlStr:
|
if 'rss version="2.0"' in xmlStr:
|
||||||
return xml2StrToDict(baseDir, domain,
|
return xml2StrToDict(baseDir, domain,
|
||||||
xmlStr, moderated, mirrored, maxPostsPerSource)
|
xmlStr, moderated, mirrored,
|
||||||
|
maxPostsPerSource, maxFeedItemSizeKb)
|
||||||
elif 'xmlns="http://www.w3.org/2005/Atom"' in xmlStr:
|
elif 'xmlns="http://www.w3.org/2005/Atom"' in xmlStr:
|
||||||
return atomFeedToDict(baseDir, domain,
|
return atomFeedToDict(baseDir, domain,
|
||||||
xmlStr, moderated, mirrored, maxPostsPerSource)
|
xmlStr, moderated, mirrored,
|
||||||
|
maxPostsPerSource, maxFeedItemSizeKb)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def getRSS(baseDir: str, domain: str, session, url: str,
|
def getRSS(baseDir: str, domain: str, session, url: str,
|
||||||
moderated: bool, mirrored: bool,
|
moderated: bool, mirrored: bool,
|
||||||
maxPostsPerSource: int, maxFeedSizeKb: int) -> {}:
|
maxPostsPerSource: int, maxFeedSizeKb: int,
|
||||||
|
maxFeedItemSizeKb: int) -> {}:
|
||||||
"""Returns an RSS url as a dict
|
"""Returns an RSS url as a dict
|
||||||
"""
|
"""
|
||||||
if not isinstance(url, str):
|
if not isinstance(url, str):
|
||||||
|
|
@ -325,7 +339,8 @@ def getRSS(baseDir: str, domain: str, session, url: str,
|
||||||
not containsInvalidChars(result.text):
|
not containsInvalidChars(result.text):
|
||||||
return xmlStrToDict(baseDir, domain, result.text,
|
return xmlStrToDict(baseDir, domain, result.text,
|
||||||
moderated, mirrored,
|
moderated, mirrored,
|
||||||
maxPostsPerSource)
|
maxPostsPerSource,
|
||||||
|
maxFeedItemSizeKb)
|
||||||
else:
|
else:
|
||||||
print('WARN: feed is too large: ' + url)
|
print('WARN: feed is too large: ' + url)
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
|
|
@ -354,6 +369,8 @@ def getRSSfromDict(baseDir: str, newswire: {},
|
||||||
rssStr = rss2Header(httpPrefix,
|
rssStr = rss2Header(httpPrefix,
|
||||||
None, domainFull,
|
None, domainFull,
|
||||||
'Newswire', translate)
|
'Newswire', translate)
|
||||||
|
if not newswire:
|
||||||
|
return ''
|
||||||
for published, fields in newswire.items():
|
for published, fields in newswire.items():
|
||||||
if '+00:00' in published:
|
if '+00:00' in published:
|
||||||
published = published.replace('+00:00', 'Z').strip()
|
published = published.replace('+00:00', 'Z').strip()
|
||||||
|
|
@ -547,7 +564,7 @@ def addBlogsToNewswire(baseDir: str, domain: str, newswire: {},
|
||||||
|
|
||||||
def getDictFromNewswire(session, baseDir: str, domain: str,
|
def getDictFromNewswire(session, baseDir: str, domain: str,
|
||||||
maxPostsPerSource: int, maxFeedSizeKb: int,
|
maxPostsPerSource: int, maxFeedSizeKb: int,
|
||||||
maxTags: int) -> {}:
|
maxTags: int, maxFeedItemSizeKb: int) -> {}:
|
||||||
"""Gets rss feeds as a dictionary from newswire file
|
"""Gets rss feeds as a dictionary from newswire file
|
||||||
"""
|
"""
|
||||||
subscriptionsFilename = baseDir + '/accounts/newswire.txt'
|
subscriptionsFilename = baseDir + '/accounts/newswire.txt'
|
||||||
|
|
@ -586,9 +603,11 @@ def getDictFromNewswire(session, baseDir: str, domain: str,
|
||||||
|
|
||||||
itemsList = getRSS(baseDir, domain, session, url,
|
itemsList = getRSS(baseDir, domain, session, url,
|
||||||
moderated, mirrored,
|
moderated, mirrored,
|
||||||
maxPostsPerSource, maxFeedSizeKb)
|
maxPostsPerSource, maxFeedSizeKb,
|
||||||
for dateStr, item in itemsList.items():
|
maxFeedItemSizeKb)
|
||||||
result[dateStr] = item
|
if itemsList:
|
||||||
|
for dateStr, item in itemsList.items():
|
||||||
|
result[dateStr] = item
|
||||||
|
|
||||||
# add blogs from each user account
|
# add blogs from each user account
|
||||||
addBlogsToNewswire(baseDir, domain, result,
|
addBlogsToNewswire(baseDir, domain, result,
|
||||||
|
|
|
||||||
6
tests.py
6
tests.py
|
|
@ -291,7 +291,7 @@ def createServerAlice(path: str, domain: str, port: int,
|
||||||
onionDomain = None
|
onionDomain = None
|
||||||
i2pDomain = None
|
i2pDomain = None
|
||||||
print('Server running: Alice')
|
print('Server running: Alice')
|
||||||
runDaemon(False, True, False, False, True, 10, False,
|
runDaemon(2048, False, True, False, False, True, 10, False,
|
||||||
0, 100, 1024, 5, False,
|
0, 100, 1024, 5, False,
|
||||||
0, False, 1, False, False, False,
|
0, False, 1, False, False, False,
|
||||||
5, True, True, 'en', __version__,
|
5, True, True, 'en', __version__,
|
||||||
|
|
@ -356,7 +356,7 @@ def createServerBob(path: str, domain: str, port: int,
|
||||||
onionDomain = None
|
onionDomain = None
|
||||||
i2pDomain = None
|
i2pDomain = None
|
||||||
print('Server running: Bob')
|
print('Server running: Bob')
|
||||||
runDaemon(False, True, False, False, True, 10, False,
|
runDaemon(2048, False, True, False, False, True, 10, False,
|
||||||
0, 100, 1024, 5, False, 0,
|
0, 100, 1024, 5, False, 0,
|
||||||
False, 1, False, False, False,
|
False, 1, False, False, False,
|
||||||
5, True, True, 'en', __version__,
|
5, True, True, 'en', __version__,
|
||||||
|
|
@ -395,7 +395,7 @@ def createServerEve(path: str, domain: str, port: int, federationList: [],
|
||||||
onionDomain = None
|
onionDomain = None
|
||||||
i2pDomain = None
|
i2pDomain = None
|
||||||
print('Server running: Eve')
|
print('Server running: Eve')
|
||||||
runDaemon(False, True, False, False, True, 10, False,
|
runDaemon(2048, False, True, False, False, True, 10, False,
|
||||||
0, 100, 1024, 5, False, 0,
|
0, 100, 1024, 5, False, 0,
|
||||||
False, 1, False, False, False,
|
False, 1, False, False, False,
|
||||||
5, True, True, 'en', __version__,
|
5, True, True, 'en', __version__,
|
||||||
|
|
|
||||||
111
webinterface.py
111
webinterface.py
|
|
@ -3557,9 +3557,10 @@ def htmlProfile(rssIconAtTop: bool,
|
||||||
|
|
||||||
# If this is the news account then show a different banner
|
# If this is the news account then show a different banner
|
||||||
if isSystemAccount(nickname):
|
if isSystemAccount(nickname):
|
||||||
|
bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain)
|
||||||
profileHeaderStr = \
|
profileHeaderStr = \
|
||||||
'<img loading="lazy" class="timeline-banner" ' + \
|
'<img loading="lazy" class="timeline-banner" ' + \
|
||||||
'src="/users/news/banner.png" />\n'
|
'src="/users/' + nickname + '/' + bannerFile + '" />\n'
|
||||||
if loginButton:
|
if loginButton:
|
||||||
profileHeaderStr += '<center>' + loginButton + '</center>\n'
|
profileHeaderStr += '<center>' + loginButton + '</center>\n'
|
||||||
|
|
||||||
|
|
@ -5604,20 +5605,24 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
|
|
||||||
editImageClass = ''
|
editImageClass = ''
|
||||||
if showHeaderImage:
|
if showHeaderImage:
|
||||||
leftColumnImageFilename = \
|
leftImageFile, leftColumnImageFilename = \
|
||||||
baseDir + '/accounts/' + nickname + '@' + domain + \
|
getLeftImageFile(baseDir, nickname, domain)
|
||||||
'/left_col_image.png'
|
|
||||||
if not os.path.isfile(leftColumnImageFilename):
|
if not os.path.isfile(leftColumnImageFilename):
|
||||||
theme = getConfigParam(baseDir, 'theme').lower()
|
theme = getConfigParam(baseDir, 'theme').lower()
|
||||||
if theme == 'default':
|
if theme == 'default':
|
||||||
theme = ''
|
theme = ''
|
||||||
else:
|
else:
|
||||||
theme = '_' + theme
|
theme = '_' + theme
|
||||||
themeLeftColumnImageFilename = \
|
themeLeftImageFile, themeLeftColumnImageFilename = \
|
||||||
baseDir + '/img/left_col_image' + theme + '.png'
|
getImageFile(baseDir, 'left_col_image', baseDir + '/img',
|
||||||
|
nickname, domain)
|
||||||
if os.path.isfile(themeLeftColumnImageFilename):
|
if os.path.isfile(themeLeftColumnImageFilename):
|
||||||
|
leftColumnImageFilename = \
|
||||||
|
baseDir + '/accounts/' + \
|
||||||
|
nickname + '@' + domain + '/' + themeLeftImageFile
|
||||||
copyfile(themeLeftColumnImageFilename,
|
copyfile(themeLeftColumnImageFilename,
|
||||||
leftColumnImageFilename)
|
leftColumnImageFilename)
|
||||||
|
leftImageFile = themeLeftImageFile
|
||||||
|
|
||||||
# show the image at the top of the column
|
# show the image at the top of the column
|
||||||
editImageClass = 'leftColEdit'
|
editImageClass = 'leftColEdit'
|
||||||
|
|
@ -5627,7 +5632,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
'\n <center>\n' + \
|
'\n <center>\n' + \
|
||||||
' <img class="leftColImg" ' + \
|
' <img class="leftColImg" ' + \
|
||||||
'loading="lazy" src="/users/' + \
|
'loading="lazy" src="/users/' + \
|
||||||
nickname + '/left_col_image.png" />\n' + \
|
nickname + '/' + leftImageFile + '" />\n' + \
|
||||||
' </center>\n'
|
' </center>\n'
|
||||||
|
|
||||||
if showBackButton:
|
if showBackButton:
|
||||||
|
|
@ -5858,20 +5863,24 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
# show a column header image, eg. title of the theme or newswire banner
|
# show a column header image, eg. title of the theme or newswire banner
|
||||||
editImageClass = ''
|
editImageClass = ''
|
||||||
if showHeaderImage:
|
if showHeaderImage:
|
||||||
rightColumnImageFilename = \
|
rightImageFile, rightColumnImageFilename = \
|
||||||
baseDir + '/accounts/' + nickname + '@' + domain + \
|
getRightImageFile(baseDir, nickname, domain)
|
||||||
'/right_col_image.png'
|
|
||||||
if not os.path.isfile(rightColumnImageFilename):
|
if not os.path.isfile(rightColumnImageFilename):
|
||||||
theme = getConfigParam(baseDir, 'theme').lower()
|
theme = getConfigParam(baseDir, 'theme').lower()
|
||||||
if theme == 'default':
|
if theme == 'default':
|
||||||
theme = ''
|
theme = ''
|
||||||
else:
|
else:
|
||||||
theme = '_' + theme
|
theme = '_' + theme
|
||||||
themeRightColumnImageFilename = \
|
themeRightImageFile, themeRightColumnImageFilename = \
|
||||||
baseDir + '/img/right_col_image' + theme + '.png'
|
getImageFile(baseDir, 'right_col_image', baseDir + '/img',
|
||||||
|
nickname, domain)
|
||||||
if os.path.isfile(themeRightColumnImageFilename):
|
if os.path.isfile(themeRightColumnImageFilename):
|
||||||
|
rightColumnImageFilename = \
|
||||||
|
baseDir + '/accounts/' + \
|
||||||
|
nickname + '@' + domain + '/' + themeRightImageFile
|
||||||
copyfile(themeRightColumnImageFilename,
|
copyfile(themeRightColumnImageFilename,
|
||||||
rightColumnImageFilename)
|
rightColumnImageFilename)
|
||||||
|
rightImageFile = themeRightImageFile
|
||||||
|
|
||||||
# show the image at the top of the column
|
# show the image at the top of the column
|
||||||
editImageClass = 'rightColEdit'
|
editImageClass = 'rightColEdit'
|
||||||
|
|
@ -5881,7 +5890,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
'\n <center>\n' + \
|
'\n <center>\n' + \
|
||||||
' <img class="rightColImg" ' + \
|
' <img class="rightColImg" ' + \
|
||||||
'loading="lazy" src="/users/' + \
|
'loading="lazy" src="/users/' + \
|
||||||
nickname + '/right_col_image.png" />\n' + \
|
nickname + '/' + rightImageFile + '" />\n' + \
|
||||||
' </center>\n'
|
' </center>\n'
|
||||||
|
|
||||||
if (showPublishButton or editor or rssIconAtTop) and not showHeaderImage:
|
if (showPublishButton or editor or rssIconAtTop) and not showHeaderImage:
|
||||||
|
|
@ -6000,11 +6009,16 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
||||||
else:
|
else:
|
||||||
editor = isEditor(baseDir, nickname)
|
editor = isEditor(baseDir, nickname)
|
||||||
|
|
||||||
|
domain = domainFull
|
||||||
|
if ':' in domain:
|
||||||
|
domain = domain.split(':')[0]
|
||||||
|
|
||||||
htmlStr = htmlHeader(cssFilename, profileStyle)
|
htmlStr = htmlHeader(cssFilename, profileStyle)
|
||||||
|
bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain)
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
'<a href="/users/' + nickname + '/' + defaultTimeline + '">' + \
|
'<a href="/users/' + nickname + '/' + defaultTimeline + '">' + \
|
||||||
'<img loading="lazy" class="timeline-banner" ' + \
|
'<img loading="lazy" class="timeline-banner" ' + \
|
||||||
'src="/users/news/banner.png" /></a>\n'
|
'src="/users/' + nickname + '/' + bannerFile + '" /></a>\n'
|
||||||
|
|
||||||
htmlStr += '<center>' + \
|
htmlStr += '<center>' + \
|
||||||
headerButtonsFrontScreen(translate, nickname,
|
headerButtonsFrontScreen(translate, nickname,
|
||||||
|
|
@ -6063,10 +6077,12 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
|
||||||
showPublishButton = editor
|
showPublishButton = editor
|
||||||
|
|
||||||
htmlStr = htmlHeader(cssFilename, profileStyle)
|
htmlStr = htmlHeader(cssFilename, profileStyle)
|
||||||
|
|
||||||
|
bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain)
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
'<a href="/users/' + nickname + '/' + defaultTimeline + '">' + \
|
'<a href="/users/' + nickname + '/' + defaultTimeline + '">' + \
|
||||||
'<img loading="lazy" class="timeline-banner" ' + \
|
'<img loading="lazy" class="timeline-banner" ' + \
|
||||||
'src="/users/news/banner.png" /></a>\n'
|
'src="/users/' + nickname + '/' + bannerFile + '" /></a>\n'
|
||||||
|
|
||||||
htmlStr += '<center>' + \
|
htmlStr += '<center>' + \
|
||||||
headerButtonsFrontScreen(translate, nickname,
|
headerButtonsFrontScreen(translate, nickname,
|
||||||
|
|
@ -6084,37 +6100,48 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
|
||||||
return htmlStr
|
return htmlStr
|
||||||
|
|
||||||
|
|
||||||
def getBannerFile(baseDir: str, nickname: str, domain: str) -> (str, str):
|
def getImageFile(baseDir: str, name: str, directory: str,
|
||||||
|
nickname: str, domain: str) -> (str, str):
|
||||||
"""
|
"""
|
||||||
returns the banner filename
|
returns the filenames for an image with the given name
|
||||||
"""
|
"""
|
||||||
bannerExtensions = ('png', 'jpg', 'jpeg', 'gif', 'avif', 'webp')
|
bannerExtensions = ('png', 'jpg', 'jpeg', 'gif', 'avif', 'webp')
|
||||||
bannerFile = ''
|
bannerFile = ''
|
||||||
bannerFilename = ''
|
bannerFilename = ''
|
||||||
for ext in bannerExtensions:
|
for ext in bannerExtensions:
|
||||||
bannerFile = 'banner.' + ext
|
bannerFile = name + '.' + ext
|
||||||
bannerFilename = baseDir + '/accounts/' + \
|
bannerFilename = directory + '/' + bannerFile
|
||||||
nickname + '@' + domain + '/' + bannerFile
|
|
||||||
if os.path.isfile(bannerFilename):
|
if os.path.isfile(bannerFilename):
|
||||||
break
|
break
|
||||||
return bannerFile, bannerFilename
|
return bannerFile, bannerFilename
|
||||||
|
|
||||||
|
|
||||||
|
def getBannerFile(baseDir: str,
|
||||||
|
nickname: str, domain: str) -> (str, str):
|
||||||
|
return getImageFile(baseDir, 'banner',
|
||||||
|
baseDir + '/accounts/' + nickname + '@' + domain,
|
||||||
|
nickname, domain)
|
||||||
|
|
||||||
|
|
||||||
def getSearchBannerFile(baseDir: str,
|
def getSearchBannerFile(baseDir: str,
|
||||||
nickname: str, domain: str) -> (str, str):
|
nickname: str, domain: str) -> (str, str):
|
||||||
"""
|
return getImageFile(baseDir, 'search_banner',
|
||||||
returns the search banner filename
|
baseDir + '/accounts/' + nickname + '@' + domain,
|
||||||
"""
|
nickname, domain)
|
||||||
bannerExtensions = ('png', 'jpg', 'jpeg', 'gif', 'avif', 'webp')
|
|
||||||
bannerFile = ''
|
|
||||||
bannerFilename = ''
|
def getLeftImageFile(baseDir: str,
|
||||||
for ext in bannerExtensions:
|
nickname: str, domain: str) -> (str, str):
|
||||||
bannerFile = 'search_banner.' + ext
|
return getImageFile(baseDir, 'left_col_image',
|
||||||
bannerFilename = baseDir + '/accounts/' + \
|
baseDir + '/accounts/' + nickname + '@' + domain,
|
||||||
nickname + '@' + domain + '/' + bannerFile
|
nickname, domain)
|
||||||
if os.path.isfile(bannerFilename):
|
|
||||||
break
|
|
||||||
return bannerFile, bannerFilename
|
def getRightImageFile(baseDir: str,
|
||||||
|
nickname: str, domain: str) -> (str, str):
|
||||||
|
return getImageFile(baseDir, 'right_col_image',
|
||||||
|
baseDir + '/accounts/' + nickname + '@' + domain,
|
||||||
|
nickname, domain)
|
||||||
|
|
||||||
|
|
||||||
def headerButtonsFrontScreen(translate: {},
|
def headerButtonsFrontScreen(translate: {},
|
||||||
|
|
@ -8698,17 +8725,17 @@ def htmlSearch(cssCache: {}, translate: {},
|
||||||
theme = ''
|
theme = ''
|
||||||
else:
|
else:
|
||||||
theme = '_' + theme
|
theme = '_' + theme
|
||||||
bannerExtensions = ('png', 'jpg', 'jpeg', 'gif', 'avif', 'webp')
|
themeSearchImageFile, themeSearchBannerFilename = \
|
||||||
for ext in bannerExtensions:
|
getImageFile(baseDir, 'search_banner', baseDir + '/img',
|
||||||
searchBannerFile = 'search_banner.' + ext
|
searchNickname, domain)
|
||||||
|
if os.path.isfile(themeSearchBannerFilename):
|
||||||
searchBannerFilename = \
|
searchBannerFilename = \
|
||||||
baseDir + '/accounts/' + \
|
baseDir + '/accounts/' + \
|
||||||
searchNickname + '@' + domain + '/' + searchBannerFile
|
searchNickname + '@' + domain + '/' + themeSearchImageFile
|
||||||
themeSearchBannerFilename = \
|
copyfile(themeSearchBannerFilename,
|
||||||
baseDir + '/img/search_banner' + theme + '.' + ext
|
searchBannerFilename)
|
||||||
if os.path.isfile(themeSearchBannerFilename):
|
searchBannerFile = themeSearchImageFile
|
||||||
copyfile(themeSearchBannerFilename, searchBannerFilename)
|
|
||||||
break
|
|
||||||
if os.path.isfile(searchBannerFilename):
|
if os.path.isfile(searchBannerFilename):
|
||||||
usersPath = '/users/' + searchNickname
|
usersPath = '/users/' + searchNickname
|
||||||
followStr += \
|
followStr += \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue