main
Bob Mottram 2021-10-20 21:51:19 +01:00
commit 0606ca4a3d
28 changed files with 620 additions and 430 deletions

397
daemon.py

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -22,7 +22,7 @@ body, table, input, select, textarea {
.graph { .graph {
display:block; display:block;
width:600px; width:100%;
height:300px; height:300px;
} }
@ -63,12 +63,12 @@ body, table, input, select, textarea {
} }
.graph tbody:before { .graph tbody:before {
content:"100%"; content:"Max";
top:-0.6em; top:-0.6em;
} }
.graph tbody:after { .graph tbody:after {
content:"0%"; content:"0";
bottom:-0.6em; bottom:-0.6em;
} }

View File

@ -58,7 +58,13 @@ def sortedWatchPoints(fitness: {}, fitnessId: str) -> []:
if not item.get('total'): if not item.get('total'):
continue continue
averageTime = item['total'] * 1000 / item['ctr'] averageTime = item['total'] * 1000 / item['ctr']
result.append(str(averageTime) + ' ' + watchPoint) averageTimeStr = str(averageTime)
threshold = 10
while threshold < 100000:
if averageTime < threshold:
averageTimeStr = '0' + averageTimeStr
threshold *= 10
result.append(averageTimeStr + ' ' + watchPoint)
result.sort(reverse=True) result.sort(reverse=True)
return result return result
@ -97,7 +103,7 @@ def htmlWatchPointsGraph(baseDir: str, fitness: {}, fitnessId: str,
ctr = 0 ctr = 0
for watchPoint in watchPointsList: for watchPoint in watchPointsList:
name = watchPoint.split(' ')[1] name = watchPoint.split(' ', 1)[1]
averageTime = float(watchPoint.split(' ')[0]) averageTime = float(watchPoint.split(' ')[0])
heightPercent = int(averageTime * 100 / maxAverageTime) heightPercent = int(averageTime * 100 / maxAverageTime)
timeMS = int(averageTime) timeMS = int(averageTime)

View File

@ -15,6 +15,7 @@ import random
from linked_data_sig import verifyJsonSignature from linked_data_sig import verifyJsonSignature
from languages import understoodPostLanguage from languages import understoodPostLanguage
from like import updateLikesCollection from like import updateLikesCollection
from utils import fileLastModified
from utils import hasObjectString from utils import hasObjectString
from utils import hasObjectStringObject from utils import hasObjectStringObject
from utils import getReplyIntervalHours from utils import getReplyIntervalHours
@ -105,6 +106,7 @@ from announce import createAnnounce
from notifyOnPost import notifyWhenPersonPosts from notifyOnPost import notifyWhenPersonPosts
from conversation import updateConversation from conversation import updateConversation
from content import validHashTag from content import validHashTag
from webapp_hashtagswarm import htmlHashTagSwarm
def _storeLastPostId(baseDir: str, nickname: str, domain: str, def _storeLastPostId(baseDir: str, nickname: str, domain: str,
@ -138,7 +140,55 @@ def _storeLastPostId(baseDir: str, nickname: str, domain: str,
pass pass
def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None: def _updateCachedHashtagSwarm(baseDir: str, nickname: str, domain: str,
httpPrefix: str, domainFull: str,
translate: {}) -> bool:
"""Updates the hashtag swarm stored as a file
"""
cachedHashtagSwarmFilename = \
acctDir(baseDir, nickname, domain) + '/.hashtagSwarm'
saveSwarm = True
if os.path.isfile(cachedHashtagSwarmFilename):
lastModified = fileLastModified(cachedHashtagSwarmFilename)
modifiedDate = None
try:
modifiedDate = \
datetime.datetime.strptime(lastModified, "%Y-%m-%dT%H:%M:%SZ")
except BaseException:
print('WARN: unable to parse last modified cache date ' +
str(lastModified))
pass
if modifiedDate:
currDate = datetime.datetime.utcnow()
timeDiff = currDate - modifiedDate
diffMins = int(timeDiff.total_seconds() / 60)
if diffMins < 10:
# was saved recently, so don't save again
# This avoids too much disk I/O
saveSwarm = False
else:
print('Updating cached hashtag swarm, last changed ' +
str(diffMins) + ' minutes ago')
else:
print('WARN: no modified date for ' + str(lastModified))
if saveSwarm:
actor = httpPrefix + '://' + domainFull + '/users/' + nickname
newSwarmStr = htmlHashTagSwarm(baseDir, actor, translate)
if newSwarmStr:
try:
with open(cachedHashtagSwarmFilename, 'w+') as fp:
fp.write(newSwarmStr)
return True
except BaseException:
print('WARN: unable to write cached hashtag swarm ' +
cachedHashtagSwarmFilename)
pass
return False
def storeHashTags(baseDir: str, nickname: str, domain: str,
httpPrefix: str, domainFull: str,
postJsonObject: {}, translate: {}) -> None:
"""Extracts hashtags from an incoming post and updates the """Extracts hashtags from an incoming post and updates the
relevant tags files. relevant tags files.
""" """
@ -161,6 +211,7 @@ def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None:
hashtagCategories = getHashtagCategories(baseDir) hashtagCategories = getHashtagCategories(baseDir)
hashtagsCtr = 0
for tag in postJsonObject['object']['tag']: for tag in postJsonObject['object']['tag']:
if not tag.get('type'): if not tag.get('type'):
continue continue
@ -179,6 +230,7 @@ def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None:
daysDiff = datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1) daysDiff = datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)
daysSinceEpoch = daysDiff.days daysSinceEpoch = daysDiff.days
tagline = str(daysSinceEpoch) + ' ' + nickname + ' ' + postUrl + '\n' tagline = str(daysSinceEpoch) + ' ' + nickname + ' ' + postUrl + '\n'
hashtagsCtr += 1
if not os.path.isfile(tagsFilename): if not os.path.isfile(tagsFilename):
with open(tagsFilename, 'w+') as tagsFile: with open(tagsFilename, 'w+') as tagsFile:
tagsFile.write(tagline) tagsFile.write(tagline)
@ -203,6 +255,12 @@ def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None:
if categoryStr: if categoryStr:
setHashtagCategory(baseDir, tagName, categoryStr, False) setHashtagCategory(baseDir, tagName, categoryStr, False)
# if some hashtags were found then recalculate the swarm
# ready for later display
if hashtagsCtr > 0:
_updateCachedHashtagSwarm(baseDir, nickname, domain,
httpPrefix, domainFull, translate)
def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
translate: {}, translate: {},
@ -1594,7 +1652,9 @@ def _receiveAnnounce(recentPostsCache: {},
if debug: if debug:
print('DEBUG: Announce post downloaded for ' + print('DEBUG: Announce post downloaded for ' +
messageJson['actor'] + ' -> ' + messageJson['object']) messageJson['actor'] + ' -> ' + messageJson['object'])
storeHashTags(baseDir, nickname, postJsonObject) storeHashTags(baseDir, nickname, domain,
httpPrefix, domainFull,
postJsonObject, translate)
# Try to obtain the actor for this person # Try to obtain the actor for this person
# so that their avatar can be shown # so that their avatar can be shown
lookupActor = None lookupActor = None
@ -2925,7 +2985,9 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
_inboxUpdateCalendar(baseDir, handle, postJsonObject) _inboxUpdateCalendar(baseDir, handle, postJsonObject)
storeHashTags(baseDir, handleName, postJsonObject) storeHashTags(baseDir, handleName, domain,
httpPrefix, domainFull,
postJsonObject, translate)
# send the post out to group members # send the post out to group members
if isGroup: if isGroup:

View File

@ -281,7 +281,8 @@ def hashtagRuleTree(operators: [],
def _hashtagAdd(baseDir: str, httpPrefix: str, domainFull: str, def _hashtagAdd(baseDir: str, httpPrefix: str, domainFull: str,
postJsonObject: {}, postJsonObject: {},
actionStr: str, hashtags: [], systemLanguage: str) -> None: actionStr: str, hashtags: [], systemLanguage: str,
translate: {}) -> None:
"""Adds a hashtag via a hashtag rule """Adds a hashtag via a hashtag rule
""" """
addHashtag = actionStr.split('add ', 1)[1].strip() addHashtag = actionStr.split('add ', 1)[1].strip()
@ -326,7 +327,12 @@ def _hashtagAdd(baseDir: str, httpPrefix: str, domainFull: str,
else: else:
content += hashtagHtml content += hashtagHtml
postJsonObject['object']['content'] = content postJsonObject['object']['content'] = content
storeHashTags(baseDir, 'news', postJsonObject) domain = domainFull
if ':' in domain:
domain = domain.split(':')[0]
storeHashTags(baseDir, 'news', domain,
httpPrefix, domainFull,
postJsonObject, translate)
def _hashtagRemove(httpPrefix: str, domainFull: str, postJsonObject: {}, def _hashtagRemove(httpPrefix: str, domainFull: str, postJsonObject: {},
@ -369,7 +375,8 @@ def _newswireHashtagProcessing(session, baseDir: str, postJsonObject: {},
federationList: [], federationList: [],
sendThreads: [], postLog: [], sendThreads: [], postLog: [],
moderated: bool, url: str, moderated: bool, url: str,
systemLanguage: str) -> bool: systemLanguage: str,
translate: {}) -> bool:
"""Applies hashtag rules to a news post. """Applies hashtag rules to a news post.
Returns true if the post should be saved to the news timeline Returns true if the post should be saved to the news timeline
of this instance of this instance
@ -413,7 +420,8 @@ def _newswireHashtagProcessing(session, baseDir: str, postJsonObject: {},
if actionStr.startswith('add '): if actionStr.startswith('add '):
# add a hashtag # add a hashtag
_hashtagAdd(baseDir, httpPrefix, domainFull, _hashtagAdd(baseDir, httpPrefix, domainFull,
postJsonObject, actionStr, hashtags, systemLanguage) postJsonObject, actionStr, hashtags, systemLanguage,
translate)
elif actionStr.startswith('remove '): elif actionStr.startswith('remove '):
# remove a hashtag # remove a hashtag
_hashtagRemove(httpPrefix, domainFull, postJsonObject, _hashtagRemove(httpPrefix, domainFull, postJsonObject,
@ -659,7 +667,8 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str,
personCache, cachedWebfingers, personCache, cachedWebfingers,
federationList, federationList,
sendThreads, postLog, sendThreads, postLog,
moderated, url, systemLanguage) moderated, url, systemLanguage,
translate)
# save the post and update the index # save the post and update the index
if savePost: if savePost:
@ -698,7 +707,9 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str,
if tag not in newswire[originalDateStr][6]: if tag not in newswire[originalDateStr][6]:
newswire[originalDateStr][6].append(tag) newswire[originalDateStr][6].append(tag)
storeHashTags(baseDir, 'news', blog) storeHashTags(baseDir, 'news', domain,
httpPrefix, domainFull,
blog, translate)
clearFromPostCaches(baseDir, recentPostsCache, postId) clearFromPostCaches(baseDir, recentPostsCache, postId)
if saveJson(blog, filename): if saveJson(blog, filename):

View File

@ -15,7 +15,7 @@ from posts import isImageMedia
from posts import outboxMessageCreateWrap from posts import outboxMessageCreateWrap
from posts import savePostToBox from posts import savePostToBox
from posts import sendToFollowersThread from posts import sendToFollowersThread
from posts import sendToNamedAddresses from posts import sendToNamedAddressesThread
from utils import hasObjectStringType from utils import hasObjectStringType
from utils import getBaseContentFromPost from utils import getBaseContentFromPost
from utils import hasObjectDict from utils import hasObjectDict
@ -627,7 +627,8 @@ def postMessageToOutbox(session, translate: {},
else: else:
print('c2s sender: ' + print('c2s sender: ' +
postToNickname + '@' + domain + ':' + str(port)) postToNickname + '@' + domain + ':' + str(port))
sendToNamedAddresses(server.session, baseDir, namedAddressesThread = \
sendToNamedAddressesThread(server.session, baseDir,
postToNickname, postToNickname,
domain, onionDomain, i2pDomain, port, domain, onionDomain, i2pDomain, port,
httpPrefix, httpPrefix,
@ -641,4 +642,5 @@ def postMessageToOutbox(session, translate: {},
sharedItemsFederatedDomains, sharedItemsFederatedDomains,
sharedItemFederationTokens, sharedItemFederationTokens,
signingPrivateKeyPem) signingPrivateKeyPem)
followersThreads.append(namedAddressesThread)
return True return True

View File

@ -2734,7 +2734,7 @@ def _isProfileUpdate(postJsonObject: {}) -> bool:
return False return False
def sendToNamedAddresses(session, baseDir: str, def _sendToNamedAddresses(session, baseDir: str,
nickname: str, domain: str, nickname: str, domain: str,
onionDomain: str, i2pDomain: str, port: int, onionDomain: str, i2pDomain: str, port: int,
httpPrefix: str, federationList: [], httpPrefix: str, federationList: [],
@ -2885,6 +2885,45 @@ def sendToNamedAddresses(session, baseDir: str,
signingPrivateKeyPem, 34436782) signingPrivateKeyPem, 34436782)
def sendToNamedAddressesThread(session, baseDir: str,
nickname: str, domain: str,
onionDomain: str, i2pDomain: str, port: int,
httpPrefix: str, federationList: [],
sendThreads: [], postLog: [],
cachedWebfingers: {}, personCache: {},
postJsonObject: {}, debug: bool,
projectVersion: str,
sharedItemsFederatedDomains: [],
sharedItemFederationTokens: {},
signingPrivateKeyPem: str):
"""Returns a thread used to send a post to named addresses
"""
sendThread = \
threadWithTrace(target=_sendToNamedAddresses,
args=(session, baseDir,
nickname, domain,
onionDomain, i2pDomain, port,
httpPrefix, federationList,
sendThreads, postLog,
cachedWebfingers, personCache,
postJsonObject, debug,
projectVersion,
sharedItemsFederatedDomains,
sharedItemFederationTokens,
signingPrivateKeyPem), daemon=True)
try:
sendThread.start()
except SocketError as e:
print('WARN: socket error while starting ' +
'thread to send to named addresses. ' + str(e))
return None
except ValueError as e:
print('WARN: error while starting ' +
'thread to send to named addresses. ' + str(e))
return None
return sendThread
def _hasSharedInbox(session, httpPrefix: str, domain: str, def _hasSharedInbox(session, httpPrefix: str, domain: str,
debug: bool, signingPrivateKeyPem: str) -> bool: debug: bool, signingPrivateKeyPem: str) -> bool:
"""Returns true if the given domain has a shared inbox """Returns true if the given domain has a shared inbox

View File

@ -4507,6 +4507,7 @@ def _testFunctions():
'do_POST', 'do_POST',
'do_HEAD', 'do_HEAD',
'__run', '__run',
'_sendToNamedAddresses',
'globaltrace', 'globaltrace',
'localtrace', 'localtrace',
'kill', 'kill',

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "عرّف عن نفسك وحدد التاريخ والوقت اللذين ترغب في الإقامة فيهما", "Introduce yourself and specify the date and time when you wish to stay": "عرّف عن نفسك وحدد التاريخ والوقت اللذين ترغب في الإقامة فيهما",
"Members": "أعضاء", "Members": "أعضاء",
"Join": "انضم", "Join": "انضم",
"Leave": "يترك" "Leave": "يترك",
"System Monitor": "مراقب النظام"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Presenteu-vos i especifiqueu la data i lhora en què voleu romandre", "Introduce yourself and specify the date and time when you wish to stay": "Presenteu-vos i especifiqueu la data i lhora en què voleu romandre",
"Members": "Membres", "Members": "Membres",
"Join": "Uneix-te", "Join": "Uneix-te",
"Leave": "Marxa" "Leave": "Marxa",
"System Monitor": "Monitor del sistema"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Cyflwynwch eich hun a nodwch y dyddiad a'r amser pan fyddwch yn dymuno aros", "Introduce yourself and specify the date and time when you wish to stay": "Cyflwynwch eich hun a nodwch y dyddiad a'r amser pan fyddwch yn dymuno aros",
"Members": "Aelodau", "Members": "Aelodau",
"Join": "Ymunwch", "Join": "Ymunwch",
"Leave": "Gadewch" "Leave": "Gadewch",
"System Monitor": "Monitor System"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Stellen Sie sich vor und geben Sie Datum und Uhrzeit Ihres Aufenthalts an", "Introduce yourself and specify the date and time when you wish to stay": "Stellen Sie sich vor und geben Sie Datum und Uhrzeit Ihres Aufenthalts an",
"Members": "Mitglieder", "Members": "Mitglieder",
"Join": "Verbinden", "Join": "Verbinden",
"Leave": "Verlassen" "Leave": "Verlassen",
"System Monitor": "Systemmonitor"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Introduce yourself and specify the date and time when you wish to stay", "Introduce yourself and specify the date and time when you wish to stay": "Introduce yourself and specify the date and time when you wish to stay",
"Members": "Members", "Members": "Members",
"Join": "Join", "Join": "Join",
"Leave": "Leave" "Leave": "Leave",
"System Monitor": "System Monitor"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Preséntese y especifique la fecha y hora en que desea quedarse", "Introduce yourself and specify the date and time when you wish to stay": "Preséntese y especifique la fecha y hora en que desea quedarse",
"Members": "Miembros", "Members": "Miembros",
"Join": "Entrar", "Join": "Entrar",
"Leave": "Dejar" "Leave": "Dejar",
"System Monitor": "Monitor del sistema"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Présentez-vous et précisez la date et l'heure auxquelles vous souhaitez rester", "Introduce yourself and specify the date and time when you wish to stay": "Présentez-vous et précisez la date et l'heure auxquelles vous souhaitez rester",
"Members": "Membres", "Members": "Membres",
"Join": "Rejoindre", "Join": "Rejoindre",
"Leave": "Laisser" "Leave": "Laisser",
"System Monitor": "Moniteur système"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Cuir tú féin in aithne agus sonraigh an dáta agus an t-am ar mhaith leat fanacht", "Introduce yourself and specify the date and time when you wish to stay": "Cuir tú féin in aithne agus sonraigh an dáta agus an t-am ar mhaith leat fanacht",
"Members": "Baill", "Members": "Baill",
"Join": "Bí páirteach", "Join": "Bí páirteach",
"Leave": "Fág" "Leave": "Fág",
"System Monitor": "Monatóir Córais"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "अपना परिचय दें और वह तारीख और समय निर्दिष्ट करें जब आप रुकना चाहते हैं", "Introduce yourself and specify the date and time when you wish to stay": "अपना परिचय दें और वह तारीख और समय निर्दिष्ट करें जब आप रुकना चाहते हैं",
"Members": "सदस्यों", "Members": "सदस्यों",
"Join": "शामिल हों", "Join": "शामिल हों",
"Leave": "छोड़ना" "Leave": "छोड़ना",
"System Monitor": "सिस्टम मॉनिटर"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Presentati e specifica la data e l'ora in cui desideri soggiornare", "Introduce yourself and specify the date and time when you wish to stay": "Presentati e specifica la data e l'ora in cui desideri soggiornare",
"Members": "Membri", "Members": "Membri",
"Join": "Aderire", "Join": "Aderire",
"Leave": "Lasciare" "Leave": "Lasciare",
"System Monitor": "Monitor di sistema"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "自己紹介をし、滞在したい日時を指定してください", "Introduce yourself and specify the date and time when you wish to stay": "自己紹介をし、滞在したい日時を指定してください",
"Members": "メンバー", "Members": "メンバー",
"Join": "加入", "Join": "加入",
"Leave": "離れる" "Leave": "離れる",
"System Monitor": "システムモニター"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Xwe bidin nasîn û roj û dema ku hûn dixwazin bimînin bimînin diyar bikin", "Introduce yourself and specify the date and time when you wish to stay": "Xwe bidin nasîn û roj û dema ku hûn dixwazin bimînin bimînin diyar bikin",
"Members": "Endam", "Members": "Endam",
"Join": "Bihevgirêdan", "Join": "Bihevgirêdan",
"Leave": "Terikandin" "Leave": "Terikandin",
"System Monitor": "System Monitor"
} }

View File

@ -483,5 +483,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Introduce yourself and specify the date and time when you wish to stay", "Introduce yourself and specify the date and time when you wish to stay": "Introduce yourself and specify the date and time when you wish to stay",
"Members": "Members", "Members": "Members",
"Join": "Join", "Join": "Join",
"Leave": "Leave" "Leave": "Leave",
"System Monitor": "System Monitor"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Apresente-se e especifique a data e hora em que deseja ficar", "Introduce yourself and specify the date and time when you wish to stay": "Apresente-se e especifique a data e hora em que deseja ficar",
"Members": "Membros", "Members": "Membros",
"Join": "Juntar", "Join": "Juntar",
"Leave": "Sair" "Leave": "Sair",
"System Monitor": "Monitor de Sistema"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Представьтесь и укажите дату и время, когда вы хотите остаться", "Introduce yourself and specify the date and time when you wish to stay": "Представьтесь и укажите дату и время, когда вы хотите остаться",
"Members": "Члены", "Members": "Члены",
"Join": "Присоединиться", "Join": "Присоединиться",
"Leave": "Оставлять" "Leave": "Оставлять",
"System Monitor": "Системный монитор"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "Jitambulishe na taja tarehe na saa unapotaka kukaa", "Introduce yourself and specify the date and time when you wish to stay": "Jitambulishe na taja tarehe na saa unapotaka kukaa",
"Members": "Wanachama", "Members": "Wanachama",
"Join": "Jiunge", "Join": "Jiunge",
"Leave": "Ondoka" "Leave": "Ondoka",
"System Monitor": "Ufuatiliaji wa Mfumo"
} }

View File

@ -487,5 +487,6 @@
"Introduce yourself and specify the date and time when you wish to stay": "自我介绍并指定您希望入住的日期和时间", "Introduce yourself and specify the date and time when you wish to stay": "自我介绍并指定您希望入住的日期和时间",
"Members": "会员", "Members": "会员",
"Join": "加入", "Join": "加入",
"Leave": "离开" "Leave": "离开",
"System Monitor": "系统监视器"
} }

View File

@ -1415,6 +1415,18 @@ def _htmlEditProfileDangerZone(translate: {}) -> str:
return editProfileForm return editProfileForm
def _htmlSystemMonitor(nickname: str, translate: {}) -> str:
"""Links to performance graphs
"""
systemMonitorStr = beginEditSection(translate['System Monitor'])
systemMonitorStr += '<p><a href="/users/' + nickname + \
'/performance?graph=get">📊 GET</a></p>'
systemMonitorStr += '<p><a href="/users/' + nickname + \
'/performance?graph=post">📊 POST</a></p>'
systemMonitorStr += endEditSection()
return systemMonitorStr
def _htmlEditProfileSkills(baseDir: str, nickname: str, domain: str, def _htmlEditProfileSkills(baseDir: str, nickname: str, domain: str,
translate: {}) -> str: translate: {}) -> str:
"""skills section of Edit Profile screen """skills section of Edit Profile screen
@ -2038,6 +2050,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
roleAssignStr = '' roleAssignStr = ''
peertubeStr = '' peertubeStr = ''
libretranslateStr = '' libretranslateStr = ''
systemMonitorStr = ''
graphicsStr = '' graphicsStr = ''
sharesFederationStr = '' sharesFederationStr = ''
@ -2063,6 +2076,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
mediaInstanceStr, mediaInstanceStr,
blogsInstanceStr, blogsInstanceStr,
newsInstanceStr) newsInstanceStr)
systemMonitorStr = _htmlSystemMonitor(nickname, translate)
instanceTitle = getConfigParam(baseDir, 'instanceTitle') instanceTitle = getConfigParam(baseDir, 'instanceTitle')
editProfileForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle) editProfileForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
@ -2123,6 +2137,9 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
# automatic translations # automatic translations
editProfileForm += libretranslateStr editProfileForm += libretranslateStr
# system monitor
editProfileForm += systemMonitorStr
# Filtering and blocking section # Filtering and blocking section
replyIntervalHours = getReplyIntervalHours(baseDir, nickname, domain, replyIntervalHours = getReplyIntervalHours(baseDir, nickname, domain,
defaultReplyIntervalHours) defaultReplyIntervalHours)

View File

@ -419,8 +419,28 @@ def htmlSearch(cssCache: {}, translate: {},
'name="submitSearch" accesskey="' + submitKey + '">' + \ 'name="submitSearch" accesskey="' + submitKey + '">' + \
translate['Submit'] + '</button>\n' translate['Submit'] + '</button>\n'
followStr += ' </form>\n' followStr += ' </form>\n'
followStr += ' <p class="hashtagswarm">' + \
htmlHashTagSwarm(baseDir, actor, translate) + '</p>\n' cachedHashtagSwarmFilename = \
acctDir(baseDir, searchNickname, domain) + '/.hashtagSwarm'
swarmStr = ''
if os.path.isfile(cachedHashtagSwarmFilename):
try:
with open(cachedHashtagSwarmFilename, 'r') as fp:
swarmStr = fp.read()
except BaseException:
print('WARN: Unable to read cached hashtag swarm')
pass
if not swarmStr:
swarmStr = htmlHashTagSwarm(baseDir, actor, translate)
if swarmStr:
try:
with open(cachedHashtagSwarmFilename, 'w+') as fp:
fp.write(swarmStr)
except BaseException:
print('WARN: Unable to save cached hashtag swarm')
pass
followStr += ' <p class="hashtagswarm">' + swarmStr + '</p>\n'
followStr += ' </center>\n' followStr += ' </center>\n'
followStr += ' </div>\n' followStr += ' </div>\n'
followStr += '</div>\n' followStr += '</div>\n'
@ -777,7 +797,8 @@ def htmlHashtagSearch(cssCache: {},
# previous page link # previous page link
hashtagSearchForm += \ hashtagSearchForm += \
' <center>\n' + \ ' <center>\n' + \
' <a href="/tags/' + hashtag + '?page=' + \ ' <a href="/users/' + nickname + \
'/tags/' + hashtag + '?page=' + \
str(pageNumber - 1) + \ str(pageNumber - 1) + \
'"><img loading="lazy" class="pageicon" src="/' + \ '"><img loading="lazy" class="pageicon" src="/' + \
'icons/pageup.png" title="' + \ 'icons/pageup.png" title="' + \
@ -853,7 +874,7 @@ def htmlHashtagSearch(cssCache: {},
# next page link # next page link
hashtagSearchForm += \ hashtagSearchForm += \
' <center>\n' + \ ' <center>\n' + \
' <a href="/tags/' + hashtag + \ ' <a href="/users/' + nickname + '/tags/' + hashtag + \
'?page=' + str(pageNumber + 1) + \ '?page=' + str(pageNumber + 1) + \
'"><img loading="lazy" class="pageicon" src="/icons' + \ '"><img loading="lazy" class="pageicon" src="/icons' + \
'/pagedown.png" title="' + translate['Page down'] + \ '/pagedown.png" title="' + translate['Page down'] + \