mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main
commit
97ff118508
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Roadman
|
||||||
|
|
||||||
|
## UX
|
||||||
|
* Change animation on buttons (themeable?)
|
||||||
|
|
||||||
|
## Teams
|
||||||
|
|
||||||
|
* Test groups
|
||||||
|
* Groups can be defined as having particular roles/skills
|
||||||
|
* Templates for different group organizations
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
* Events timeline
|
||||||
|
* Events appear on calendar
|
||||||
|
* Check compatibility with Mobilizon
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
* Modularize daemon
|
||||||
|
* Move modules out of the daemon
|
||||||
|
* Make comment notes linking daemon functions to webinterface
|
||||||
|
|
@ -40,7 +40,7 @@ def createAcceptReject(baseDir: str, federationList: [],
|
||||||
newAccept = {
|
newAccept = {
|
||||||
"@context": "https://www.w3.org/ns/activitystreams",
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
'type': acceptType,
|
'type': acceptType,
|
||||||
'actor': httpPrefix+'://'+domain+'/users/'+nickname,
|
'actor': httpPrefix+'://' + domain + '/users/' + nickname,
|
||||||
'to': [toUrl],
|
'to': [toUrl],
|
||||||
'cc': [],
|
'cc': [],
|
||||||
'object': objectJson
|
'object': objectJson
|
||||||
|
|
@ -107,33 +107,33 @@ def acceptFollow(baseDir: str, domain: str, messageJson: {},
|
||||||
thisActor = messageJson['object']['actor']
|
thisActor = messageJson['object']['actor']
|
||||||
nickname = getNicknameFromActor(thisActor)
|
nickname = getNicknameFromActor(thisActor)
|
||||||
if not nickname:
|
if not nickname:
|
||||||
print('WARN: no nickname found in '+thisActor)
|
print('WARN: no nickname found in ' + thisActor)
|
||||||
return
|
return
|
||||||
acceptedDomain, acceptedPort = getDomainFromActor(thisActor)
|
acceptedDomain, acceptedPort = getDomainFromActor(thisActor)
|
||||||
if not acceptedDomain:
|
if not acceptedDomain:
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: domain not found in '+thisActor)
|
print('DEBUG: domain not found in ' + thisActor)
|
||||||
return
|
return
|
||||||
if not nickname:
|
if not nickname:
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: nickname not found in '+thisActor)
|
print('DEBUG: nickname not found in ' + thisActor)
|
||||||
return
|
return
|
||||||
if acceptedPort:
|
if acceptedPort:
|
||||||
if '/' + acceptedDomain + ':' + str(acceptedPort) + \
|
if '/' + acceptedDomain + ':' + str(acceptedPort) + \
|
||||||
'/users/' + nickname not in thisActor:
|
'/users/' + nickname not in thisActor:
|
||||||
if debug:
|
if debug:
|
||||||
print('Port: '+str(acceptedPort))
|
print('Port: ' + str(acceptedPort))
|
||||||
print('Expected: /' + acceptedDomain + ':' +
|
print('Expected: /' + acceptedDomain + ':' +
|
||||||
str(acceptedPort) + '/users/'+nickname)
|
str(acceptedPort) + '/users/' + nickname)
|
||||||
print('Actual: '+thisActor)
|
print('Actual: ' + thisActor)
|
||||||
print('DEBUG: unrecognized actor '+thisActor)
|
print('DEBUG: unrecognized actor ' + thisActor)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
if not '/' + acceptedDomain+'/users/' + nickname in thisActor:
|
if not '/' + acceptedDomain+'/users/' + nickname in thisActor:
|
||||||
if debug:
|
if debug:
|
||||||
print('Expected: /'+acceptedDomain+'/users/'+nickname)
|
print('Expected: /' + acceptedDomain+'/users/' + nickname)
|
||||||
print('Actual: '+thisActor)
|
print('Actual: ' + thisActor)
|
||||||
print('DEBUG: unrecognized actor '+thisActor)
|
print('DEBUG: unrecognized actor ' + thisActor)
|
||||||
return
|
return
|
||||||
followedActor = messageJson['object']['object']
|
followedActor = messageJson['object']['object']
|
||||||
followedDomain, port = getDomainFromActor(followedActor)
|
followedDomain, port = getDomainFromActor(followedActor)
|
||||||
|
|
|
||||||
5
cache.py
5
cache.py
|
|
@ -45,8 +45,9 @@ def getPersonFromCache(baseDir: str, personUrl: str, personCache: {},
|
||||||
# does the person exist as a cached file?
|
# does the person exist as a cached file?
|
||||||
cacheFilename = baseDir + '/cache/actors/' + \
|
cacheFilename = baseDir + '/cache/actors/' + \
|
||||||
personUrl.replace('/', '#')+'.json'
|
personUrl.replace('/', '#')+'.json'
|
||||||
if os.path.isfile(getFileCaseInsensitive(cacheFilename)):
|
actorFilename = getFileCaseInsensitive(cacheFilename)
|
||||||
personJson = loadJson(getFileCaseInsensitive(cacheFilename))
|
if actorFilename:
|
||||||
|
personJson = loadJson(actorFilename)
|
||||||
if personJson:
|
if personJson:
|
||||||
storePersonInCache(baseDir, personUrl, personJson,
|
storePersonInCache(baseDir, personUrl, personJson,
|
||||||
personCache, False)
|
personCache, False)
|
||||||
|
|
|
||||||
|
|
@ -992,8 +992,8 @@ aside .toggle-inside li {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
padding: var(--button-height-padding);
|
padding: var(--button-height-padding);
|
||||||
width: 10%;
|
width: 10%;
|
||||||
max-width: 100px;
|
max-width: 200px;
|
||||||
min-width: 80px;
|
min-width: 10ch;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
|
@ -1009,7 +1009,7 @@ aside .toggle-inside li {
|
||||||
padding: var(--button-height-padding);
|
padding: var(--button-height-padding);
|
||||||
width: 10%;
|
width: 10%;
|
||||||
max-width: 100px;
|
max-width: 100px;
|
||||||
min-width: 80px;
|
min-width: 10ch;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
|
@ -1025,7 +1025,7 @@ aside .toggle-inside li {
|
||||||
padding: var(--button-height-padding);
|
padding: var(--button-height-padding);
|
||||||
width: 10%;
|
width: 10%;
|
||||||
max-width: 100px;
|
max-width: 100px;
|
||||||
min-width: 80px;
|
min-width: 10ch;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
|
@ -1041,7 +1041,7 @@ aside .toggle-inside li {
|
||||||
padding: var(--button-height-padding);
|
padding: var(--button-height-padding);
|
||||||
width: 10%;
|
width: 10%;
|
||||||
max-width: 100px;
|
max-width: 100px;
|
||||||
min-width: 80px;
|
min-width: 10ch;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
|
@ -1432,7 +1432,7 @@ aside .toggle-inside li {
|
||||||
padding: var(--button-height-padding-mobile);
|
padding: var(--button-height-padding-mobile);
|
||||||
width: 20%;
|
width: 20%;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
min-width: 80px;
|
min-width: 10ch;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
|
|
@ -1448,7 +1448,7 @@ aside .toggle-inside li {
|
||||||
padding: var(--button-height-padding-mobile);
|
padding: var(--button-height-padding-mobile);
|
||||||
width: 20%;
|
width: 20%;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
min-width: 80px;
|
min-width: 10ch;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
|
|
@ -1464,7 +1464,7 @@ aside .toggle-inside li {
|
||||||
padding: var(--button-height-padding-mobile);
|
padding: var(--button-height-padding-mobile);
|
||||||
width: 20%;
|
width: 20%;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
min-width: 80px;
|
min-width: 10ch;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
|
|
@ -1480,7 +1480,7 @@ aside .toggle-inside li {
|
||||||
padding: var(--button-height-padding-mobile);
|
padding: var(--button-height-padding-mobile);
|
||||||
width: 20%;
|
width: 20%;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
min-width: 80px;
|
min-width: 10ch;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
|
|
|
||||||
|
|
@ -1819,7 +1819,8 @@ if YTDomain:
|
||||||
if setTheme(baseDir, themeName):
|
if setTheme(baseDir, themeName):
|
||||||
print('Theme set to ' + themeName)
|
print('Theme set to ' + themeName)
|
||||||
|
|
||||||
runDaemon(args.blogsinstance, args.mediainstance,
|
if __name__ == "__main__":
|
||||||
|
runDaemon(args.blogsinstance, args.mediainstance,
|
||||||
args.maxRecentPosts,
|
args.maxRecentPosts,
|
||||||
not args.nosharedinbox,
|
not args.nosharedinbox,
|
||||||
registration, args.language, __version__,
|
registration, args.language, __version__,
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -8,6 +8,7 @@ Domestic_Manners by Dustin Norlander is under GPLv2. See https://www.1001fonts.c
|
||||||
Edition is public domain. See https://www.fontspace.com/edition-font-f35311
|
Edition is public domain. See https://www.fontspace.com/edition-font-f35311
|
||||||
ElectrumADFExp-Regular is by Arkandis Digital Foundry under GPLv2. See https://www.1001fonts.com/electrum-adf-exp-font.html
|
ElectrumADFExp-Regular is by Arkandis Digital Foundry under GPLv2. See https://www.1001fonts.com/electrum-adf-exp-font.html
|
||||||
GeneralFailureRegular is public domain. See https://www.fontspace.com/general-failure-font-f32565
|
GeneralFailureRegular is public domain. See https://www.fontspace.com/general-failure-font-f32565
|
||||||
|
JetBrains is Apache 2.0. See https://www.jetbrains.com/lp/mono/
|
||||||
Judges is under GPL. See https://webfonts.ffonts.net/Judges.font
|
Judges is under GPL. See https://webfonts.ffonts.net/Judges.font
|
||||||
LinBiolinum is under GPLv2. See https://www.1001fonts.com/linux-biolinum-font.html
|
LinBiolinum is under GPLv2. See https://www.1001fonts.com/linux-biolinum-font.html
|
||||||
LcdSolid is public domain. See https://www.fontspace.com/lcd-solid-font-f11346
|
LcdSolid is public domain. See https://www.fontspace.com/lcd-solid-font-f11346
|
||||||
|
|
|
||||||
11
inbox.py
11
inbox.py
|
|
@ -87,7 +87,13 @@ def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None:
|
||||||
return
|
return
|
||||||
if not isinstance(postJsonObject['object']['tag'], list):
|
if not isinstance(postJsonObject['object']['tag'], list):
|
||||||
return
|
return
|
||||||
tagsDir = baseDir+'/tags'
|
tagsDir = baseDir + '/tags'
|
||||||
|
|
||||||
|
# add tags directory if it doesn't exist
|
||||||
|
if not os.path.isdir(tagsDir):
|
||||||
|
print('Creating tags directory')
|
||||||
|
os.mkdir(tagsDir)
|
||||||
|
|
||||||
for tag in postJsonObject['object']['tag']:
|
for tag in postJsonObject['object']['tag']:
|
||||||
if not tag.get('type'):
|
if not tag.get('type'):
|
||||||
continue
|
continue
|
||||||
|
|
@ -134,7 +140,7 @@ def inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
avatarUrl = None
|
avatarUrl = None
|
||||||
if boxname != 'tlevents' and boxname != 'outbox':
|
if boxname != 'tlevents' and boxname != 'outbox':
|
||||||
boxName = 'inbox'
|
boxName = 'inbox'
|
||||||
individualPostAsHtml(recentPostsCache, maxRecentPosts,
|
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
|
||||||
getIconsDir(baseDir), translate, pageNumber,
|
getIconsDir(baseDir), translate, pageNumber,
|
||||||
baseDir, session, cachedWebfingers, personCache,
|
baseDir, session, cachedWebfingers, personCache,
|
||||||
nickname, domain, port, postJsonObject,
|
nickname, domain, port, postJsonObject,
|
||||||
|
|
@ -2364,6 +2370,7 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
if nickname != 'inbox':
|
if nickname != 'inbox':
|
||||||
# replies index will be updated
|
# replies index will be updated
|
||||||
updateIndexList.append('tlreplies')
|
updateIndexList.append('tlreplies')
|
||||||
|
if postJsonObject['object'].get('inReplyTo'):
|
||||||
inReplyTo = postJsonObject['object']['inReplyTo']
|
inReplyTo = postJsonObject['object']['inReplyTo']
|
||||||
if inReplyTo:
|
if inReplyTo:
|
||||||
if isinstance(inReplyTo, str):
|
if isinstance(inReplyTo, str):
|
||||||
|
|
|
||||||
42
posts.py
42
posts.py
|
|
@ -31,7 +31,6 @@ from webfinger import webfingerHandle
|
||||||
from httpsig import createSignedHeader
|
from httpsig import createSignedHeader
|
||||||
from utils import removeIdEnding
|
from utils import removeIdEnding
|
||||||
from utils import siteIsActive
|
from utils import siteIsActive
|
||||||
from utils import removePostFromCache
|
|
||||||
from utils import getCachedPostFilename
|
from utils import getCachedPostFilename
|
||||||
from utils import getStatusNumber
|
from utils import getStatusNumber
|
||||||
from utils import createPersonDir
|
from utils import createPersonDir
|
||||||
|
|
@ -3535,19 +3534,20 @@ def mutePost(baseDir: str, nickname: str, domain: str, postId: str,
|
||||||
if not postJsonObject:
|
if not postJsonObject:
|
||||||
return
|
return
|
||||||
|
|
||||||
print('MUTE: ' + postFilename)
|
# remove cached post so that the muted version gets recreated
|
||||||
muteFile = open(postFilename + '.muted', 'w+')
|
# without its content text and/or image
|
||||||
if muteFile:
|
|
||||||
muteFile.write('\n')
|
|
||||||
muteFile.close()
|
|
||||||
|
|
||||||
# remove cached posts so that the muted version gets created
|
|
||||||
cachedPostFilename = \
|
cachedPostFilename = \
|
||||||
getCachedPostFilename(baseDir, nickname, domain, postJsonObject)
|
getCachedPostFilename(baseDir, nickname, domain, postJsonObject)
|
||||||
if cachedPostFilename:
|
if cachedPostFilename:
|
||||||
if os.path.isfile(cachedPostFilename):
|
if os.path.isfile(cachedPostFilename):
|
||||||
os.remove(cachedPostFilename)
|
os.remove(cachedPostFilename)
|
||||||
|
|
||||||
|
muteFile = open(postFilename + '.muted', 'w+')
|
||||||
|
if muteFile:
|
||||||
|
muteFile.write('\n')
|
||||||
|
muteFile.close()
|
||||||
|
print('MUTE: ' + postFilename + '.muted file added')
|
||||||
|
|
||||||
# if the post is in the recent posts cache then mark it as muted
|
# if the post is in the recent posts cache then mark it as muted
|
||||||
if recentPostsCache.get('index'):
|
if recentPostsCache.get('index'):
|
||||||
postId = \
|
postId = \
|
||||||
|
|
@ -3557,8 +3557,11 @@ def mutePost(baseDir: str, nickname: str, domain: str, postId: str,
|
||||||
if recentPostsCache['json'].get(postId):
|
if recentPostsCache['json'].get(postId):
|
||||||
postJsonObject['muted'] = True
|
postJsonObject['muted'] = True
|
||||||
recentPostsCache['json'][postId] = json.dumps(postJsonObject)
|
recentPostsCache['json'][postId] = json.dumps(postJsonObject)
|
||||||
|
if recentPostsCache.get('html'):
|
||||||
|
if recentPostsCache['html'].get(postId):
|
||||||
|
del recentPostsCache['html'][postId]
|
||||||
print('MUTE: ' + postId +
|
print('MUTE: ' + postId +
|
||||||
' marked as muted in recent posts cache')
|
' marked as muted in recent posts memory cache')
|
||||||
|
|
||||||
|
|
||||||
def unmutePost(baseDir: str, nickname: str, domain: str, postId: str,
|
def unmutePost(baseDir: str, nickname: str, domain: str, postId: str,
|
||||||
|
|
@ -3572,18 +3575,33 @@ def unmutePost(baseDir: str, nickname: str, domain: str, postId: str,
|
||||||
if not postJsonObject:
|
if not postJsonObject:
|
||||||
return
|
return
|
||||||
|
|
||||||
print('UNMUTE: ' + postFilename)
|
|
||||||
muteFilename = postFilename + '.muted'
|
muteFilename = postFilename + '.muted'
|
||||||
if os.path.isfile(muteFilename):
|
if os.path.isfile(muteFilename):
|
||||||
os.remove(muteFilename)
|
os.remove(muteFilename)
|
||||||
|
print('UNMUTE: ' + muteFilename + ' file removed')
|
||||||
|
|
||||||
# remove cached posts so that it gets recreated
|
# remove cached post so that the muted version gets recreated
|
||||||
|
# with its content text and/or image
|
||||||
cachedPostFilename = \
|
cachedPostFilename = \
|
||||||
getCachedPostFilename(baseDir, nickname, domain, postJsonObject)
|
getCachedPostFilename(baseDir, nickname, domain, postJsonObject)
|
||||||
if cachedPostFilename:
|
if cachedPostFilename:
|
||||||
if os.path.isfile(cachedPostFilename):
|
if os.path.isfile(cachedPostFilename):
|
||||||
os.remove(cachedPostFilename)
|
os.remove(cachedPostFilename)
|
||||||
removePostFromCache(postJsonObject, recentPostsCache)
|
|
||||||
|
# if the post is in the recent posts cache then mark it as unmuted
|
||||||
|
if recentPostsCache.get('index'):
|
||||||
|
postId = \
|
||||||
|
removeIdEnding(postJsonObject['id']).replace('/', '#')
|
||||||
|
if postId in recentPostsCache['index']:
|
||||||
|
print('UNMUTE: ' + postId + ' is in recent posts cache')
|
||||||
|
if recentPostsCache['json'].get(postId):
|
||||||
|
postJsonObject['muted'] = False
|
||||||
|
recentPostsCache['json'][postId] = json.dumps(postJsonObject)
|
||||||
|
if recentPostsCache.get('html'):
|
||||||
|
if recentPostsCache['html'].get(postId):
|
||||||
|
del recentPostsCache['html'][postId]
|
||||||
|
print('UNMUTE: ' + postId +
|
||||||
|
' marked as unmuted in recent posts cache')
|
||||||
|
|
||||||
|
|
||||||
def sendBlockViaServer(baseDir: str, session,
|
def sendBlockViaServer(baseDir: str, session,
|
||||||
|
|
|
||||||
6
theme.py
6
theme.py
|
|
@ -223,15 +223,15 @@ def setThemeDefault(baseDir: str):
|
||||||
name = 'default'
|
name = 'default'
|
||||||
removeTheme(baseDir)
|
removeTheme(baseDir)
|
||||||
setThemeInConfig(baseDir, name)
|
setThemeInConfig(baseDir, name)
|
||||||
themeParams = {
|
|
||||||
"dummyValue": "1234"
|
|
||||||
}
|
|
||||||
bgParams = {
|
bgParams = {
|
||||||
"login": "jpg",
|
"login": "jpg",
|
||||||
"follow": "jpg",
|
"follow": "jpg",
|
||||||
"options": "jpg",
|
"options": "jpg",
|
||||||
"search": "jpg"
|
"search": "jpg"
|
||||||
}
|
}
|
||||||
|
themeParams = {
|
||||||
|
"dummy": "1234"
|
||||||
|
}
|
||||||
setThemeFromDict(baseDir, name, themeParams, bgParams)
|
setThemeFromDict(baseDir, name, themeParams, bgParams)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
42
utils.py
42
utils.py
|
|
@ -365,26 +365,30 @@ def followPerson(baseDir: str, nickname: str, domain: str,
|
||||||
return True
|
return True
|
||||||
# prepend to follow file
|
# prepend to follow file
|
||||||
try:
|
try:
|
||||||
with open(filename, 'r+') as followFile:
|
with open(filename, 'r+') as f:
|
||||||
content = followFile.read()
|
content = f.read()
|
||||||
followFile.seek(0, 0)
|
f.seek(0, 0)
|
||||||
followFile.write(handleToFollow + '\n' + content)
|
f.write(handleToFollow + '\n' + content)
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: follow added')
|
print('DEBUG: follow added')
|
||||||
return True
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('WARN: Failed to write entry to follow file ' +
|
print('WARN: Failed to write entry to follow file ' +
|
||||||
filename + ' ' + str(e))
|
filename + ' ' + str(e))
|
||||||
|
else:
|
||||||
|
# first follow
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: creating new following file to follow ' +
|
||||||
|
handleToFollow)
|
||||||
|
with open(filename, 'w+') as f:
|
||||||
|
f.write(handleToFollow + '\n')
|
||||||
|
|
||||||
|
# Default to adding new follows to the calendar.
|
||||||
|
# Possibly this could be made optional
|
||||||
if followFile == 'following.txt':
|
if followFile == 'following.txt':
|
||||||
# if following a person add them to the list of
|
# if following a person add them to the list of
|
||||||
# calendar follows
|
# calendar follows
|
||||||
addPersonToCalendar(baseDir, nickname, domain,
|
addPersonToCalendar(baseDir, nickname, domain,
|
||||||
followNickname, followDomain)
|
followNickname, followDomain)
|
||||||
if debug:
|
|
||||||
print('DEBUG: creating new following file to follow ' + handleToFollow)
|
|
||||||
with open(filename, 'w+') as followfile:
|
|
||||||
followfile.write(handleToFollow + '\n')
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -621,7 +625,7 @@ def validNickname(domain: str, nickname: str) -> bool:
|
||||||
'likes', 'users', 'statuses',
|
'likes', 'users', 'statuses',
|
||||||
'accounts', 'channels', 'profile',
|
'accounts', 'channels', 'profile',
|
||||||
'updates', 'repeat', 'announce',
|
'updates', 'repeat', 'announce',
|
||||||
'shares', 'fonts', 'icons')
|
'shares', 'fonts', 'icons', 'avatars')
|
||||||
if nickname in reservedNames:
|
if nickname in reservedNames:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
@ -907,21 +911,19 @@ def searchBoxPosts(baseDir: str, nickname: str, domain: str,
|
||||||
def getFileCaseInsensitive(path: str) -> str:
|
def getFileCaseInsensitive(path: str) -> str:
|
||||||
"""Returns a case specific filename given a case insensitive version of it
|
"""Returns a case specific filename given a case insensitive version of it
|
||||||
"""
|
"""
|
||||||
# does the given file exist? If so then we don't need
|
|
||||||
# to do a directory search
|
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
return path
|
return path
|
||||||
if path != path.lower():
|
if path != path.lower():
|
||||||
if os.path.isfile(path.lower()):
|
if os.path.isfile(path.lower()):
|
||||||
return path.lower()
|
return path.lower()
|
||||||
directory, filename = os.path.split(path)
|
# directory, filename = os.path.split(path)
|
||||||
directory, filename = (directory or '.'), filename.lower()
|
# directory, filename = (directory or '.'), filename.lower()
|
||||||
for f in os.listdir(directory):
|
# for f in os.listdir(directory):
|
||||||
if f.lower() == filename:
|
# if f.lower() == filename:
|
||||||
newpath = os.path.join(directory, f)
|
# newpath = os.path.join(directory, f)
|
||||||
if os.path.isfile(newpath):
|
# if os.path.isfile(newpath):
|
||||||
return newpath
|
# return newpath
|
||||||
return path
|
return None
|
||||||
|
|
||||||
|
|
||||||
def undoLikesCollectionEntry(recentPostsCache: {},
|
def undoLikesCollectionEntry(recentPostsCache: {},
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ from matrix import getMatrixAddress
|
||||||
from donate import getDonationUrl
|
from donate import getDonationUrl
|
||||||
from utils import removeIdEnding
|
from utils import removeIdEnding
|
||||||
from utils import getProtocolPrefixes
|
from utils import getProtocolPrefixes
|
||||||
from utils import getFileCaseInsensitive
|
|
||||||
from utils import searchBoxPosts
|
from utils import searchBoxPosts
|
||||||
from utils import isEventPost
|
from utils import isEventPost
|
||||||
from utils import isBlogPost
|
from utils import isBlogPost
|
||||||
|
|
@ -304,16 +303,13 @@ def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {},
|
||||||
# get from locally stored image
|
# get from locally stored image
|
||||||
actorStr = personJson['id'].replace('/', '-')
|
actorStr = personJson['id'].replace('/', '-')
|
||||||
avatarImagePath = baseDir + '/cache/avatars/' + actorStr
|
avatarImagePath = baseDir + '/cache/avatars/' + actorStr
|
||||||
if os.path.isfile(getFileCaseInsensitive(avatarImagePath + '.png')):
|
|
||||||
return '/avatars/' + actorStr + '.png'
|
imageExtension = ('png', 'jpg', 'jpeg', 'gif', 'webp')
|
||||||
elif os.path.isfile(getFileCaseInsensitive(avatarImagePath + '.jpg')):
|
for ext in imageExtension:
|
||||||
return '/avatars/' + actorStr + '.jpg'
|
if os.path.isfile(avatarImagePath + '.' + ext):
|
||||||
elif os.path.isfile(getFileCaseInsensitive(avatarImagePath + '.gif')):
|
return '/avatars/' + actorStr + '.' + ext
|
||||||
return '/avatars/' + actorStr + '.gif'
|
elif os.path.isfile(avatarImagePath.lower() + '.' + ext):
|
||||||
elif os.path.isfile(getFileCaseInsensitive(avatarImagePath + '.webp')):
|
return '/avatars/' + actorStr.lower() + '.' + ext
|
||||||
return '/avatars/' + actorStr + '.webp'
|
|
||||||
elif os.path.isfile(getFileCaseInsensitive(avatarImagePath)):
|
|
||||||
return '/avatars/' + actorStr
|
|
||||||
|
|
||||||
if personJson.get('icon'):
|
if personJson.get('icon'):
|
||||||
if personJson['icon'].get('url'):
|
if personJson['icon'].get('url'):
|
||||||
|
|
@ -3812,6 +3808,9 @@ def individualPostAsHtml(allowDownloads: bool,
|
||||||
storeToCache=True) -> str:
|
storeToCache=True) -> str:
|
||||||
""" Shows a single post as html
|
""" Shows a single post as html
|
||||||
"""
|
"""
|
||||||
|
if not postJsonObject:
|
||||||
|
return ''
|
||||||
|
|
||||||
# benchmark
|
# benchmark
|
||||||
postStartTime = time.time()
|
postStartTime = time.time()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue