mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main
commit
e593aa2259
6
inbox.py
6
inbox.py
|
|
@ -1372,7 +1372,8 @@ def _receiveAnnounce(recentPostsCache: {},
|
||||||
messageJson,
|
messageJson,
|
||||||
__version__, translate,
|
__version__, translate,
|
||||||
YTReplacementDomain,
|
YTReplacementDomain,
|
||||||
allowLocalNetworkAccess)
|
allowLocalNetworkAccess,
|
||||||
|
recentPostsCache)
|
||||||
if not postJsonObject:
|
if not postJsonObject:
|
||||||
notInOnion = True
|
notInOnion = True
|
||||||
if onionDomain:
|
if onionDomain:
|
||||||
|
|
@ -2450,7 +2451,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
if isImageMedia(session, baseDir, httpPrefix,
|
if isImageMedia(session, baseDir, httpPrefix,
|
||||||
nickname, domain, postJsonObject,
|
nickname, domain, postJsonObject,
|
||||||
translate, YTReplacementDomain,
|
translate, YTReplacementDomain,
|
||||||
allowLocalNetworkAccess):
|
allowLocalNetworkAccess,
|
||||||
|
recentPostsCache):
|
||||||
# media index will be updated
|
# media index will be updated
|
||||||
updateIndexList.append('tlmedia')
|
updateIndexList.append('tlmedia')
|
||||||
if isBlogPost(postJsonObject):
|
if isBlogPost(postJsonObject):
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ def _validFeedDate(pubDate: str) -> bool:
|
||||||
# convert from YY-MM-DD HH:MM:SS+00:00 to
|
# convert from YY-MM-DD HH:MM:SS+00:00 to
|
||||||
# YY-MM-DDTHH:MM:SSZ
|
# YY-MM-DDTHH:MM:SSZ
|
||||||
postDate = pubDate.replace(' ', 'T').replace('+00:00', 'Z')
|
postDate = pubDate.replace(' ', 'T').replace('+00:00', 'Z')
|
||||||
return validPostDate(postDate, 30)
|
return validPostDate(postDate, 90)
|
||||||
|
|
||||||
|
|
||||||
def parseFeedDate(pubDate: str) -> str:
|
def parseFeedDate(pubDate: str) -> str:
|
||||||
|
|
|
||||||
108
posts.py
108
posts.py
|
|
@ -31,6 +31,7 @@ from session import postImage
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
from httpsig import createSignedHeader
|
from httpsig import createSignedHeader
|
||||||
from siteactive import siteIsActive
|
from siteactive import siteIsActive
|
||||||
|
from utils import rejectPostId
|
||||||
from utils import removeInvalidChars
|
from utils import removeInvalidChars
|
||||||
from utils import fileLastModified
|
from utils import fileLastModified
|
||||||
from utils import isPublicPost
|
from utils import isPublicPost
|
||||||
|
|
@ -2952,7 +2953,8 @@ def isImageMedia(session, baseDir: str, httpPrefix: str,
|
||||||
nickname: str, domain: str,
|
nickname: str, domain: str,
|
||||||
postJsonObject: {}, translate: {},
|
postJsonObject: {}, translate: {},
|
||||||
YTReplacementDomain: str,
|
YTReplacementDomain: str,
|
||||||
allowLocalNetworkAccess: bool) -> bool:
|
allowLocalNetworkAccess: bool,
|
||||||
|
recentPostsCache: {}) -> bool:
|
||||||
"""Returns true if the given post has attached image media
|
"""Returns true if the given post has attached image media
|
||||||
"""
|
"""
|
||||||
if postJsonObject['type'] == 'Announce':
|
if postJsonObject['type'] == 'Announce':
|
||||||
|
|
@ -2961,7 +2963,8 @@ def isImageMedia(session, baseDir: str, httpPrefix: str,
|
||||||
nickname, domain, postJsonObject,
|
nickname, domain, postJsonObject,
|
||||||
__version__, translate,
|
__version__, translate,
|
||||||
YTReplacementDomain,
|
YTReplacementDomain,
|
||||||
allowLocalNetworkAccess)
|
allowLocalNetworkAccess,
|
||||||
|
recentPostsCache)
|
||||||
if postJsonAnnounce:
|
if postJsonAnnounce:
|
||||||
postJsonObject = postJsonAnnounce
|
postJsonObject = postJsonAnnounce
|
||||||
if postJsonObject['type'] != 'Create':
|
if postJsonObject['type'] != 'Create':
|
||||||
|
|
@ -3146,9 +3149,9 @@ def _createBoxIndexed(recentPostsCache: {},
|
||||||
'/' + indexBoxName + '.index'
|
'/' + indexBoxName + '.index'
|
||||||
postsCtr = 0
|
postsCtr = 0
|
||||||
if os.path.isfile(indexFilename):
|
if os.path.isfile(indexFilename):
|
||||||
maxPostCtr = itemsPerPage * pageNumber
|
|
||||||
with open(indexFilename, 'r') as indexFile:
|
with open(indexFilename, 'r') as indexFile:
|
||||||
while postsCtr < maxPostCtr:
|
postsAddedToTimeline = 0
|
||||||
|
while postsAddedToTimeline < itemsPerPage:
|
||||||
postFilename = indexFile.readline()
|
postFilename = indexFile.readline()
|
||||||
|
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
|
|
@ -3213,19 +3216,26 @@ def _createBoxIndexed(recentPostsCache: {},
|
||||||
if postUrl in recentPostsCache['index']:
|
if postUrl in recentPostsCache['index']:
|
||||||
if recentPostsCache['json'].get(postUrl):
|
if recentPostsCache['json'].get(postUrl):
|
||||||
url = recentPostsCache['json'][postUrl]
|
url = recentPostsCache['json'][postUrl]
|
||||||
_addPostStringToTimeline(url,
|
if _addPostStringToTimeline(url,
|
||||||
boxname, postsInBox,
|
boxname, postsInBox,
|
||||||
boxActor)
|
boxActor):
|
||||||
postsCtr += 1
|
postsCtr += 1
|
||||||
continue
|
postsAddedToTimeline += 1
|
||||||
|
continue
|
||||||
|
|
||||||
# read the post from file
|
# read the post from file
|
||||||
fullPostFilename = \
|
fullPostFilename = \
|
||||||
locatePost(baseDir, nickname,
|
locatePost(baseDir, nickname,
|
||||||
domain, postUrl, False)
|
domain, postUrl, False)
|
||||||
if fullPostFilename:
|
if fullPostFilename:
|
||||||
_addPostToTimeline(fullPostFilename, boxname,
|
# has the post been rejected?
|
||||||
postsInBox, boxActor)
|
if os.path.isfile(fullPostFilename + '.reject'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if _addPostToTimeline(fullPostFilename, boxname,
|
||||||
|
postsInBox, boxActor):
|
||||||
|
postsAddedToTimeline += 1
|
||||||
|
postsCtr += 1
|
||||||
else:
|
else:
|
||||||
if timelineNickname != nickname:
|
if timelineNickname != nickname:
|
||||||
# if this is the features timeline
|
# if this is the features timeline
|
||||||
|
|
@ -3233,8 +3243,10 @@ def _createBoxIndexed(recentPostsCache: {},
|
||||||
locatePost(baseDir, timelineNickname,
|
locatePost(baseDir, timelineNickname,
|
||||||
domain, postUrl, False)
|
domain, postUrl, False)
|
||||||
if fullPostFilename:
|
if fullPostFilename:
|
||||||
_addPostToTimeline(fullPostFilename, boxname,
|
if _addPostToTimeline(fullPostFilename, boxname,
|
||||||
postsInBox, boxActor)
|
postsInBox, boxActor):
|
||||||
|
postsAddedToTimeline += 1
|
||||||
|
postsCtr += 1
|
||||||
else:
|
else:
|
||||||
print('WARN: features timeline. ' +
|
print('WARN: features timeline. ' +
|
||||||
'Unable to locate post ' + postUrl)
|
'Unable to locate post ' + postUrl)
|
||||||
|
|
@ -3242,7 +3254,9 @@ def _createBoxIndexed(recentPostsCache: {},
|
||||||
print('WARN: Unable to locate post ' + postUrl +
|
print('WARN: Unable to locate post ' + postUrl +
|
||||||
' nickname ' + nickname)
|
' nickname ' + nickname)
|
||||||
|
|
||||||
postsCtr += 1
|
if postsCtr < 3:
|
||||||
|
print('Posts added to json timeline ' + boxname + ': ' +
|
||||||
|
str(postsAddedToTimeline))
|
||||||
|
|
||||||
# Generate first and last entries within header
|
# Generate first and last entries within header
|
||||||
if postsCtr > 0:
|
if postsCtr > 0:
|
||||||
|
|
@ -3865,9 +3879,14 @@ def populateRepliesJson(baseDir: str, nickname: str, domain: str,
|
||||||
repliesJson['orderedItems'].append(pjo)
|
repliesJson['orderedItems'].append(pjo)
|
||||||
|
|
||||||
|
|
||||||
def _rejectAnnounce(announceFilename: str):
|
def _rejectAnnounce(announceFilename: str,
|
||||||
|
baseDir: str, nickname: str, domain: str,
|
||||||
|
announcePostId: str, recentPostsCache: {}):
|
||||||
"""Marks an announce as rejected
|
"""Marks an announce as rejected
|
||||||
"""
|
"""
|
||||||
|
rejectPostId(baseDir, nickname, domain, announcePostId, recentPostsCache)
|
||||||
|
|
||||||
|
# reject the post referenced by the announce activity object
|
||||||
if not os.path.isfile(announceFilename + '.reject'):
|
if not os.path.isfile(announceFilename + '.reject'):
|
||||||
rejectAnnounceFile = open(announceFilename + '.reject', "w+")
|
rejectAnnounceFile = open(announceFilename + '.reject', "w+")
|
||||||
if rejectAnnounceFile:
|
if rejectAnnounceFile:
|
||||||
|
|
@ -3879,7 +3898,8 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
|
||||||
nickname: str, domain: str,
|
nickname: str, domain: str,
|
||||||
postJsonObject: {}, projectVersion: str,
|
postJsonObject: {}, projectVersion: str,
|
||||||
translate: {}, YTReplacementDomain: str,
|
translate: {}, YTReplacementDomain: str,
|
||||||
allowLocalNetworkAccess: bool) -> {}:
|
allowLocalNetworkAccess: bool,
|
||||||
|
recentPostsCache: {}) -> {}:
|
||||||
"""Download the post referenced by an announce
|
"""Download the post referenced by an announce
|
||||||
"""
|
"""
|
||||||
if not postJsonObject.get('object'):
|
if not postJsonObject.get('object'):
|
||||||
|
|
@ -3891,6 +3911,10 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
|
||||||
announceCacheDir = baseDir + '/cache/announce/' + nickname
|
announceCacheDir = baseDir + '/cache/announce/' + nickname
|
||||||
if not os.path.isdir(announceCacheDir):
|
if not os.path.isdir(announceCacheDir):
|
||||||
os.mkdir(announceCacheDir)
|
os.mkdir(announceCacheDir)
|
||||||
|
|
||||||
|
postId = None
|
||||||
|
if postJsonObject.get('id'):
|
||||||
|
postId = postJsonObject['id']
|
||||||
announceFilename = \
|
announceFilename = \
|
||||||
announceCacheDir + '/' + \
|
announceCacheDir + '/' + \
|
||||||
postJsonObject['object'].replace('/', '#') + '.json'
|
postJsonObject['object'].replace('/', '#') + '.json'
|
||||||
|
|
@ -3951,43 +3975,65 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
|
||||||
if not isinstance(announcedJson, dict):
|
if not isinstance(announcedJson, dict):
|
||||||
print('WARN: announce json is not a dict - ' +
|
print('WARN: announce json is not a dict - ' +
|
||||||
postJsonObject['object'])
|
postJsonObject['object'])
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
if not announcedJson.get('id'):
|
if not announcedJson.get('id'):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
if '/statuses/' not in announcedJson['id']:
|
if '/statuses/' not in announcedJson['id']:
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
if not hasUsersPath(announcedJson['id']):
|
if not hasUsersPath(announcedJson['id']):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
if not announcedJson.get('type'):
|
if not announcedJson.get('type'):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
if announcedJson['type'] != 'Note' and \
|
if announcedJson['type'] != 'Note' and \
|
||||||
announcedJson['type'] != 'Article':
|
announcedJson['type'] != 'Article':
|
||||||
# You can only announce Note or Article types
|
# You can only announce Note or Article types
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
if not announcedJson.get('content'):
|
if not announcedJson.get('content'):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
if not announcedJson.get('published'):
|
if not announcedJson.get('published'):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
if not validPostDate(announcedJson['published']):
|
if not validPostDate(announcedJson['published']):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Check the content of the announce
|
# Check the content of the announce
|
||||||
contentStr = announcedJson['content']
|
contentStr = announcedJson['content']
|
||||||
if dangerousMarkup(contentStr, allowLocalNetworkAccess):
|
if dangerousMarkup(contentStr, allowLocalNetworkAccess):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if isFiltered(baseDir, nickname, domain, contentStr):
|
if isFiltered(baseDir, nickname, domain, contentStr):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# remove any long words
|
# remove any long words
|
||||||
|
|
@ -4006,7 +4052,9 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
|
||||||
announcedJson)
|
announcedJson)
|
||||||
if announcedJson['type'] != 'Create':
|
if announcedJson['type'] != 'Create':
|
||||||
# Create wrap failed
|
# Create wrap failed
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# labelAccusatoryPost(postJsonObject, translate)
|
# labelAccusatoryPost(postJsonObject, translate)
|
||||||
|
|
@ -4022,7 +4070,9 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
|
||||||
attributedDomain = getFullDomain(attributedDomain, attributedPort)
|
attributedDomain = getFullDomain(attributedDomain, attributedPort)
|
||||||
if isBlocked(baseDir, nickname, domain,
|
if isBlocked(baseDir, nickname, domain,
|
||||||
attributedNickname, attributedDomain):
|
attributedNickname, attributedDomain):
|
||||||
_rejectAnnounce(announceFilename)
|
_rejectAnnounce(announceFilename,
|
||||||
|
baseDir, nickname, domain, postId,
|
||||||
|
recentPostsCache)
|
||||||
return None
|
return None
|
||||||
postJsonObject = announcedJson
|
postJsonObject = announcedJson
|
||||||
replaceYouTube(postJsonObject, YTReplacementDomain)
|
replaceYouTube(postJsonObject, YTReplacementDomain)
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "هي",
|
"She/Her": "هي",
|
||||||
"girl": "فتاة",
|
"girl": "فتاة",
|
||||||
"boy": "صبي",
|
"boy": "صبي",
|
||||||
"pronoun": "ضمير"
|
"pronoun": "ضمير",
|
||||||
|
"Type of instance": "نوع المثيل",
|
||||||
|
"Security": "حماية",
|
||||||
|
"Enabling broch mode": "يوفر تمكين وضع الكتيب تحصينًا مؤقتًا ضد الهجوم. لن يتم قبول سوى المشاركات من خلال المثيلات المعروفة بالفعل. تنقضي بعد أسبوع.",
|
||||||
|
"Instance Settings": "إعدادات المثيل",
|
||||||
|
"Video Settings": "اعدادات الفيديو",
|
||||||
|
"Filtering and Blocking": "التصفية والحظر",
|
||||||
|
"Role Assignment": "تعيين الدور",
|
||||||
|
"Contact Details": "بيانات المتصل",
|
||||||
|
"Background Images": "صور الخلفية"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Ella",
|
"She/Her": "Ella",
|
||||||
"girl": "noia",
|
"girl": "noia",
|
||||||
"boy": "noi",
|
"boy": "noi",
|
||||||
"pronoun": "pronom"
|
"pronoun": "pronom",
|
||||||
|
"Type of instance": "Tipus d’instància",
|
||||||
|
"Security": "Seguretat",
|
||||||
|
"Enabling broch mode": "L'activació del mode de fulletó proporciona una fortificació temporal contra l'atac. Només s’acceptaran publicacions d’instàncies ja conegudes. Transcorre al cap d’una setmana.",
|
||||||
|
"Instance Settings": "Configuració de la instància",
|
||||||
|
"Video Settings": "Configuració del vídeo",
|
||||||
|
"Filtering and Blocking": "Filtratge i bloqueig",
|
||||||
|
"Role Assignment": "Assignació de funcions",
|
||||||
|
"Contact Details": "Detalls de contacte",
|
||||||
|
"Background Images": "Imatges de fons"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Hi/Ei",
|
"She/Her": "Hi/Ei",
|
||||||
"girl": "merch",
|
"girl": "merch",
|
||||||
"boy": "bachgen",
|
"boy": "bachgen",
|
||||||
"pronoun": "rhagenw"
|
"pronoun": "rhagenw",
|
||||||
|
"Type of instance": "Math o enghraifft",
|
||||||
|
"Security": "Diogelwch",
|
||||||
|
"Enabling broch mode": "Mae modd galluogi broch yn darparu amddiffynfa dros dro yn erbyn ymosodiad. Dim ond swyddi mewn achosion y gwyddys amdanynt eisoes a dderbynnir. Mae'n mynd heibio ar ôl wythnos.",
|
||||||
|
"Instance Settings": "Gosodiadau Instance",
|
||||||
|
"Video Settings": "Gosodiadau Fideo",
|
||||||
|
"Filtering and Blocking": "Hidlo a Blocio",
|
||||||
|
"Role Assignment": "Aseiniad Rôl",
|
||||||
|
"Background Images": "Delweddau Cefndir",
|
||||||
|
"Contact Details": "Manylion cyswllt"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Sie",
|
"She/Her": "Sie",
|
||||||
"girl": "mädchen",
|
"girl": "mädchen",
|
||||||
"boy": "junge",
|
"boy": "junge",
|
||||||
"pronoun": "pronomen"
|
"pronoun": "pronomen",
|
||||||
|
"Type of instance": "Art der Instanz",
|
||||||
|
"Security": "Sicherheit",
|
||||||
|
"Enabling broch mode": "Das Aktivieren des Broch-Modus bietet eine vorübergehende Verstärkung gegen Angriffe. Es werden nur Beiträge von bereits bekannten Instanzen akzeptiert. Es vergeht nach einer Woche.",
|
||||||
|
"Instance Settings": "Instanzeinstellungen",
|
||||||
|
"Video Settings": "Video-Einstellungen",
|
||||||
|
"Filtering and Blocking": "Filtern und Blockieren",
|
||||||
|
"Role Assignment": "Rollenzuweisung",
|
||||||
|
"Background Images": "Hintergrundbilder",
|
||||||
|
"Contact Details": "Kontaktdetails"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
"Profile for": "Profile for",
|
"Profile for": "Profile for",
|
||||||
"The files attached below should be no larger than 10MB in total uploaded at once.": "The files attached below should be no larger than 10MB in total uploaded at once.",
|
"The files attached below should be no larger than 10MB in total uploaded at once.": "The files attached below should be no larger than 10MB in total uploaded at once.",
|
||||||
"Avatar image": "Avatar image",
|
"Avatar image": "Avatar image",
|
||||||
"Background image": "Background image",
|
"Background image": "Background image, which appears behind your avatar",
|
||||||
"Timeline banner image": "Timeline banner image",
|
"Timeline banner image": "Timeline banner image",
|
||||||
"Approve follower requests": "Approve follower requests",
|
"Approve follower requests": "Approve follower requests",
|
||||||
"This is a bot account": "This is a bot account",
|
"This is a bot account": "This is a bot account",
|
||||||
|
|
@ -360,7 +360,7 @@
|
||||||
"New account": "New account",
|
"New account": "New account",
|
||||||
"Moved to new account address": "Moved to new account address",
|
"Moved to new account address": "Moved to new account address",
|
||||||
"Yet another Epicyon Instance": "Yet another Epicyon Instance",
|
"Yet another Epicyon Instance": "Yet another Epicyon Instance",
|
||||||
"Other accounts": "Other accounts",
|
"Other accounts": "Other fediverse accounts",
|
||||||
"Pin this post to your profile.": "Pin this post to your profile.",
|
"Pin this post to your profile.": "Pin this post to your profile.",
|
||||||
"Administered by": "Administered by",
|
"Administered by": "Administered by",
|
||||||
"Version": "Version",
|
"Version": "Version",
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "She/Her",
|
"She/Her": "She/Her",
|
||||||
"girl": "girl",
|
"girl": "girl",
|
||||||
"boy": "boy",
|
"boy": "boy",
|
||||||
"pronoun": "pronoun"
|
"pronoun": "pronoun",
|
||||||
|
"Type of instance": "Type of instance",
|
||||||
|
"Security": "Security",
|
||||||
|
"Enabling broch mode": "Enabling broch mode provides a temporary fortification against attack. Only posts by already known instances will be accepted. If not turned off, it elapses after a week.",
|
||||||
|
"Instance Settings": "Instance Settings",
|
||||||
|
"Video Settings": "Video Settings",
|
||||||
|
"Filtering and Blocking": "Filtering and Blocking",
|
||||||
|
"Role Assignment": "Role Assignment",
|
||||||
|
"Contact Details": "Contact Details",
|
||||||
|
"Background Images": "Background Images"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Ella",
|
"She/Her": "Ella",
|
||||||
"girl": "muchacha",
|
"girl": "muchacha",
|
||||||
"boy": "niño",
|
"boy": "niño",
|
||||||
"pronoun": "pronombre"
|
"pronoun": "pronombre",
|
||||||
|
"Type of instance": "Tipo de instancia",
|
||||||
|
"Security": "Seguridad",
|
||||||
|
"Enabling broch mode": "Habilitar el modo broche proporciona una fortificación temporal contra el ataque. Solo se aceptarán publicaciones de instancias ya conocidas. Transcurre después de una semana.",
|
||||||
|
"Instance Settings": "Configuración de instancia",
|
||||||
|
"Video Settings": "Ajustes de video",
|
||||||
|
"Filtering and Blocking": "Filtrado y bloqueo",
|
||||||
|
"Role Assignment": "Asignación de roles",
|
||||||
|
"Background Images": "Imágenes de fondo",
|
||||||
|
"Contact Details": "Detalles de contacto"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Elle",
|
"She/Her": "Elle",
|
||||||
"girl": "fille",
|
"girl": "fille",
|
||||||
"boy": "garçon",
|
"boy": "garçon",
|
||||||
"pronoun": "pronom"
|
"pronoun": "pronom",
|
||||||
|
"Type of instance": "Type d'instance",
|
||||||
|
"Security": "Sécurité",
|
||||||
|
"Enabling broch mode": "L'activation du mode broch fournit une fortification temporaire contre les attaques. Seuls les messages par des instances déjà connues seront acceptés. Il s'écoule après une semaine.",
|
||||||
|
"Instance Settings": "Paramètres d'instance",
|
||||||
|
"Video Settings": "Paramètres vidéo",
|
||||||
|
"Filtering and Blocking": "Filtrage et blocage",
|
||||||
|
"Role Assignment": "Attribution de rôle",
|
||||||
|
"Background Images": "Images d'arrière-plan",
|
||||||
|
"Contact Details": "Détails du contact"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Sí",
|
"She/Her": "Sí",
|
||||||
"girl": "cailín",
|
"girl": "cailín",
|
||||||
"boy": "buachaill",
|
"boy": "buachaill",
|
||||||
"pronoun": "forainm"
|
"pronoun": "forainm",
|
||||||
|
"Type of instance": "Cineál mar shampla",
|
||||||
|
"Security": "Slándáil",
|
||||||
|
"Enabling broch mode": "Soláthraíonn modh bróiste cumasaithe daingniú sealadach ar ionsaí. Ní ghlacfar ach le poist de réir cásanna a bhfuil eolas orthu cheana. Maireann sé tar éis seachtaine.",
|
||||||
|
"Instance Settings": "Socruithe Institiúide",
|
||||||
|
"Video Settings": "Socruithe Físe",
|
||||||
|
"Filtering and Blocking": "Scagadh agus Blocáil",
|
||||||
|
"Role Assignment": "Sannadh Róil",
|
||||||
|
"Background Images": "Íomhánna Cúlra",
|
||||||
|
"Contact Details": "Sonraí Teagmhála"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "वह/उसकी",
|
"She/Her": "वह/उसकी",
|
||||||
"girl": "लड़की",
|
"girl": "लड़की",
|
||||||
"boy": "लड़का",
|
"boy": "लड़का",
|
||||||
"pronoun": "सवर्नाम"
|
"pronoun": "सवर्नाम",
|
||||||
|
"Type of instance": "उदाहरण के प्रकार",
|
||||||
|
"Security": "सुरक्षा",
|
||||||
|
"Enabling broch mode": "ब्रोश मोड को सक्षम करना हमले के खिलाफ एक अस्थायी किलेबंदी प्रदान करता है। केवल पहले से ज्ञात उदाहरणों द्वारा पोस्ट स्वीकार किए जाएंगे। यह एक सप्ताह के बाद समाप्त हो जाता है।",
|
||||||
|
"Instance Settings": "उदाहरण सेटिंग्स",
|
||||||
|
"Video Settings": "वीडियो सेटिंग्स",
|
||||||
|
"Filtering and Blocking": "छानना और अवरुद्ध करना",
|
||||||
|
"Role Assignment": "भूमिका असाइनमेंट",
|
||||||
|
"Background Images": "पृष्ठभूमि छवियों",
|
||||||
|
"Contact Details": "सम्पर्क करने का विवरण"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Lei",
|
"She/Her": "Lei",
|
||||||
"girl": "ragazza",
|
"girl": "ragazza",
|
||||||
"boy": "ragazzo",
|
"boy": "ragazzo",
|
||||||
"pronoun": "pronome"
|
"pronoun": "pronome",
|
||||||
|
"Type of instance": "Tipo di istanza",
|
||||||
|
"Security": "Sicurezza",
|
||||||
|
"Enabling broch mode": "L'attivazione della modalità Broch fornisce una fortificazione temporanea contro gli attacchi. Verranno accettati solo i post di istanze già note. Scade dopo una settimana.",
|
||||||
|
"Instance Settings": "Impostazioni istanza",
|
||||||
|
"Video Settings": "Impostazioni video",
|
||||||
|
"Filtering and Blocking": "Filtraggio e blocco",
|
||||||
|
"Role Assignment": "Assegnazione del ruolo",
|
||||||
|
"Background Images": "Immagini di sfondo",
|
||||||
|
"Contact Details": "Dettagli del contatto"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "彼女",
|
"She/Her": "彼女",
|
||||||
"girl": "女の子",
|
"girl": "女の子",
|
||||||
"boy": "男の子",
|
"boy": "男の子",
|
||||||
"pronoun": "代名詞"
|
"pronoun": "代名詞",
|
||||||
|
"Type of instance": "インスタンスのタイプ",
|
||||||
|
"Security": "セキュリティ",
|
||||||
|
"Enabling broch mode": "ブロッホモードを有効にすると、攻撃に対する一時的な要塞が提供されます。 既知のインスタンスによる投稿のみが受け入れられます。 一週間後に経過します。",
|
||||||
|
"Instance Settings": "インスタンス設定",
|
||||||
|
"Video Settings": "ビデオ設定",
|
||||||
|
"Filtering and Blocking": "フィルタリングとブロッキング",
|
||||||
|
"Role Assignment": "役割の割り当て",
|
||||||
|
"Background Images": "背景画像",
|
||||||
|
"Contact Details": "連絡先の詳細"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@
|
||||||
"New account": "New account",
|
"New account": "New account",
|
||||||
"Moved to new account address": "Moved to new account address",
|
"Moved to new account address": "Moved to new account address",
|
||||||
"Yet another Epicyon Instance": "Yet another Epicyon Instance",
|
"Yet another Epicyon Instance": "Yet another Epicyon Instance",
|
||||||
"Other accounts": "Other accounts",
|
"Other accounts": "Other fediverse accounts",
|
||||||
"Pin this post to your profile.": "Pin this post to your profile.",
|
"Pin this post to your profile.": "Pin this post to your profile.",
|
||||||
"Administered by": "Administered by",
|
"Administered by": "Administered by",
|
||||||
"Version": "Version",
|
"Version": "Version",
|
||||||
|
|
@ -383,5 +383,14 @@
|
||||||
"She/Her": "She/Her",
|
"She/Her": "She/Her",
|
||||||
"girl": "girl",
|
"girl": "girl",
|
||||||
"boy": "boy",
|
"boy": "boy",
|
||||||
"pronoun": "pronoun"
|
"pronoun": "pronoun",
|
||||||
|
"Type of instance": "Type of instance",
|
||||||
|
"Security": "Security",
|
||||||
|
"Enabling broch mode": "Enabling broch mode provides a temporary fortification against attack. Only posts by already known instances will be accepted. If not turned off, it elapses after a week.",
|
||||||
|
"Instance Settings": "Instance Settings",
|
||||||
|
"Video Settings": "Video Settings",
|
||||||
|
"Filtering and Blocking": "Filtering and Blocking",
|
||||||
|
"Role Assignment": "Role Assignment",
|
||||||
|
"Background Images": "Background Images",
|
||||||
|
"Contact Details": "Contact Details"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Ela",
|
"She/Her": "Ela",
|
||||||
"girl": "garota",
|
"girl": "garota",
|
||||||
"boy": "garoto",
|
"boy": "garoto",
|
||||||
"pronoun": "pronome"
|
"pronoun": "pronome",
|
||||||
|
"Type of instance": "Tipo de instância",
|
||||||
|
"Security": "Segurança",
|
||||||
|
"Enabling broch mode": "Habilitar o modo broch fornece uma fortificação temporária contra ataques. Somente postagens de instâncias já conhecidas serão aceitas. Decorre depois de uma semana.",
|
||||||
|
"Instance Settings": "Configurações de instância",
|
||||||
|
"Video Settings": "Configurações de vídeo",
|
||||||
|
"Filtering and Blocking": "Filtragem e Bloqueio",
|
||||||
|
"Role Assignment": "Atribuição de Função",
|
||||||
|
"Background Images": "Imagens de fundo",
|
||||||
|
"Contact Details": "Detalhes do contato"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "Она/Ее",
|
"She/Her": "Она/Ее",
|
||||||
"girl": "девочка",
|
"girl": "девочка",
|
||||||
"boy": "мальчик",
|
"boy": "мальчик",
|
||||||
"pronoun": "местоимение"
|
"pronoun": "местоимение",
|
||||||
|
"Type of instance": "Тип экземпляра",
|
||||||
|
"Security": "Безопасность",
|
||||||
|
"Enabling broch mode": "Включение режима брошюры обеспечивает временную защиту от атак. Будут приниматься только сообщения от уже известных экземпляров. Проходит через неделю.",
|
||||||
|
"Instance Settings": "Настройки экземпляра",
|
||||||
|
"Video Settings": "Настройки видео",
|
||||||
|
"Filtering and Blocking": "Фильтрация и блокировка",
|
||||||
|
"Role Assignment": "Назначение ролей",
|
||||||
|
"Background Images": "Фоновые изображения",
|
||||||
|
"Contact Details": "Контактная информация"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,5 +387,14 @@
|
||||||
"She/Her": "她",
|
"She/Her": "她",
|
||||||
"girl": "女孩",
|
"girl": "女孩",
|
||||||
"boy": "男生",
|
"boy": "男生",
|
||||||
"pronoun": "代词"
|
"pronoun": "代词",
|
||||||
|
"Type of instance": "实例类型",
|
||||||
|
"Security": "安全",
|
||||||
|
"Enabling broch mode": "启用broch模式可提供针对攻击的临时防御。 仅接受已知实例的帖子。 一个星期后就过去了。",
|
||||||
|
"Instance Settings": "实例设定",
|
||||||
|
"Video Settings": "影片设定",
|
||||||
|
"Filtering and Blocking": "过滤和阻止",
|
||||||
|
"Role Assignment": "角色分配",
|
||||||
|
"Background Images": "背景图片",
|
||||||
|
"Contact Details": "联系方式"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
38
utils.py
38
utils.py
|
|
@ -100,7 +100,7 @@ def hasUsersPath(pathStr: str) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def validPostDate(published: str, maxAgeDays=7) -> bool:
|
def validPostDate(published: str, maxAgeDays=90) -> bool:
|
||||||
"""Returns true if the published date is recent and is not in the future
|
"""Returns true if the published date is recent and is not in the future
|
||||||
"""
|
"""
|
||||||
baselineTime = datetime.datetime(1970, 1, 1)
|
baselineTime = datetime.datetime(1970, 1, 1)
|
||||||
|
|
@ -1206,7 +1206,7 @@ def deletePost(baseDir: str, httpPrefix: str,
|
||||||
# remove any attachment
|
# remove any attachment
|
||||||
_removeAttachment(baseDir, httpPrefix, domain, postJsonObject)
|
_removeAttachment(baseDir, httpPrefix, domain, postJsonObject)
|
||||||
|
|
||||||
extensions = ('votes', 'arrived', 'muted', '.tts')
|
extensions = ('votes', 'arrived', 'muted', 'tts', 'reject')
|
||||||
for ext in extensions:
|
for ext in extensions:
|
||||||
extFilename = postFilename + '.' + ext
|
extFilename = postFilename + '.' + ext
|
||||||
if os.path.isfile(extFilename):
|
if os.path.isfile(extFilename):
|
||||||
|
|
@ -2034,3 +2034,37 @@ def camelCaseSplit(text: str) -> str:
|
||||||
for word in matches:
|
for word in matches:
|
||||||
resultStr += word.group(0) + ' '
|
resultStr += word.group(0) + ' '
|
||||||
return resultStr.strip()
|
return resultStr.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def rejectPostId(baseDir: str, nickname: str, domain: str,
|
||||||
|
postId: str, recentPostsCache: {}) -> None:
|
||||||
|
""" Marks the given post as rejected,
|
||||||
|
for example an announce which is too old
|
||||||
|
"""
|
||||||
|
postFilename = locatePost(baseDir, nickname, domain, postId)
|
||||||
|
if not postFilename:
|
||||||
|
return
|
||||||
|
|
||||||
|
if recentPostsCache.get('index'):
|
||||||
|
# if this is a full path then remove the directories
|
||||||
|
indexFilename = postFilename
|
||||||
|
if '/' in postFilename:
|
||||||
|
indexFilename = 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 = \
|
||||||
|
indexFilename.replace('\n', '').replace('\r', '')
|
||||||
|
postUrl = postUrl.replace('.json', '').strip()
|
||||||
|
|
||||||
|
if postUrl in recentPostsCache['index']:
|
||||||
|
if recentPostsCache['json'].get(postUrl):
|
||||||
|
del recentPostsCache['json'][postUrl]
|
||||||
|
if recentPostsCache['html'].get(postUrl):
|
||||||
|
del recentPostsCache['html'][postUrl]
|
||||||
|
|
||||||
|
rejectFile = open(postFilename + '.reject', "w+")
|
||||||
|
if rejectFile:
|
||||||
|
rejectFile.write('\n')
|
||||||
|
rejectFile.close()
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ from posts import getPersonBox
|
||||||
from posts import isDM
|
from posts import isDM
|
||||||
from posts import downloadAnnounce
|
from posts import downloadAnnounce
|
||||||
from posts import populateRepliesJson
|
from posts import populateRepliesJson
|
||||||
|
from utils import rejectPostId
|
||||||
from utils import isRecentPost
|
from utils import isRecentPost
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
|
|
@ -1288,8 +1289,12 @@ def individualPostAsHtml(allowDownloads: bool,
|
||||||
nickname, domain, postJsonObject,
|
nickname, domain, postJsonObject,
|
||||||
projectVersion, translate,
|
projectVersion, translate,
|
||||||
YTReplacementDomain,
|
YTReplacementDomain,
|
||||||
allowLocalNetworkAccess)
|
allowLocalNetworkAccess,
|
||||||
|
recentPostsCache)
|
||||||
if not postJsonAnnounce:
|
if not postJsonAnnounce:
|
||||||
|
# if the announce could not be downloaded then mark it as rejected
|
||||||
|
rejectPostId(baseDir, nickname, domain, postJsonObject['id'],
|
||||||
|
recentPostsCache)
|
||||||
return ''
|
return ''
|
||||||
postJsonObject = postJsonAnnounce
|
postJsonObject = postJsonAnnounce
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1211,26 +1211,30 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
'<input type="range" min="1" max="100" ' + \
|
'<input type="range" min="1" max="100" ' + \
|
||||||
'class="slider" name="skillValue' + \
|
'class="slider" name="skillValue' + \
|
||||||
str(skillCtr) + '" value="50"></p>'
|
str(skillCtr) + '" value="50"></p>'
|
||||||
|
skillsStr += ' </div></details>\n'
|
||||||
|
|
||||||
cssFilename = baseDir + '/epicyon-profile.css'
|
cssFilename = baseDir + '/epicyon-profile.css'
|
||||||
if os.path.isfile(baseDir + '/epicyon.css'):
|
if os.path.isfile(baseDir + '/epicyon.css'):
|
||||||
cssFilename = baseDir + '/epicyon.css'
|
cssFilename = baseDir + '/epicyon.css'
|
||||||
|
|
||||||
moderatorsStr = ''
|
|
||||||
themesDropdown = ''
|
themesDropdown = ''
|
||||||
instanceStr = ''
|
instanceStr = ''
|
||||||
editorsStr = ''
|
roleAssignStr = ''
|
||||||
peertubeStr = ''
|
peertubeStr = ''
|
||||||
|
|
||||||
adminNickname = getConfigParam(baseDir, 'admin')
|
adminNickname = getConfigParam(baseDir, 'admin')
|
||||||
if adminNickname:
|
if adminNickname:
|
||||||
if path.startswith('/users/' + adminNickname + '/'):
|
if path.startswith('/users/' + adminNickname + '/'):
|
||||||
|
# Instance details section
|
||||||
instanceDescription = \
|
instanceDescription = \
|
||||||
getConfigParam(baseDir, 'instanceDescription')
|
getConfigParam(baseDir, 'instanceDescription')
|
||||||
instanceDescriptionShort = \
|
instanceDescriptionShort = \
|
||||||
getConfigParam(baseDir, 'instanceDescriptionShort')
|
getConfigParam(baseDir, 'instanceDescriptionShort')
|
||||||
instanceTitle = \
|
instanceTitle = \
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
getConfigParam(baseDir, 'instanceTitle')
|
||||||
|
|
||||||
|
instanceStr = '<details><summary class="cw">' + \
|
||||||
|
translate['Instance Settings'] + '</summary>\n'
|
||||||
instanceStr += '<div class="container">'
|
instanceStr += '<div class="container">'
|
||||||
instanceStr += \
|
instanceStr += \
|
||||||
' <label class="labels">' + \
|
' <label class="labels">' + \
|
||||||
|
|
@ -1271,63 +1275,12 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
translate['Instance Logo'] + '</label>'
|
translate['Instance Logo'] + '</label>'
|
||||||
instanceStr += \
|
instanceStr += \
|
||||||
' <input type="file" id="instanceLogo" name="instanceLogo"'
|
' <input type="file" id="instanceLogo" name="instanceLogo"'
|
||||||
instanceStr += ' accept="' + imageFormats + '">'
|
instanceStr += ' accept="' + imageFormats + '"><br>\n'
|
||||||
if getConfigParam(baseDir, "verifyAllSignatures"):
|
|
||||||
instanceStr += \
|
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
|
||||||
'name="verifyallsignatures" checked> ' + \
|
|
||||||
translate['Verify all signatures'] + '<br>\n'
|
|
||||||
else:
|
|
||||||
instanceStr += \
|
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
|
||||||
'name="verifyallsignatures"> ' + \
|
|
||||||
translate['Verify all signatures'] + '<br>\n'
|
|
||||||
if getConfigParam(baseDir, "brochMode"):
|
|
||||||
instanceStr += \
|
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
|
||||||
'name="brochMode" checked> ' + \
|
|
||||||
translate['Broch mode'] + '<br>\n'
|
|
||||||
else:
|
|
||||||
instanceStr += \
|
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
|
||||||
'name="brochMode"> ' + \
|
|
||||||
translate['Broch mode'] + '<br>\n'
|
|
||||||
instanceStr += '</div>'
|
|
||||||
|
|
||||||
moderators = ''
|
|
||||||
moderatorsFile = baseDir + '/accounts/moderators.txt'
|
|
||||||
if os.path.isfile(moderatorsFile):
|
|
||||||
with open(moderatorsFile, "r") as f:
|
|
||||||
moderators = f.read()
|
|
||||||
moderatorsStr = '<div class="container">'
|
|
||||||
moderatorsStr += ' <b>' + translate['Moderators'] + '</b><br>'
|
|
||||||
moderatorsStr += ' ' + \
|
|
||||||
translate['A list of moderator nicknames. One per line.']
|
|
||||||
moderatorsStr += \
|
|
||||||
' <textarea id="message" name="moderators" placeholder="' + \
|
|
||||||
translate['List of moderator nicknames'] + \
|
|
||||||
'..." style="height:200px" spellcheck="false">' + \
|
|
||||||
moderators + '</textarea>'
|
|
||||||
moderatorsStr += '</div>'
|
|
||||||
|
|
||||||
editors = ''
|
|
||||||
editorsFile = baseDir + '/accounts/editors.txt'
|
|
||||||
if os.path.isfile(editorsFile):
|
|
||||||
with open(editorsFile, "r") as f:
|
|
||||||
editors = f.read()
|
|
||||||
editorsStr = '<div class="container">'
|
|
||||||
editorsStr += ' <b>' + translate['Site Editors'] + '</b><br>'
|
|
||||||
editorsStr += ' ' + \
|
|
||||||
translate['A list of editor nicknames. One per line.']
|
|
||||||
editorsStr += \
|
|
||||||
' <textarea id="message" name="editors" placeholder="" ' + \
|
|
||||||
'style="height:200px" spellcheck="false">' + \
|
|
||||||
editors + '</textarea>'
|
|
||||||
editorsStr += '</div>'
|
|
||||||
|
|
||||||
|
# Themes section
|
||||||
themes = getThemesList(baseDir)
|
themes = getThemesList(baseDir)
|
||||||
themesDropdown = '<div class="container">'
|
themesDropdown += ' <br><label class="labels">' + \
|
||||||
themesDropdown += ' <b>' + translate['Theme'] + '</b><br>'
|
translate['Theme'] + '</label><br>\n'
|
||||||
grayscaleFilename = \
|
grayscaleFilename = \
|
||||||
baseDir + '/accounts/.grayscale'
|
baseDir + '/accounts/.grayscale'
|
||||||
grayscale = ''
|
grayscale = ''
|
||||||
|
|
@ -1352,15 +1305,96 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
'name="removeCustomFont"> ' + \
|
'name="removeCustomFont"> ' + \
|
||||||
translate['Remove the custom font'] + '<br>'
|
translate['Remove the custom font'] + '<br>'
|
||||||
themesDropdown += '</div>'
|
|
||||||
themeName = getConfigParam(baseDir, 'theme')
|
themeName = getConfigParam(baseDir, 'theme')
|
||||||
themesDropdown = \
|
themesDropdown = \
|
||||||
themesDropdown.replace('<option value="' + themeName + '">',
|
themesDropdown.replace('<option value="' + themeName + '">',
|
||||||
'<option value="' + themeName +
|
'<option value="' + themeName +
|
||||||
'" selected>')
|
'" selected>')
|
||||||
|
instanceStr += themesDropdown
|
||||||
|
instanceStr += \
|
||||||
|
' <br><label class="labels">' + \
|
||||||
|
translate['Security'] + '</label><br>\n'
|
||||||
|
if getConfigParam(baseDir, "verifyAllSignatures"):
|
||||||
|
instanceStr += \
|
||||||
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
|
'name="verifyallsignatures" checked> ' + \
|
||||||
|
translate['Verify all signatures'] + '<br>\n'
|
||||||
|
else:
|
||||||
|
instanceStr += \
|
||||||
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
|
'name="verifyallsignatures"> ' + \
|
||||||
|
translate['Verify all signatures'] + '<br>\n'
|
||||||
|
instanceStr += translate['Enabling broch mode'] + '<br>\n'
|
||||||
|
if getConfigParam(baseDir, "brochMode"):
|
||||||
|
instanceStr += \
|
||||||
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
|
'name="brochMode" checked> ' + \
|
||||||
|
translate['Broch mode'] + '<br>\n'
|
||||||
|
else:
|
||||||
|
instanceStr += \
|
||||||
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
|
'name="brochMode"> ' + \
|
||||||
|
translate['Broch mode'] + '<br>\n'
|
||||||
|
# Instance type
|
||||||
|
instanceStr += \
|
||||||
|
' <br><label class="labels">' + \
|
||||||
|
translate['Type of instance'] + '</label><br>\n'
|
||||||
|
instanceStr += \
|
||||||
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
|
'name="mediaInstance" ' + mediaInstanceStr + '> ' + \
|
||||||
|
translate['This is a media instance'] + '<br>\n'
|
||||||
|
instanceStr += \
|
||||||
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
|
'name="blogsInstance" ' + blogsInstanceStr + '> ' + \
|
||||||
|
translate['This is a blogging instance'] + '<br>\n'
|
||||||
|
instanceStr += \
|
||||||
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
|
'name="newsInstance" ' + newsInstanceStr + '> ' + \
|
||||||
|
translate['This is a news instance'] + '<br>\n'
|
||||||
|
instanceStr += ' </div></details>\n'
|
||||||
|
|
||||||
peertubeStr = \
|
# Role assignments section
|
||||||
' <br><b><label class="labels">' + \
|
moderators = ''
|
||||||
|
moderatorsFile = baseDir + '/accounts/moderators.txt'
|
||||||
|
if os.path.isfile(moderatorsFile):
|
||||||
|
with open(moderatorsFile, "r") as f:
|
||||||
|
moderators = f.read()
|
||||||
|
# site moderators
|
||||||
|
roleAssignStr = '<details><summary class="cw">' + \
|
||||||
|
translate['Role Assignment'] + '</summary>\n'
|
||||||
|
roleAssignStr += '<div class="container">'
|
||||||
|
roleAssignStr += ' <b><label class="labels">' + \
|
||||||
|
translate['Moderators'] + '</label></b><br>\n'
|
||||||
|
roleAssignStr += ' ' + \
|
||||||
|
translate['A list of moderator nicknames. One per line.']
|
||||||
|
roleAssignStr += \
|
||||||
|
' <textarea id="message" name="moderators" placeholder="' + \
|
||||||
|
translate['List of moderator nicknames'] + \
|
||||||
|
'..." style="height:200px" spellcheck="false">' + \
|
||||||
|
moderators + '</textarea>'
|
||||||
|
|
||||||
|
# site editors
|
||||||
|
editors = ''
|
||||||
|
editorsFile = baseDir + '/accounts/editors.txt'
|
||||||
|
if os.path.isfile(editorsFile):
|
||||||
|
with open(editorsFile, "r") as f:
|
||||||
|
editors = f.read()
|
||||||
|
roleAssignStr += ' <b><label class="labels">' + \
|
||||||
|
translate['Site Editors'] + '</label></b><br>\n'
|
||||||
|
roleAssignStr += ' ' + \
|
||||||
|
translate['A list of editor nicknames. One per line.']
|
||||||
|
roleAssignStr += \
|
||||||
|
' <textarea id="message" name="editors" placeholder="" ' + \
|
||||||
|
'style="height:200px" spellcheck="false">' + \
|
||||||
|
editors + '</textarea>'
|
||||||
|
roleAssignStr += ' </div></details>\n'
|
||||||
|
|
||||||
|
# Video section
|
||||||
|
peertubeStr = ' <details><summary class="cw">' + \
|
||||||
|
translate['Video Settings'] + '</summary>\n'
|
||||||
|
peertubeStr += ' <div class="container">\n'
|
||||||
|
peertubeStr += \
|
||||||
|
' <b><label class="labels">' + \
|
||||||
translate['Peertube Instances'] + '</label></b>\n'
|
translate['Peertube Instances'] + '</label></b>\n'
|
||||||
idx = 'Show video previews for the following Peertube sites.'
|
idx = 'Show video previews for the following Peertube sites.'
|
||||||
peertubeStr += \
|
peertubeStr += \
|
||||||
|
|
@ -1373,6 +1407,16 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
' <textarea id="message" name="ptInstances" ' + \
|
' <textarea id="message" name="ptInstances" ' + \
|
||||||
'style="height:200px" spellcheck="false">' + \
|
'style="height:200px" spellcheck="false">' + \
|
||||||
peertubeInstancesStr + '</textarea>\n'
|
peertubeInstancesStr + '</textarea>\n'
|
||||||
|
peertubeStr += \
|
||||||
|
' <br><b><label class="labels">' + \
|
||||||
|
translate['YouTube Replacement Domain'] + '</label></b>\n'
|
||||||
|
YTReplacementDomain = getConfigParam(baseDir, "youtubedomain")
|
||||||
|
if not YTReplacementDomain:
|
||||||
|
YTReplacementDomain = ''
|
||||||
|
peertubeStr += \
|
||||||
|
' <input type="text" name="ytdomain" value="' + \
|
||||||
|
YTReplacementDomain + '">\n'
|
||||||
|
peertubeStr += ' </div></details>\n'
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = \
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
getConfigParam(baseDir, 'instanceTitle')
|
||||||
|
|
@ -1433,6 +1477,12 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <textarea id="message" name="bio" style="height:200px" ' + \
|
' <textarea id="message" name="bio" style="height:200px" ' + \
|
||||||
'spellcheck="true">' + bioStr + '</textarea>\n'
|
'spellcheck="true">' + bioStr + '</textarea>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <label class="labels">' + translate['Avatar image'] + \
|
||||||
|
'</label>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="file" id="avatar" name="avatar"'
|
||||||
|
editProfileForm += ' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
alsoKnownAsStr = ''
|
alsoKnownAsStr = ''
|
||||||
if actorJson.get('alsoKnownAs'):
|
if actorJson.get('alsoKnownAs'):
|
||||||
|
|
@ -1460,135 +1510,13 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <input type="text" placeholder="https://..." ' + \
|
' <input type="text" placeholder="https://..." ' + \
|
||||||
'name="donateUrl" value="' + donateUrl + '">\n'
|
'name="donateUrl" value="' + donateUrl + '">\n'
|
||||||
editProfileForm += \
|
|
||||||
'<label class="labels">' + translate['XMPP'] + '</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="xmppAddress" value="' + \
|
|
||||||
xmppAddress + '">\n'
|
|
||||||
editProfileForm += '<label class="labels">' + \
|
|
||||||
translate['Matrix'] + '</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="matrixAddress" value="' + \
|
|
||||||
matrixAddress+'">\n'
|
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">SSB</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="ssbAddress" value="' + \
|
|
||||||
ssbAddress + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">Blog</label><br>\n'
|
editProfileForm += '<label class="labels">Blog</label><br>\n'
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <input type="text" name="blogAddress" value="' + \
|
' <input type="text" name="blogAddress" value="' + \
|
||||||
blogAddress + '">\n'
|
blogAddress + '">\n'
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">Tox</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="toxAddress" value="' + \
|
|
||||||
toxAddress + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">Briar</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="briarAddress" value="' + \
|
|
||||||
briarAddress + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">Jami</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="jamiAddress" value="' + \
|
|
||||||
jamiAddress + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">' + \
|
|
||||||
translate['Email'] + '</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="email" value="' + emailAddress + '">\n'
|
|
||||||
editProfileForm += \
|
|
||||||
'<label class="labels">' + \
|
|
||||||
translate['PGP Fingerprint'] + '</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="openpgp" value="' + \
|
|
||||||
PGPfingerprint + '">\n'
|
|
||||||
editProfileForm += \
|
|
||||||
'<label class="labels">' + translate['PGP'] + '</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <textarea id="message" placeholder=' + \
|
|
||||||
'"-----BEGIN PGP PUBLIC KEY BLOCK-----" name="pgp" ' + \
|
|
||||||
'style="height:100px" spellcheck="false">' + \
|
|
||||||
PGPpubKey + '</textarea>\n'
|
|
||||||
editProfileForm += '<a href="/users/' + nickname + \
|
|
||||||
'/followingaccounts"><label class="labels">' + \
|
|
||||||
translate['Following'] + '</label></a><br>\n'
|
|
||||||
editProfileForm += ' </div>\n'
|
|
||||||
editProfileForm += ' <div class="container">\n'
|
|
||||||
idx = 'The files attached below should be no larger than ' + \
|
|
||||||
'10MB in total uploaded at once.'
|
|
||||||
editProfileForm += \
|
|
||||||
' <label class="labels">' + translate[idx] + '</label><br><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <label class="labels">' + translate['Avatar image'] + \
|
|
||||||
'</label>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="file" id="avatar" name="avatar"'
|
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
|
||||||
|
|
||||||
if not newsInstance:
|
|
||||||
editProfileForm += \
|
|
||||||
' <br><label class="labels">' + \
|
|
||||||
translate['Background image'] + '</label>\n'
|
|
||||||
editProfileForm += ' <input type="file" id="image" name="image"'
|
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
|
||||||
translate['Timeline banner image'] + '</label>\n'
|
|
||||||
editProfileForm += ' <input type="file" id="banner" name="banner"'
|
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
|
||||||
translate['Search banner image'] + '</label>\n'
|
|
||||||
editProfileForm += ' <input type="file" id="search_banner" '
|
|
||||||
editProfileForm += 'name="search_banner"'
|
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
|
||||||
translate['Left column image'] + '</label>\n'
|
|
||||||
editProfileForm += ' <input type="file" id="left_col_image" '
|
|
||||||
editProfileForm += 'name="left_col_image"'
|
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
|
||||||
translate['Right column image'] + '</label>\n'
|
|
||||||
editProfileForm += ' <input type="file" id="right_col_image" '
|
|
||||||
editProfileForm += 'name="right_col_image"'
|
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += ' </div>\n'
|
|
||||||
editProfileForm += ' <div class="container">\n'
|
|
||||||
editProfileForm += \
|
|
||||||
'<label class="labels">' + translate['Change Password'] + \
|
|
||||||
'</label><br>\n'
|
|
||||||
editProfileForm += ' <input type="text" name="password" ' + \
|
|
||||||
'value=""><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
'<label class="labels">' + translate['Confirm Password'] + \
|
|
||||||
'</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="passwordconfirm" value="">\n'
|
|
||||||
editProfileForm += ' </div>\n'
|
editProfileForm += ' </div>\n'
|
||||||
|
|
||||||
if path.startswith('/users/' + adminNickname + '/'):
|
# Option checkboxes
|
||||||
editProfileForm += ' <div class="container">\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
|
||||||
'name="mediaInstance" ' + mediaInstanceStr + '> ' + \
|
|
||||||
translate['This is a media instance'] + '<br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
|
||||||
'name="blogsInstance" ' + blogsInstanceStr + '> ' + \
|
|
||||||
translate['This is a blogging instance'] + '<br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
|
||||||
'name="newsInstance" ' + newsInstanceStr + '> ' + \
|
|
||||||
translate['This is a news instance'] + '<br>\n'
|
|
||||||
editProfileForm += ' </div>\n'
|
|
||||||
|
|
||||||
editProfileForm += ' <div class="container">\n'
|
editProfileForm += ' <div class="container">\n'
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
|
|
@ -1618,9 +1546,128 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
' <input type="checkbox" class="profilecheckbox" ' + \
|
' <input type="checkbox" class="profilecheckbox" ' + \
|
||||||
'name="hideLikeButton" ' + hideLikeButton + '> ' + \
|
'name="hideLikeButton" ' + hideLikeButton + '> ' + \
|
||||||
translate["Don't show the Like button"] + '<br>\n'
|
translate["Don't show the Like button"] + '<br>\n'
|
||||||
|
editProfileForm += ' </div>\n'
|
||||||
|
|
||||||
|
# Contact information
|
||||||
|
editProfileForm += ' <details><summary class="cw">' + \
|
||||||
|
translate['Contact Details'] + '</summary>\n'
|
||||||
|
editProfileForm += '<div class="container">'
|
||||||
|
editProfileForm += '<label class="labels">' + \
|
||||||
|
translate['Email'] + '</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="email" value="' + emailAddress + '">\n'
|
||||||
|
editProfileForm += \
|
||||||
|
'<label class="labels">' + translate['XMPP'] + '</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="xmppAddress" value="' + \
|
||||||
|
xmppAddress + '">\n'
|
||||||
|
editProfileForm += '<label class="labels">' + \
|
||||||
|
translate['Matrix'] + '</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="matrixAddress" value="' + \
|
||||||
|
matrixAddress+'">\n'
|
||||||
|
|
||||||
|
editProfileForm += '<label class="labels">SSB</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="ssbAddress" value="' + \
|
||||||
|
ssbAddress + '">\n'
|
||||||
|
|
||||||
|
editProfileForm += '<label class="labels">Tox</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="toxAddress" value="' + \
|
||||||
|
toxAddress + '">\n'
|
||||||
|
|
||||||
|
editProfileForm += '<label class="labels">Briar</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="briarAddress" value="' + \
|
||||||
|
briarAddress + '">\n'
|
||||||
|
|
||||||
|
editProfileForm += '<label class="labels">Jami</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="jamiAddress" value="' + \
|
||||||
|
jamiAddress + '">\n'
|
||||||
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <br><b><label class="labels">' + \
|
'<label class="labels">' + \
|
||||||
|
translate['PGP Fingerprint'] + '</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="openpgp" value="' + \
|
||||||
|
PGPfingerprint + '">\n'
|
||||||
|
editProfileForm += \
|
||||||
|
'<label class="labels">' + translate['PGP'] + '</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <textarea id="message" placeholder=' + \
|
||||||
|
'"-----BEGIN PGP PUBLIC KEY BLOCK-----" name="pgp" ' + \
|
||||||
|
'style="height:600px" spellcheck="false">' + \
|
||||||
|
PGPpubKey + '</textarea>\n'
|
||||||
|
editProfileForm += '<a href="/users/' + nickname + \
|
||||||
|
'/followingaccounts"><label class="labels">' + \
|
||||||
|
translate['Following'] + '</label></a><br>\n'
|
||||||
|
editProfileForm += ' </div></details>\n'
|
||||||
|
|
||||||
|
# Customize images and banners
|
||||||
|
editProfileForm += ' <details><summary class="cw">' + \
|
||||||
|
translate['Background Images'] + '</summary>\n'
|
||||||
|
editProfileForm += ' <div class="container">\n'
|
||||||
|
idx = 'The files attached below should be no larger than ' + \
|
||||||
|
'10MB in total uploaded at once.'
|
||||||
|
editProfileForm += \
|
||||||
|
' <label class="labels">' + translate[idx] + '</label><br><br>\n'
|
||||||
|
|
||||||
|
if not newsInstance:
|
||||||
|
editProfileForm += \
|
||||||
|
' <label class="labels">' + \
|
||||||
|
translate['Background image'] + '</label>\n'
|
||||||
|
editProfileForm += ' <input type="file" id="image" name="image"'
|
||||||
|
editProfileForm += ' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
|
editProfileForm += ' <br><label class="labels">' + \
|
||||||
|
translate['Timeline banner image'] + '</label>\n'
|
||||||
|
editProfileForm += ' <input type="file" id="banner" name="banner"'
|
||||||
|
editProfileForm += ' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
|
editProfileForm += ' <br><label class="labels">' + \
|
||||||
|
translate['Search banner image'] + '</label>\n'
|
||||||
|
editProfileForm += ' <input type="file" id="search_banner" '
|
||||||
|
editProfileForm += 'name="search_banner"'
|
||||||
|
editProfileForm += ' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
|
editProfileForm += ' <br><label class="labels">' + \
|
||||||
|
translate['Left column image'] + '</label>\n'
|
||||||
|
editProfileForm += ' <input type="file" id="left_col_image" '
|
||||||
|
editProfileForm += 'name="left_col_image"'
|
||||||
|
editProfileForm += ' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
|
editProfileForm += ' <br><label class="labels">' + \
|
||||||
|
translate['Right column image'] + '</label>\n'
|
||||||
|
editProfileForm += ' <input type="file" id="right_col_image" '
|
||||||
|
editProfileForm += 'name="right_col_image"'
|
||||||
|
editProfileForm += ' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
|
editProfileForm += ' </div></details>\n'
|
||||||
|
|
||||||
|
# Change password
|
||||||
|
editProfileForm += ' <details><summary class="cw">' + \
|
||||||
|
translate['Change Password'] + '</summary>\n'
|
||||||
|
editProfileForm += ' <div class="container">\n'
|
||||||
|
editProfileForm += \
|
||||||
|
'<label class="labels">' + translate['Change Password'] + \
|
||||||
|
'</label><br>\n'
|
||||||
|
editProfileForm += ' <input type="text" name="password" ' + \
|
||||||
|
'value=""><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
'<label class="labels">' + translate['Confirm Password'] + \
|
||||||
|
'</label><br>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <input type="text" name="passwordconfirm" value="">\n'
|
||||||
|
editProfileForm += ' </div></details>\n'
|
||||||
|
|
||||||
|
# Filtering and blocking section
|
||||||
|
editProfileForm += '<details><summary class="cw">' + \
|
||||||
|
translate['Filtering and Blocking'] + '</summary>\n'
|
||||||
|
editProfileForm += ' <div class="container">\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <b><label class="labels">' + \
|
||||||
translate['Filtered words'] + '</label></b>\n'
|
translate['Filtered words'] + '</label></b>\n'
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
editProfileForm += ' <br><label class="labels">' + \
|
||||||
translate['One per line'] + '</label>\n'
|
translate['One per line'] + '</label>\n'
|
||||||
|
|
@ -1690,17 +1737,11 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
'style="height:100px" spellcheck="false">' + \
|
'style="height:100px" spellcheck="false">' + \
|
||||||
gitProjectsStr + '</textarea>\n'
|
gitProjectsStr + '</textarea>\n'
|
||||||
|
|
||||||
editProfileForm += \
|
editProfileForm += ' </div></details>\n'
|
||||||
' <br><b><label class="labels">' + \
|
|
||||||
translate['YouTube Replacement Domain'] + '</label></b>\n'
|
|
||||||
YTReplacementDomain = getConfigParam(baseDir, "youtubedomain")
|
|
||||||
if not YTReplacementDomain:
|
|
||||||
YTReplacementDomain = ''
|
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="ytdomain" value="' + \
|
|
||||||
YTReplacementDomain + '">\n'
|
|
||||||
|
|
||||||
editProfileForm += ' </div>\n'
|
# Skills section
|
||||||
|
editProfileForm += '<details><summary class="cw">' + \
|
||||||
|
translate['Skills'] + '</summary>\n'
|
||||||
editProfileForm += ' <div class="container">\n'
|
editProfileForm += ' <div class="container">\n'
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <b><label class="labels">' + \
|
' <b><label class="labels">' + \
|
||||||
|
|
@ -1711,9 +1752,12 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
'teams with an appropriate combination of skills.'
|
'teams with an appropriate combination of skills.'
|
||||||
editProfileForm += ' <label class="labels">' + \
|
editProfileForm += ' <label class="labels">' + \
|
||||||
translate[idx] + '</label>\n'
|
translate[idx] + '</label>\n'
|
||||||
editProfileForm += skillsStr + themesDropdown
|
editProfileForm += skillsStr
|
||||||
editProfileForm += moderatorsStr + editorsStr + peertubeStr
|
editProfileForm += roleAssignStr + peertubeStr + instanceStr
|
||||||
editProfileForm += ' </div>\n' + instanceStr
|
|
||||||
|
# danger zone section
|
||||||
|
editProfileForm += ' <details><summary class="cw">' + \
|
||||||
|
translate['Danger Zone'] + '</summary>\n'
|
||||||
editProfileForm += ' <div class="container">\n'
|
editProfileForm += ' <div class="container">\n'
|
||||||
editProfileForm += ' <b><label class="labels">' + \
|
editProfileForm += ' <b><label class="labels">' + \
|
||||||
translate['Danger Zone'] + '</label></b><br>\n'
|
translate['Danger Zone'] + '</label></b><br>\n'
|
||||||
|
|
@ -1721,7 +1765,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
' <input type="checkbox" class=dangercheckbox" ' + \
|
' <input type="checkbox" class=dangercheckbox" ' + \
|
||||||
'name="deactivateThisAccount"> ' + \
|
'name="deactivateThisAccount"> ' + \
|
||||||
translate['Deactivate this account'] + '<br>\n'
|
translate['Deactivate this account'] + '<br>\n'
|
||||||
editProfileForm += ' </div>\n'
|
editProfileForm += ' </div></details>\n'
|
||||||
editProfileForm += ' </div>\n'
|
editProfileForm += ' </div>\n'
|
||||||
editProfileForm += '</form>\n'
|
editProfileForm += '</form>\n'
|
||||||
editProfileForm += htmlFooter()
|
editProfileForm += htmlFooter()
|
||||||
|
|
|
||||||
|
|
@ -672,8 +672,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
# show each post in the timeline
|
# show each post in the timeline
|
||||||
for item in timelineJson['orderedItems']:
|
for item in timelineJson['orderedItems']:
|
||||||
if item['type'] == 'Create' or \
|
if item['type'] == 'Create' or \
|
||||||
item['type'] == 'Announce' or \
|
item['type'] == 'Announce':
|
||||||
item['type'] == 'Update':
|
|
||||||
# is the actor who sent this post snoozed?
|
# is the actor who sent this post snoozed?
|
||||||
if isPersonSnoozed(baseDir, nickname, domain, item['actor']):
|
if isPersonSnoozed(baseDir, nickname, domain, item['actor']):
|
||||||
continue
|
continue
|
||||||
|
|
@ -696,6 +695,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
_logTimelineTiming(enableTimingLog,
|
_logTimelineTiming(enableTimingLog,
|
||||||
timelineStartTime,
|
timelineStartTime,
|
||||||
boxName, '10')
|
boxName, '10')
|
||||||
|
else:
|
||||||
|
print('Muted post in timeline ' + boxName)
|
||||||
|
|
||||||
if not currTlStr:
|
if not currTlStr:
|
||||||
_logTimelineTiming(enableTimingLog,
|
_logTimelineTiming(enableTimingLog,
|
||||||
|
|
@ -734,6 +735,10 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
if boxName == 'tlmedia':
|
if boxName == 'tlmedia':
|
||||||
tlStr += '</div>\n'
|
tlStr += '</div>\n'
|
||||||
|
|
||||||
|
if itemCtr < 3:
|
||||||
|
print('Items added to html timeline ' + boxName + ': ' +
|
||||||
|
str(itemCtr) + ' ' + str(timelineJson['orderedItems']))
|
||||||
|
|
||||||
# page down arrow
|
# page down arrow
|
||||||
if itemCtr > 2:
|
if itemCtr > 2:
|
||||||
tlStr += textModeSeparator
|
tlStr += textModeSeparator
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue