diff --git a/auth.py b/auth.py
index a9b83a938..7ac45cecf 100644
--- a/auth.py
+++ b/auth.py
@@ -121,7 +121,7 @@ def storeBasicCredentials(baseDir: str, nickname: str, password: str) -> bool:
if os.path.isfile(passwordFile):
if nickname + ':' in open(passwordFile).read():
with open(passwordFile, "r") as fin:
- with open(passwordFile + '.new', "w") as fout:
+ with open(passwordFile + '.new', 'w+') as fout:
for line in fin:
if not line.startswith(nickname + ':'):
fout.write(line)
@@ -133,7 +133,7 @@ def storeBasicCredentials(baseDir: str, nickname: str, password: str) -> bool:
with open(passwordFile, 'a+') as passfile:
passfile.write(storeStr + '\n')
else:
- with open(passwordFile, "w") as passfile:
+ with open(passwordFile, 'w+') as passfile:
passfile.write(storeStr + '\n')
return True
@@ -145,7 +145,7 @@ def removePassword(baseDir: str, nickname: str) -> None:
passwordFile = baseDir + '/accounts/passwords'
if os.path.isfile(passwordFile):
with open(passwordFile, "r") as fin:
- with open(passwordFile + '.new', "w") as fout:
+ with open(passwordFile + '.new', 'w+') as fout:
for line in fin:
if not line.startswith(nickname + ':'):
fout.write(line)
diff --git a/blog.py b/blog.py
index e41aacdff..91db9ca66 100644
--- a/blog.py
+++ b/blog.py
@@ -73,7 +73,7 @@ def noOfBlogReplies(baseDir: str, httpPrefix: str, translate: {},
if lines and removals:
print('Rewriting ' + postFilename + ' to remove ' +
str(len(removals)) + ' entries')
- with open(postFilename, "w") as f:
+ with open(postFilename, 'w+') as f:
for replyPostId in lines:
replyPostId = replyPostId.replace('\n', '').replace('\r', '')
if replyPostId not in removals:
diff --git a/cache.py b/cache.py
index 37d1f4270..0ac180f80 100644
--- a/cache.py
+++ b/cache.py
@@ -14,7 +14,8 @@ from utils import getFileCaseInsensitive
def storePersonInCache(baseDir: str, personUrl: str,
- personJson: {}, personCache: {}) -> None:
+ personJson: {}, personCache: {},
+ allowWriteToFile: bool) -> None:
"""Store an actor in the cache
"""
currTime = datetime.datetime.utcnow()
@@ -26,25 +27,29 @@ def storePersonInCache(baseDir: str, personUrl: str,
return
# store to file
- if os.path.isdir(baseDir+'/cache/actors'):
- cacheFilename = baseDir + '/cache/actors/' + \
- personUrl.replace('/', '#')+'.json'
- if not os.path.isfile(cacheFilename):
- saveJson(personJson, cacheFilename)
+ if allowWriteToFile:
+ if os.path.isdir(baseDir+'/cache/actors'):
+ cacheFilename = baseDir + '/cache/actors/' + \
+ personUrl.replace('/', '#')+'.json'
+ if not os.path.isfile(cacheFilename):
+ saveJson(personJson, cacheFilename)
-def getPersonFromCache(baseDir: str, personUrl: str, personCache: {}) -> {}:
+def getPersonFromCache(baseDir: str, personUrl: str, personCache: {},
+ allowWriteToFile: bool) -> {}:
"""Get an actor from the cache
"""
# if the actor is not in memory then try to load it from file
loadedFromFile = False
if not personCache.get(personUrl):
+ # does the person exist as a cached file?
cacheFilename = baseDir + '/cache/actors/' + \
personUrl.replace('/', '#')+'.json'
if os.path.isfile(getFileCaseInsensitive(cacheFilename)):
personJson = loadJson(getFileCaseInsensitive(cacheFilename))
if personJson:
- storePersonInCache(baseDir, personUrl, personJson, personCache)
+ storePersonInCache(baseDir, personUrl, personJson,
+ personCache, False)
loadedFromFile = True
if personCache.get(personUrl):
diff --git a/daemon.py b/daemon.py
index 4300d4d47..3b322a57e 100644
--- a/daemon.py
+++ b/daemon.py
@@ -1118,22 +1118,20 @@ class PubServer(BaseHTTPRequestHandler):
'epicyon=; SameSite=Strict',
callingDomain)
- def _benchmarkGETtimings(self, GETstartTime, GETtimings: [], getID: int):
- """Updates a list containing how long each segment of GET takes
+ def _benchmarkGETtimings(self, GETstartTime, GETtimings: {},
+ prevGetId: str, currGetId: str):
+ """Updates a dictionary containing how long each segment of GET takes
"""
- if self.server.debug:
- timeDiff = int((time.time() - GETstartTime) * 1000)
- logEvent = False
- if timeDiff > 100:
- logEvent = True
- if GETtimings:
- timeDiff = int(timeDiff - int(GETtimings[-1]))
- GETtimings.append(str(timeDiff))
- if logEvent:
- ctr = 1
- for timeDiff in GETtimings:
- print('GET TIMING|' + str(ctr) + '|' + timeDiff)
- ctr += 1
+ timeDiff = int((time.time() - GETstartTime) * 1000)
+ logEvent = False
+ if timeDiff > 100:
+ logEvent = True
+ if prevGetId:
+ if GETtimings.get(prevGetId):
+ timeDiff = int(timeDiff - int(GETtimings[prevGetId]))
+ GETtimings[currGetId] = str(timeDiff)
+ if logEvent:
+ print('GET TIMING ' + currGetId + ' = ' + str(timeDiff))
def _benchmarkPOSTtimings(self, POSTstartTime, POSTtimings: [],
postID: int):
@@ -1202,7 +1200,9 @@ class PubServer(BaseHTTPRequestHandler):
return
GETstartTime = time.time()
- GETtimings = []
+ GETtimings = {}
+
+ self._benchmarkGETtimings(GETstartTime, GETtimings, None, 'start')
# Since fediverse crawlers are quite active,
# make returning info to them high priority
@@ -1210,13 +1210,16 @@ class PubServer(BaseHTTPRequestHandler):
if self._nodeinfo(callingDomain):
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 1)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'start', '_nodeinfo(callingDomain)')
# minimal mastodon api
if self._mastoApi(callingDomain):
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 2)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ '_nodeinfo(callingDomain)',
+ '_mastoApi(callingDomain)')
if self.path == '/logout':
msg = \
@@ -1224,9 +1227,14 @@ class PubServer(BaseHTTPRequestHandler):
self.server.baseDir, False).encode('utf-8')
self._logout_headers('text/html', len(msg), callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ '_nodeinfo(callingDomain)',
+ 'logout')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 3)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ '_nodeinfo(callingDomain)',
+ 'show logout')
# replace https://domain/@nick with https://domain/users/nick
if self.path.startswith('/@'):
@@ -1248,7 +1256,8 @@ class PubServer(BaseHTTPRequestHandler):
if self.headers.get('Cookie'):
cookie = self.headers['Cookie']
- self._benchmarkGETtimings(GETstartTime, GETtimings, 4)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show logout', 'get cookie')
# manifest for progressive web apps
if '/manifest.json' in self.path:
@@ -1341,6 +1350,8 @@ class PubServer(BaseHTTPRequestHandler):
self._write(msg)
if self.server.debug:
print('Sent manifest: ' + callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show logout', 'send manifest')
return
# favicon image
@@ -1400,7 +1411,8 @@ class PubServer(BaseHTTPRequestHandler):
else:
print('GET Not authorized')
- self._benchmarkGETtimings(GETstartTime, GETtimings, 5)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show logout', 'isAuthorized')
if not self.server.session:
print('Starting new session during GET')
@@ -1408,9 +1420,12 @@ class PubServer(BaseHTTPRequestHandler):
if not self.server.session:
print('ERROR: GET failed to create session duing GET')
self._404()
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'isAuthorized', 'session fail')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 6)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'isAuthorized', 'create session')
# is this a html request?
htmlGET = False
@@ -1433,6 +1448,9 @@ class PubServer(BaseHTTPRequestHandler):
self._400()
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'create session', 'hasAccept')
+
# get fonts
if '/fonts/' in self.path:
fontStr = self.path.split('/fonts/')[1]
@@ -1464,6 +1482,9 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.debug:
print('font sent from cache: ' +
self.path + ' ' + callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'hasAccept',
+ 'send font from cache')
return
else:
if os.path.isfile(fontFilename):
@@ -1478,13 +1499,17 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.debug:
print('font sent from file: ' +
self.path + ' ' + callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'hasAccept',
+ 'send font from file')
return
if self.server.debug:
print('font not found: ' + self.path + ' ' + callingDomain)
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 7)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'hasAccept', 'fonts')
# treat shared inbox paths consistently
if self.path == '/sharedInbox' or \
@@ -1498,7 +1523,8 @@ class PubServer(BaseHTTPRequestHandler):
self.path = '/inbox'
- self._benchmarkGETtimings(GETstartTime, GETtimings, 8)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'fonts', 'sharedInbox enabled')
# RSS 2.0
if self.path.startswith('/blog/') and \
@@ -1538,6 +1564,9 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.debug:
print('Sent rss2 feed: ' +
self.path + ' ' + callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'sharedInbox enabled',
+ 'blog rss2')
return
if self.server.debug:
print('Failed to get rss2 feed: ' +
@@ -1545,6 +1574,9 @@ class PubServer(BaseHTTPRequestHandler):
self._404()
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'sharedInbox enabled', 'rss2 done')
+
# RSS 3.0
if self.path.startswith('/blog/') and \
self.path.endswith('/rss.txt'):
@@ -1582,6 +1614,9 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.debug:
print('Sent rss3 feed: ' +
self.path + ' ' + callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'sharedInbox enabled',
+ 'blog rss3')
return
if self.server.debug:
print('Failed to get rss3 feed: ' +
@@ -1589,6 +1624,9 @@ class PubServer(BaseHTTPRequestHandler):
self._404()
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'sharedInbox enabled', 'rss3 done')
+
# show the main blog page
if htmlGET and (self.path == '/blog' or
self.path == '/blog/' or
@@ -1617,10 +1655,15 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/html', len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'rss3 done', 'blog view')
return
self._404()
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'rss3 done', 'blog view done')
+
# show a particular page of blog entries
# for a particular account
if htmlGET and self.path.startswith('/blog/'):
@@ -1665,6 +1708,8 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/html', len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'blog view done', 'blog page')
return
self._404()
return
@@ -1687,6 +1732,14 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
None, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'blog page',
+ 'registered devices')
+ return
+
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'blog view done',
+ 'registered devices done')
if htmlGET and '/users/' in self.path:
# show the person options screen with view/follow/block/report
@@ -1715,7 +1768,8 @@ class PubServer(BaseHTTPRequestHandler):
emailAddress = None
actorJson = getPersonFromCache(self.server.baseDir,
optionsActor,
- self.server.personCache)
+ self.server.personCache,
+ True)
if actorJson:
donateUrl = getDonationUrl(actorJson)
xmppAddress = getXmppAddress(actorJson)
@@ -1742,6 +1796,9 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/html', len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'registered devices done',
+ 'person options')
return
if callingDomain.endswith('.onion') and \
self.server.onionDomain:
@@ -1759,6 +1816,9 @@ class PubServer(BaseHTTPRequestHandler):
callingDomain)
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'registered devices done',
+ 'person options done')
# show blog post
blogFilename, nickname = \
self._pathContainsBlogLink(self.server.baseDir,
@@ -1781,11 +1841,16 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/html', len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'person options done',
+ 'blog post 2')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 9)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'person options done',
+ 'blog post 2 done')
# remove a shared item
if htmlGET and '?rmshare=' in self.path:
@@ -1812,9 +1877,14 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/html', len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'blog post 2 done',
+ 'remove shared item')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 10)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'blog post 2 done',
+ 'remove shared item done')
if self.path.startswith('/terms'):
if callingDomain.endswith('.onion') and \
@@ -1832,9 +1902,14 @@ class PubServer(BaseHTTPRequestHandler):
msg = msg.encode('utf-8')
self._login_headers('text/html', len(msg), callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'blog post 2 done',
+ 'terms of service shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 11)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'blog post 2 done',
+ 'terms of service done')
# show a list of who you are following
if htmlGET and authorized and '/users/' in self.path and \
@@ -1849,8 +1924,15 @@ class PubServer(BaseHTTPRequestHandler):
msg = htmlFollowingList(self.server.baseDir, followingFilename)
self._login_headers('text/html', len(msg), callingDomain)
self._write(msg.encode('utf-8'))
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'terms of service done',
+ 'following accounts shown')
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'terms of service done',
+ 'following accounts done')
+
if self.path.endswith('/about'):
if callingDomain.endswith('.onion'):
msg = \
@@ -1871,15 +1953,22 @@ class PubServer(BaseHTTPRequestHandler):
msg = msg.encode('utf-8')
self._login_headers('text/html', len(msg), callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'following accounts done',
+ 'show about screen')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 12)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'following accounts done',
+ 'show about screen done')
# send robots.txt if asked
if self._robotsTxt():
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 13)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show about screen done',
+ 'robots txt')
# if not authorized then show the login screen
if htmlGET and self.path != '/login' and \
@@ -1928,9 +2017,14 @@ class PubServer(BaseHTTPRequestHandler):
self._redirect_headers(self.server.httpPrefix + '://' +
self.server.domainFull +
'/login', None, callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'robots txt',
+ 'show login screen')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 14)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'robots txt',
+ 'show login screen done')
# get css
# Note that this comes before the busy flag to avoid conflicts
@@ -1950,11 +2044,16 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/css', len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show login screen done',
+ 'show profile.css')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 15)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show login screen done',
+ 'profile.css done')
# manifest images used to create a home screen icon
# when selecting "add to home screen" in browsers
@@ -1992,10 +2091,17 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'profile.css done',
+ 'manifest logo shown')
return
self._404()
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'profile.css done',
+ 'manifest logo done')
+
# manifest images used to show example screenshots
# for use by app stores
if self.path == '/screenshot1.jpg' or \
@@ -2025,10 +2131,17 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'manifest logo done',
+ 'show screenshot')
return
self._404()
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'manifest logo done',
+ 'show screenshot done')
+
# image on login screen or qrcode
if self.path == '/login.png' or \
self.path == '/login.gif' or \
@@ -2061,11 +2174,16 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show screenshot done',
+ 'login screen logo')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 16)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show screenshot done',
+ 'login screen logo done')
# QR code for account handle
if '/users/' in self.path and \
@@ -2099,10 +2217,17 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'login screen logo done',
+ 'account qrcode')
return
self._404()
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'login screen logo done',
+ 'account qrcode done')
+
# search screen banner image
if '/users/' in self.path and \
self.path.endswith('/search_banner.png'):
@@ -2132,11 +2257,16 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'account qrcode done',
+ 'search screen banner')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 17)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'account qrcode done',
+ 'search screen banner done')
if '-background.' in self.path:
for ext in ('webp', 'gif', 'jpg', 'png'):
@@ -2171,11 +2301,18 @@ class PubServer(BaseHTTPRequestHandler):
bgBinary, cookie,
callingDomain)
self._write(bgBinary)
+ self._benchmarkGETtimings(GETstartTime,
+ GETtimings,
+ 'search screen ' +
+ 'banner done',
+ 'background shown')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 18)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'search screen banner done',
+ 'background shown done')
# emoji images
if '/emoji/' in self.path:
@@ -2205,11 +2342,16 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'background shown done',
+ 'show emoji')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 19)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'background shown done',
+ 'show emoji done')
# show media
# Note that this comes before the busy flag to avoid conflicts
@@ -2250,11 +2392,16 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show emoji done',
+ 'show media')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 20)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show emoji done',
+ 'show media done')
# show shared item images
# Note that this comes before the busy flag to avoid conflicts
@@ -2285,11 +2432,16 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show media done',
+ 'share files shown')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 21)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show media done',
+ 'share files done')
# icon images
# Note that this comes before the busy flag to avoid conflicts
@@ -2320,11 +2472,16 @@ class PubServer(BaseHTTPRequestHandler):
callingDomain)
self._write(mediaBinary)
self.server.iconsCache[mediaStr] = mediaBinary
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show files done',
+ 'icon shown')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 22)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show files done',
+ 'icon shown done')
# cached avatar images
# Note that this comes before the busy flag to avoid conflicts
@@ -2367,11 +2524,16 @@ class PubServer(BaseHTTPRequestHandler):
# self._404()
return
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'icon shown done',
+ 'avatar shown')
return
self._404()
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 23)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'icon shown done',
+ 'avatar shown done')
# show avatar or background image
# Note that this comes before the busy flag to avoid conflicts
@@ -2411,9 +2573,14 @@ class PubServer(BaseHTTPRequestHandler):
mediaBinary, cookie,
callingDomain)
self._write(mediaBinary)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'icon shown done',
+ 'avatar background shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 24)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'icon shown done',
+ 'avatar background shown done')
# This busy state helps to avoid flooding
# Resources which are expected to be called from a web page
@@ -2429,7 +2596,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.lastGET = currTimeGET
self.server.GETbusy = True
- self._benchmarkGETtimings(GETstartTime, GETtimings, 25)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'avatar background shown done',
+ 'GET busy time')
if not self._permittedDir(self.path):
if self.server.debug:
@@ -2437,12 +2606,18 @@ class PubServer(BaseHTTPRequestHandler):
self._404()
self.server.GETbusy = False
return
+
# get webfinger endpoint for a person
if self._webfinger(callingDomain):
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'GET busy time',
+ 'webfinger called')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 26)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'GET busy time',
+ 'permitted directory')
if self.path.startswith('/login') or \
(self.path == '/' and not authorized):
@@ -2452,9 +2627,14 @@ class PubServer(BaseHTTPRequestHandler):
self._login_headers('text/html', len(msg), callingDomain)
self._write(msg)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'permitted directory',
+ 'login shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 27)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'permitted directory',
+ 'login shown done')
# hashtag search
if self.path.startswith('/tags/') or \
@@ -2516,9 +2696,14 @@ class PubServer(BaseHTTPRequestHandler):
self._redirect_headers(originPathStrAbsolute + '/search',
cookie, callingDomain)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'login shown done',
+ 'hashtag search')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 28)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'login shown done',
+ 'hashtag search done')
# show or hide buttons in the web interface
if htmlGET and '/users/' in self.path and \
@@ -2551,9 +2736,14 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/html', len(msg), cookie, callingDomain)
self._write(msg)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'hashtag search done',
+ 'search screen shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 29)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'hashtag search done',
+ 'search screen shown done')
# Show the calendar for a user
if htmlGET and '/users/' in self.path:
@@ -2566,8 +2756,15 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/html', len(msg), cookie, callingDomain)
self._write(msg)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'search screen shown done',
+ 'calendar shown')
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'search screen shown done',
+ 'calendar shown done')
+
# Show confirmation for deleting a calendar event
if htmlGET and '/users/' in self.path:
if '/eventdelete' in self.path and \
@@ -2614,6 +2811,9 @@ class PubServer(BaseHTTPRequestHandler):
self.path.split('/eventdelete')[0]
self._redirect_headers(actor + '/calendar',
cookie, callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'calendar shown done',
+ 'calendar delete shown')
return
msg = msg.encode('utf-8')
self._set_headers('text/html', len(msg),
@@ -2622,7 +2822,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 30)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'calendar shown done',
+ 'calendar delete shown done')
# search for emoji by name
if htmlGET and '/users/' in self.path:
@@ -2635,9 +2837,14 @@ class PubServer(BaseHTTPRequestHandler):
cookie, callingDomain)
self._write(msg)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'calendar delete shown done',
+ 'emoji search shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 31)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'calendar delete shown done',
+ 'emoji search shown done')
repeatPrivate = False
if htmlGET and '?repeatprivate=' in self.path:
@@ -2732,9 +2939,14 @@ class PubServer(BaseHTTPRequestHandler):
timelineStr + '?page=' +
str(pageNumber) +
timelineBookmark, cookie, callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'emoji search shown done',
+ 'show announce')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 32)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'emoji search shown done',
+ 'show announce done')
if htmlGET and '?unrepeatprivate=' in self.path:
self.path = self.path.replace('?unrepeatprivate=', '?unrepeat=')
@@ -2823,9 +3035,14 @@ class PubServer(BaseHTTPRequestHandler):
timelineStr + '?page=' +
str(pageNumber) +
timelineBookmark, cookie, callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show announce done',
+ 'unannounce')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 33)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show announce done',
+ 'unannounce done')
# send a follow request approval from the web interface
if authorized and '/followapprove=' in self.path and \
@@ -2871,10 +3088,15 @@ class PubServer(BaseHTTPRequestHandler):
'http://' + self.server.i2pDomain + originPathStr
self._redirect_headers(originPathStrAbsolute,
cookie, callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'unannounce done',
+ 'follow approve shown')
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 34)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'unannounce done',
+ 'follow approve done')
# deny a follow request from the web interface
if authorized and '/followdeny=' in self.path and \
@@ -2911,9 +3133,14 @@ class PubServer(BaseHTTPRequestHandler):
self._redirect_headers(originPathStrAbsolute,
cookie, callingDomain)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'follow approve done',
+ 'follow deny shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 35)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'follow approve done',
+ 'follow deny done')
# like from the web interface icon
if htmlGET and '?like=' in self.path:
@@ -3013,9 +3240,14 @@ class PubServer(BaseHTTPRequestHandler):
'?page=' + str(pageNumber) +
timelineBookmark, cookie,
callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'follow deny done',
+ 'like shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 36)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'follow deny done',
+ 'like shown done')
# undo a like from the web interface icon
if htmlGET and '?unlike=' in self.path:
@@ -3115,9 +3347,14 @@ class PubServer(BaseHTTPRequestHandler):
'?page=' + str(pageNumber) +
timelineBookmark, cookie,
callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'like shown done',
+ 'unlike shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 36)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'like shown done',
+ 'unlike shown done')
# bookmark from the web interface icon
if htmlGET and '?bookmark=' in self.path:
@@ -3205,8 +3442,15 @@ class PubServer(BaseHTTPRequestHandler):
'?page=' + str(pageNumber) +
timelineBookmark, cookie,
callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'unlike shown done',
+ 'bookmark shown')
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'unlike shown done',
+ 'bookmark shown done')
+
# undo a bookmark from the web interface icon
if htmlGET and '?unbookmark=' in self.path:
pageNumber = 1
@@ -3293,9 +3537,14 @@ class PubServer(BaseHTTPRequestHandler):
'?page=' + str(pageNumber) +
timelineBookmark, cookie,
callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'bookmark shown done',
+ 'unbookmark shown')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 37)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'bookmark shown done',
+ 'unbookmark shown done')
# delete a post from the web interface icon
if htmlGET and '?delete=' in self.path:
@@ -3389,8 +3638,15 @@ class PubServer(BaseHTTPRequestHandler):
actor = 'http://' + self.server.i2pDomain + usersPath
self._redirect_headers(actor + '/' + timelineStr,
cookie, callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'unbookmark shown done',
+ 'delete shown')
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'unbookmark shown done',
+ 'delete shown done')
+
# mute a post from the web interface icon
if htmlGET and '?mute=' in self.path:
pageNumber = 1
@@ -3436,8 +3692,15 @@ class PubServer(BaseHTTPRequestHandler):
self._redirect_headers(actor + '/' +
timelineStr + timelineBookmark,
cookie, callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'delete shown done',
+ 'post muted')
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'delete shown done',
+ 'post muted done')
+
# unmute a post from the web interface icon
if htmlGET and '?unmute=' in self.path:
pageNumber = 1
@@ -3486,8 +3749,15 @@ class PubServer(BaseHTTPRequestHandler):
self._redirect_headers(actor + '/' + timelineStr +
timelineBookmark,
cookie, callingDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'post muted done',
+ 'unmute activated')
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'post muted done',
+ 'unmute activated done')
+
# reply from the web interface icon
inReplyToUrl = None
# replyWithDM = False
@@ -3681,9 +3951,14 @@ class PubServer(BaseHTTPRequestHandler):
cookie, callingDomain)
self._write(msg)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'unmute activated done',
+ 'new post made')
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 38)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'unmute activated done',
+ 'new post done')
# get an individual post from the path /@nickname/statusnumber
if '/@' in self.path:
@@ -3775,13 +4050,18 @@ class PubServer(BaseHTTPRequestHandler):
else:
self._404()
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'new post done',
+ 'individual post shown')
return
else:
self._404()
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 39)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'new post done',
+ 'individual post done')
# get replies to a post /users/nickname/statuses/number/replies
if self.path.endswith('/replies') or '/replies?page=' in self.path:
@@ -3999,6 +4279,14 @@ class PubServer(BaseHTTPRequestHandler):
cookie,
callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime,
+ GETtimings,
+ 'indiv' +
+ 'idual' +
+ ' post done',
+ 'post ' +
+ 'replies ' +
+ 'done')
else:
if self._fetchAuthenticated():
msg = \
@@ -4016,7 +4304,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 40)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'individual post done',
+ 'post replies done')
if self.path.endswith('/roles') and '/users/' in self.path:
namedStatus = self.path.split('/users/')[1]
@@ -4066,6 +4356,11 @@ class PubServer(BaseHTTPRequestHandler):
self._set_headers('text/html', len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime,
+ GETtimings,
+ 'post replies ' +
+ 'done',
+ 'show roles')
else:
if self._fetchAuthenticated():
msg = json.dumps(actorJson['roles'],
@@ -4080,6 +4375,10 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'post replies done',
+ 'show roles done')
+
# show skills on the profile page
if self.path.endswith('/skills') and '/users/' in self.path:
namedStatus = self.path.split('/users/')[1]
@@ -4131,6 +4430,11 @@ class PubServer(BaseHTTPRequestHandler):
cookie,
callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime,
+ GETtimings,
+ 'post roles ' +
+ 'done',
+ 'show skills')
else:
if self._fetchAuthenticated():
msg = json.dumps(actorJson['skills'],
@@ -4158,7 +4462,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 41)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'post roles done',
+ 'show skills done')
# get an individual post from the path
# /users/nickname/statuses/number
@@ -4240,6 +4546,11 @@ class PubServer(BaseHTTPRequestHandler):
cookie,
callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime,
+ GETtimings,
+ 'show skills ' +
+ 'done',
+ 'show status')
else:
if self._fetchAuthenticated():
msg = json.dumps(postJsonObject,
@@ -4258,7 +4569,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 42)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show skills done',
+ 'show status done')
# get the inbox for a given person
if self.path.endswith('/inbox') or '/inbox?page=' in self.path:
@@ -4276,6 +4589,9 @@ class PubServer(BaseHTTPRequestHandler):
authorized,
self.server.ocapAlways)
if inboxFeed:
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show status done',
+ 'show inbox json')
if self._requestHTTP():
nickname = self.path.replace('/users/', '')
nickname = nickname.replace('/inbox', '')
@@ -4300,6 +4616,10 @@ class PubServer(BaseHTTPRequestHandler):
maxPostsInFeed, 'inbox',
authorized,
self.server.ocapAlways)
+ self._benchmarkGETtimings(GETstartTime,
+ GETtimings,
+ 'show status done',
+ 'show inbox page')
msg = htmlInbox(self.server.defaultTimeline,
self.server.recentPostsCache,
self.server.maxRecentPosts,
@@ -4318,11 +4638,17 @@ class PubServer(BaseHTTPRequestHandler):
self.server.projectVersion,
self._isMinimal(nickname),
self.server.YTReplacementDomain)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show status done',
+ 'show inbox html')
msg = msg.encode('utf-8')
self._set_headers('text/html',
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show status done',
+ 'show inbox')
else:
# don't need authenticated fetch here because
# there is already the authorization check
@@ -4349,7 +4675,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 43)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show status done',
+ 'show inbox done')
# get the direct messages for a given person
if self.path.endswith('/dm') or '/dm?page=' in self.path:
@@ -4415,6 +4743,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show inbox done',
+ 'show dms')
else:
# don't need authenticated fetch here because
# there is already the authorization check
@@ -4441,7 +4772,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 44)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show inbox done',
+ 'show dms done')
# get the replies for a given person
if self.path.endswith('/tlreplies') or '/tlreplies?page=' in self.path:
@@ -4506,6 +4839,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show dms done',
+ 'show replies 2')
else:
# don't need authenticated fetch here because there is
# already the authorization check
@@ -4533,7 +4869,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 45)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show dms done',
+ 'show replies 2 done')
# get the media for a given person
if self.path.endswith('/tlmedia') or '/tlmedia?page=' in self.path:
@@ -4598,6 +4936,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show replies 2 done',
+ 'show media 2')
else:
# don't need authenticated fetch here because there is
# already the authorization check
@@ -4625,6 +4966,10 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show replies 2 done',
+ 'show media 2 done')
+
# get the blogs for a given person
if self.path.endswith('/tlblogs') or '/tlblogs?page=' in self.path:
if '/users/' in self.path:
@@ -4688,6 +5033,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show media 2 done',
+ 'show blogs 2')
else:
# don't need authenticated fetch here because there is
# already the authorization check
@@ -4715,7 +5063,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 46)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show media 2 done',
+ 'show blogs 2 done')
# get the shared items timeline for a given person
if self.path.endswith('/tlshares') or '/tlshares?page=' in self.path:
@@ -4754,6 +5104,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show blogs 2 done',
+ 'show shares 2')
self.server.GETbusy = False
return
# not the shares timeline
@@ -4764,6 +5117,10 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show blogs 2 done',
+ 'show shares 2 done')
+
# get the bookmarks for a given person
if self.path.endswith('/tlbookmarks') or \
'/tlbookmarks?page=' in self.path or \
@@ -4832,6 +5189,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show shares 2 done',
+ 'show bookmarks 2')
else:
# don't need authenticated fetch here because
# there is already the authorization check
@@ -4858,6 +5218,10 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show shares 2 done',
+ 'show bookmarks 2 done')
+
# get the events for a given person
if self.path.endswith('/tlevents') or \
'/tlevents?page=' in self.path or \
@@ -4930,6 +5294,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show bookmarks 2 done',
+ 'show events')
else:
# don't need authenticated fetch here because
# there is already the authorization check
@@ -4955,7 +5322,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 47)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show bookmarks 2 done',
+ 'show events done')
# get outbox feed for a person
outboxFeed = \
@@ -5016,6 +5385,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show events done',
+ 'show outbox')
else:
if self._fetchAuthenticated():
msg = json.dumps(outboxFeed,
@@ -5030,7 +5402,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 48)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show events done',
+ 'show outbox done')
# get the moderation feed for a moderator
if self.path.endswith('/moderation') or \
@@ -5094,6 +5468,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show outbox done',
+ 'show moderation')
else:
# don't need authenticated fetch here because
# there is already the authorization check
@@ -5119,7 +5496,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 49)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show outbox done',
+ 'show moderation done')
shares = \
getSharesFeedForPerson(self.server.baseDir,
@@ -5184,6 +5563,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show moderation done',
+ 'show profile 2')
self.server.GETbusy = False
return
else:
@@ -5200,7 +5582,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 50)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show moderation done',
+ 'show profile 2 done')
following = \
getFollowingFeed(self.server.baseDir, self.server.domain,
@@ -5265,6 +5649,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg), cookie, callingDomain)
self._write(msg)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show profile 2 done',
+ 'show profile 3')
return
else:
if self._fetchAuthenticated():
@@ -5279,7 +5666,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 51)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show profile 2 done',
+ 'show profile 3 done')
followers = \
getFollowingFeed(self.server.baseDir, self.server.domain,
@@ -5345,6 +5734,9 @@ class PubServer(BaseHTTPRequestHandler):
cookie, callingDomain)
self._write(msg)
self.server.GETbusy = False
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show profile 3 done',
+ 'show profile 4')
return
else:
if self._fetchAuthenticated():
@@ -5359,7 +5751,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 52)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show profile 3 done',
+ 'show profile 4 done')
# look up a person
getPerson = \
@@ -5397,6 +5791,9 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
cookie, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show profile 4 done',
+ 'show profile posts')
else:
if self._fetchAuthenticated():
msg = json.dumps(getPerson,
@@ -5410,7 +5807,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 53)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show profile 4 done',
+ 'show profile posts done')
# check that a json file was requested
if not self.path.endswith('.json'):
@@ -5428,7 +5827,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy = False
return
- self._benchmarkGETtimings(GETstartTime, GETtimings, 54)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'show profile posts done',
+ 'authenticated fetch')
# check that the file exists
filename = self.server.baseDir + self.path
@@ -5442,13 +5843,17 @@ class PubServer(BaseHTTPRequestHandler):
len(msg),
None, callingDomain)
self._write(msg)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'authenticated fetch',
+ 'arbitrary json')
else:
if self.server.debug:
print('DEBUG: GET Unknown file')
self._404()
self.server.GETbusy = False
- self._benchmarkGETtimings(GETstartTime, GETtimings, 55)
+ self._benchmarkGETtimings(GETstartTime, GETtimings,
+ 'arbitrary json', 'end benchmarks')
def do_HEAD(self):
callingDomain = self.server.domainFull
@@ -7097,7 +7502,7 @@ class PubServer(BaseHTTPRequestHandler):
if fields.get('followDMs'):
if fields['followDMs'] == 'on':
followDMsActive = True
- with open(followDMsFilename, "w") as fFile:
+ with open(followDMsFilename, 'w+') as fFile:
fFile.write('\n')
if not followDMsActive:
if os.path.isfile(followDMsFilename):
@@ -7111,21 +7516,39 @@ class PubServer(BaseHTTPRequestHandler):
if fields.get('removeTwitter'):
if fields['removeTwitter'] == 'on':
removeTwitterActive = True
- with open(removeTwitterFilename, "w") as rFile:
+ with open(removeTwitterFilename, 'w+') as rFile:
rFile.write('\n')
if not removeTwitterActive:
if os.path.isfile(removeTwitterFilename):
os.remove(removeTwitterFilename)
- # notify about new Likes
+ # hide Like button
+ hideLikeButtonFile = \
+ self.server.baseDir + '/accounts/' + \
+ nickname + '@' + self.server.domain + \
+ '/.hideLikeButton'
notifyLikesFilename = \
self.server.baseDir + '/accounts/' + \
nickname + '@' + self.server.domain + \
'/.notifyLikes'
+ hideLikeButtonActive = False
+ if fields.get('hideLikeButton'):
+ if fields['hideLikeButton'] == 'on':
+ hideLikeButtonActive = True
+ with open(hideLikeButtonFile, 'w+') as rFile:
+ rFile.write('\n')
+ # remove notify likes selection
+ if os.path.isfile(notifyLikesFilename):
+ os.remove(notifyLikesFilename)
+ if not hideLikeButtonActive:
+ if os.path.isfile(hideLikeButtonFile):
+ os.remove(hideLikeButtonFile)
+ # notify about new Likes
notifyLikesActive = False
if fields.get('notifyLikes'):
- if fields['notifyLikes'] == 'on':
+ if fields['notifyLikes'] == 'on' and \
+ not hideLikeButtonActive:
notifyLikesActive = True
- with open(notifyLikesFilename, "w") as rFile:
+ with open(notifyLikesFilename, 'w+') as rFile:
rFile.write('\n')
if not notifyLikesActive:
if os.path.isfile(notifyLikesFilename):
@@ -7162,7 +7585,7 @@ class PubServer(BaseHTTPRequestHandler):
nickname + '@' + self.server.domain + \
'/filters.txt'
if fields.get('filteredWords'):
- with open(filterFilename, "w") as filterfile:
+ with open(filterFilename, 'w+') as filterfile:
filterfile.write(fields['filteredWords'])
else:
if os.path.isfile(filterFilename):
@@ -7173,7 +7596,7 @@ class PubServer(BaseHTTPRequestHandler):
nickname + '@' + self.server.domain + \
'/replacewords.txt'
if fields.get('switchWords'):
- with open(switchFilename, "w") as switchfile:
+ with open(switchFilename, 'w+') as switchfile:
switchfile.write(fields['switchWords'])
else:
if os.path.isfile(switchFilename):
@@ -7184,7 +7607,7 @@ class PubServer(BaseHTTPRequestHandler):
nickname + '@' + self.server.domain + \
'/blocking.txt'
if fields.get('blocked'):
- with open(blockedFilename, "w") as blockedfile:
+ with open(blockedFilename, 'w+') as blockedfile:
blockedfile.write(fields['blocked'])
else:
if os.path.isfile(blockedFilename):
@@ -7195,7 +7618,7 @@ class PubServer(BaseHTTPRequestHandler):
nickname + '@' + self.server.domain + \
'/allowedinstances.txt'
if fields.get('allowedInstances'):
- with open(allowedInstancesFilename, "w") as aFile:
+ with open(allowedInstancesFilename, 'w+') as aFile:
aFile.write(fields['allowedInstances'])
else:
if os.path.isfile(allowedInstancesFilename):
@@ -7206,7 +7629,7 @@ class PubServer(BaseHTTPRequestHandler):
nickname + '@' + self.server.domain + \
'/gitprojects.txt'
if fields.get('gitProjects'):
- with open(gitProjectsFilename, "w") as aFile:
+ with open(gitProjectsFilename, 'w+') as aFile:
aFile.write(fields['gitProjects'].lower())
else:
if os.path.isfile(gitProjectsFilename):
@@ -7230,7 +7653,8 @@ class PubServer(BaseHTTPRequestHandler):
# personCache in memory
storePersonInCache(self.server.baseDir,
actorJson['id'], actorJson,
- self.server.personCache)
+ self.server.personCache,
+ True)
# clear any cached images for this actor
idStr = actorJson['id'].replace('/', '-')
removeAvatarFromCache(self.server.baseDir, idStr)
diff --git a/follow.py b/follow.py
index a2da2d991..6b764df37 100644
--- a/follow.py
+++ b/follow.py
@@ -210,7 +210,7 @@ def unfollowPerson(baseDir: str, nickname: str, domain: str,
return
with open(filename, "r") as f:
lines = f.readlines()
- with open(filename, "w") as f:
+ with open(filename, 'w+') as f:
for line in lines:
if line.strip("\n").strip("\r").lower() != handleToUnfollowLower:
f.write(line)
diff --git a/git.py b/git.py
index 68680e33e..dda0f31a0 100644
--- a/git.py
+++ b/git.py
@@ -210,12 +210,12 @@ def receiveGitPatch(baseDir: str, nickname: str, domain: str,
return False
patchStr = \
gitAddFromHandle(patchStr, '@' + fromNickname + '@' + fromDomain)
- with open(patchFilename, "w") as patchFile:
+ with open(patchFilename, 'w+') as patchFile:
patchFile.write(patchStr)
patchNotifyFilename = \
baseDir + '/accounts/' + \
nickname + '@' + domain + '/.newPatchContent'
- with open(patchNotifyFilename, "w") as patchFile:
+ with open(patchNotifyFilename, 'w+') as patchFile:
patchFile.write(patchStr)
return True
return False
diff --git a/happening.py b/happening.py
index 1c81e0d5c..6f1d2b1e7 100644
--- a/happening.py
+++ b/happening.py
@@ -244,7 +244,7 @@ def getTodaysEvents(baseDir: str, nickname: str, domain: str,
# if some posts have been deleted then regenerate the calendar file
if recreateEventsFile:
- calendarFile = open(calendarFilename, "w")
+ calendarFile = open(calendarFilename, 'w+')
for postId in calendarPostIds:
calendarFile.write(postId + '\n')
calendarFile.close()
@@ -412,7 +412,7 @@ def getThisWeeksEvents(baseDir: str, nickname: str, domain: str) -> {}:
# if some posts have been deleted then regenerate the calendar file
if recreateEventsFile:
- calendarFile = open(calendarFilename, "w")
+ calendarFile = open(calendarFilename, 'w+')
for postId in calendarPostIds:
calendarFile.write(postId + '\n')
calendarFile.close()
@@ -494,7 +494,7 @@ def getCalendarEvents(baseDir: str, nickname: str, domain: str,
# if some posts have been deleted then regenerate the calendar file
if recreateEventsFile:
- calendarFile = open(calendarFilename, "w")
+ calendarFile = open(calendarFilename, 'w+')
for postId in calendarPostIds:
calendarFile.write(postId + '\n')
calendarFile.close()
diff --git a/inbox.py b/inbox.py
index ced05e1f7..107865bda 100644
--- a/inbox.py
+++ b/inbox.py
@@ -199,7 +199,8 @@ def getPersonPubKey(baseDir: str, session, personUrl: str,
if debug:
print('DEBUG: Obtaining public key for shared inbox')
personUrl = personUrl.replace('/users/inbox', '/inbox')
- personJson = getPersonFromCache(baseDir, personUrl, personCache)
+ personJson = \
+ getPersonFromCache(baseDir, personUrl, personCache, True)
if not personJson:
if debug:
print('DEBUG: Obtaining public key for ' + personUrl)
@@ -228,7 +229,7 @@ def getPersonPubKey(baseDir: str, session, personUrl: str,
if debug:
print('DEBUG: Public key not found for ' + personUrl)
- storePersonInCache(baseDir, personUrl, personJson, personCache)
+ storePersonInCache(baseDir, personUrl, personJson, personCache, True)
return pubKey
@@ -272,6 +273,8 @@ def inboxPermittedMessage(domain: str, messageJson: {},
return False
if messageJson['object'].get('inReplyTo'):
inReplyTo = messageJson['object']['inReplyTo']
+ if not isinstance(inReplyTo, str):
+ return False
if not urlPermitted(inReplyTo, federationList, "inbox:write"):
return False
@@ -863,7 +866,8 @@ def personReceiveUpdate(baseDir: str,
'cached actor when updating')
return False
# save to cache in memory
- storePersonInCache(baseDir, personJson['id'], personJson, personCache)
+ storePersonInCache(baseDir, personJson['id'], personJson,
+ personCache, True)
# save to cache on file
if saveJson(personJson, actorFilename):
print('actor updated for ' + personJson['id'])
@@ -1596,6 +1600,8 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
if not messageJson['object'].get('to'):
return False
replyTo = messageJson['object']['inReplyTo']
+ if not isinstance(replyTo, str):
+ return False
if debug:
print('DEBUG: post contains a reply')
# is this a reply to a post on this domain?
@@ -1636,7 +1642,7 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
repliesFile.write(messageId + '\n')
repliesFile.close()
else:
- repliesFile = open(postRepliesFilename, "w")
+ repliesFile = open(postRepliesFilename, 'w+')
repliesFile.write(messageId + '\n')
repliesFile.close()
return True
@@ -1760,6 +1766,9 @@ def obtainAvatarForReplyPost(session, baseDir: str, httpPrefix: str,
if not lookupActor:
return
+ if not isinstance(lookupActor, str):
+ return
+
if not ('/users/' in lookupActor or
'/accounts/' in lookupActor or
'/channel/' in lookupActor or
@@ -2355,13 +2364,17 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
if nickname != 'inbox':
# replies index will be updated
updateIndexList.append('tlreplies')
- if not isMuted(baseDir, nickname, domain,
- postJsonObject['object']['inReplyTo']):
- replyNotify(baseDir, handle,
- httpPrefix + '://' + domain +
- '/users/' + nickname + '/tlreplies')
- else:
- isReplyToMutedPost = True
+ inReplyTo = postJsonObject['object']['inReplyTo']
+ if inReplyTo:
+ if isinstance(inReplyTo, str):
+ if not isMuted(baseDir, nickname, domain,
+ inReplyTo):
+ replyNotify(baseDir, handle,
+ httpPrefix + '://' + domain +
+ '/users/' + nickname +
+ '/tlreplies')
+ else:
+ isReplyToMutedPost = True
if isImageMedia(session, baseDir, httpPrefix,
nickname, domain, postJsonObject,
@@ -2386,7 +2399,7 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
# This enables you to ignore a threat that's getting boring
if isReplyToMutedPost:
print('MUTE REPLY: ' + destinationFilename)
- muteFile = open(destinationFilename + '.muted', "w")
+ muteFile = open(destinationFilename + '.muted', 'w+')
if muteFile:
muteFile.write('\n')
muteFile.close()
diff --git a/person.py b/person.py
index 0afdc7b14..af7020df6 100644
--- a/person.py
+++ b/person.py
@@ -350,7 +350,7 @@ def createPersonBase(baseDir: str, nickname: str, domain: str, port: int,
if not os.path.isdir(baseDir + privateKeysSubdir):
os.mkdir(baseDir + privateKeysSubdir)
filename = baseDir + privateKeysSubdir + '/' + handle + '.key'
- with open(filename, "w") as text_file:
+ with open(filename, 'w+') as text_file:
print(privateKeyPem, file=text_file)
# save the public key
@@ -358,7 +358,7 @@ def createPersonBase(baseDir: str, nickname: str, domain: str, port: int,
if not os.path.isdir(baseDir + publicKeysSubdir):
os.mkdir(baseDir + publicKeysSubdir)
filename = baseDir + publicKeysSubdir + '/' + handle + '.pem'
- with open(filename, "w") as text_file:
+ with open(filename, 'w+') as text_file:
print(publicKeyPem, file=text_file)
if password:
@@ -454,22 +454,22 @@ def createPerson(baseDir: str, nickname: str, domain: str, port: int,
setRole(baseDir, nickname, domain, 'instance', 'delegator')
setConfigParam(baseDir, 'admin', nickname)
+ if not os.path.isdir(baseDir + '/accounts'):
+ os.mkdir(baseDir + '/accounts')
+ if not os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
+ os.mkdir(baseDir + '/accounts/' + nickname + '@' + domain)
+
if manualFollowerApproval:
followDMsFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/.followDMs'
- with open(followDMsFilename, "w") as fFile:
+ with open(followDMsFilename, 'w+') as fFile:
fFile.write('\n')
# notify when posts are liked
notifyLikesFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/.notifyLikes'
- with open(notifyLikesFilename, "w") as fFile:
- fFile.write('\n')
-
- if not os.path.isdir(baseDir + '/accounts'):
- os.mkdir(baseDir + '/accounts')
- if not os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
- os.mkdir(baseDir + '/accounts/' + nickname + '@' + domain)
+ with open(notifyLikesFilename, 'w+') as nFile:
+ nFile.write('\n')
if os.path.isfile(baseDir + '/img/default-avatar.png'):
copyfile(baseDir + '/img/default-avatar.png',
diff --git a/posts.py b/posts.py
index 1517fea4d..95026c113 100644
--- a/posts.py
+++ b/posts.py
@@ -209,7 +209,8 @@ def getPersonBox(baseDir: str, session, wfRequest: {},
personUrl = httpPrefix + '://' + domain + '/users/' + nickname
if not personUrl:
return None, None, None, None, None, None, None, None
- personJson = getPersonFromCache(baseDir, personUrl, personCache)
+ personJson = \
+ getPersonFromCache(baseDir, personUrl, personCache, True)
if not personJson:
if '/channel/' in personUrl or '/accounts/' in personUrl:
asHeader = {
@@ -265,7 +266,7 @@ def getPersonBox(baseDir: str, session, wfRequest: {},
if personJson.get('name'):
displayName = personJson['name']
- storePersonInCache(baseDir, personUrl, personJson, personCache)
+ storePersonInCache(baseDir, personUrl, personJson, personCache, True)
return boxJson, pubKeyId, pubKey, personId, sharedInbox, \
capabilityAcquisition, avatarUrl, displayName
@@ -388,15 +389,16 @@ def getPosts(session, outboxUrl: str, maxPosts: int,
inReplyTo = ''
if item['object'].get('inReplyTo'):
if item['object']['inReplyTo']:
- # No replies to non-permitted domains
- if not urlPermitted(item['object']['inReplyTo'],
- federationList,
- "objects:read"):
- if debug:
- print('url not permitted ' +
- item['object']['inReplyTo'])
- continue
- inReplyTo = item['object']['inReplyTo']
+ if isinstance(item['object']['inReplyTo'], str):
+ # No replies to non-permitted domains
+ if not urlPermitted(item['object']['inReplyTo'],
+ federationList,
+ "objects:read"):
+ if debug:
+ print('url not permitted ' +
+ item['object']['inReplyTo'])
+ continue
+ inReplyTo = item['object']['inReplyTo']
conversation = ''
if item['object'].get('conversation'):
@@ -483,10 +485,11 @@ def getPostDomains(session, outboxUrl: str, maxPosts: int,
if not isinstance(item['object'], dict):
continue
if item['object'].get('inReplyTo'):
- postDomain, postPort = \
- getDomainFromActor(item['object']['inReplyTo'])
- if postDomain not in postDomains:
- postDomains.append(postDomain)
+ if isinstance(item['object']['inReplyTo'], str):
+ postDomain, postPort = \
+ getDomainFromActor(item['object']['inReplyTo'])
+ if postDomain not in postDomains:
+ postDomains.append(postDomain)
if item['object'].get('tag'):
for tagItem in item['object']['tag']:
@@ -2675,8 +2678,9 @@ def isReply(postJsonObject: {}, actor: str) -> bool:
postJsonObject['object']['type'] != 'Article':
return False
if postJsonObject['object'].get('inReplyTo'):
- if postJsonObject['object']['inReplyTo'].startswith(actor):
- return True
+ if isinstance(postJsonObject['object']['inReplyTo'], str):
+ if postJsonObject['object']['inReplyTo'].startswith(actor):
+ return True
if not postJsonObject['object'].get('tag'):
return False
if not isinstance(postJsonObject['object']['tag'], list):
@@ -3532,7 +3536,7 @@ def mutePost(baseDir: str, nickname: str, domain: str, postId: str,
return
print('MUTE: ' + postFilename)
- muteFile = open(postFilename + '.muted', "w")
+ muteFile = open(postFilename + '.muted', 'w+')
if muteFile:
muteFile.write('\n')
muteFile.close()
diff --git a/question.py b/question.py
index a52a9bb09..9618154ae 100644
--- a/question.py
+++ b/question.py
@@ -25,6 +25,8 @@ def questionUpdateVotes(baseDir: str, nickname: str, domain: str,
return None
if not replyJson['object']['inReplyTo']:
return None
+ if not isinstance(replyJson['object']['inReplyTo'], str):
+ return None
if not replyJson['object'].get('name'):
return None
inReplyTo = replyJson['object']['inReplyTo']
@@ -64,7 +66,7 @@ def questionUpdateVotes(baseDir: str, nickname: str, domain: str,
votersFilename = questionPostFilename.replace('.json', '.voters')
if not os.path.isfile(votersFilename):
# create a new voters file
- votersFile = open(votersFilename, "w")
+ votersFile = open(votersFilename, 'w+')
if votersFile:
votersFile.write(replyJson['actor'] +
votersFileSeparator +
@@ -97,7 +99,7 @@ def questionUpdateVotes(baseDir: str, nickname: str, domain: str,
else:
newlines.append(voteLine)
if saveVotersFile:
- with open(votersFilename, "w") as votersFile:
+ with open(votersFilename, 'w+') as votersFile:
for voteLine in newlines:
votersFile.write(voteLine)
else:
diff --git a/roles.py b/roles.py
index 967997b07..f2bc57374 100644
--- a/roles.py
+++ b/roles.py
@@ -52,7 +52,7 @@ def addModerator(baseDir: str, nickname: str, domain: str) -> None:
if moderator == nickname:
return
lines.append(nickname)
- with open(moderatorsFile, "w") as f:
+ with open(moderatorsFile, 'w+') as f:
for moderator in lines:
moderator = moderator.strip('\n').strip('\r')
if len(moderator) > 1:
@@ -74,7 +74,7 @@ def removeModerator(baseDir: str, nickname: str):
return
with open(moderatorsFile, "r") as f:
lines = f.readlines()
- with open(moderatorsFile, "w") as f:
+ with open(moderatorsFile, 'w+') as f:
for moderator in lines:
moderator = moderator.strip('\n').strip('\r')
if len(moderator) > 1 and moderator != nickname:
diff --git a/tests.py b/tests.py
index 59b97c462..13e3a2892 100644
--- a/tests.py
+++ b/tests.py
@@ -209,8 +209,8 @@ def testCache():
"test": "This is a test"
}
personCache = {}
- storePersonInCache(None, personUrl, personJson, personCache)
- result = getPersonFromCache(None, personUrl, personCache)
+ storePersonInCache(None, personUrl, personJson, personCache, True)
+ result = getPersonFromCache(None, personUrl, personCache, True)
assert result['id'] == 123456
assert result['test'] == 'This is a test'
@@ -2064,6 +2064,9 @@ def testTranslations():
langDict = {}
for lang in languagesStr:
langJson = loadJson('translations/' + lang + '.json')
+ if not langJson:
+ print('Missing language file ' +
+ 'translations/' + lang + '.json')
assert langJson
langDict[lang] = langJson
diff --git a/translations/ar.json b/translations/ar.json
index b6223d1d1..6faa4aa4a 100644
--- a/translations/ar.json
+++ b/translations/ar.json
@@ -282,5 +282,6 @@
"Create a new event": "أنشئ حدثًا جديدًا",
"Moderation policy or code of conduct": "سياسة الوسطية أو قواعد السلوك",
"Edit event": "تحرير الحدث",
- "Notify when posts are liked": "يخطر عندما يتم اعجاب المشاركات"
+ "Notify when posts are liked": "يخطر عندما يتم اعجاب المشاركات",
+ "Don't show the Like button": "لا تظهر زر أعجبني"
}
diff --git a/translations/ca.json b/translations/ca.json
index 343576942..c59b79eb8 100644
--- a/translations/ca.json
+++ b/translations/ca.json
@@ -282,5 +282,6 @@
"Create a new event": "Creeu un esdeveniment nou",
"Moderation policy or code of conduct": "Política de moderació o codi de conducta",
"Edit event": "Edita l’esdeveniment",
- "Notify when posts are liked": "Notifiqueu-ho quan us agradin les publicacions"
+ "Notify when posts are liked": "Notifiqueu-ho quan us agradin les publicacions",
+ "Don't show the Like button": "No mostreu el botó M'agrada"
}
diff --git a/translations/cy.json b/translations/cy.json
index 631892be2..e77c7ecea 100644
--- a/translations/cy.json
+++ b/translations/cy.json
@@ -282,5 +282,6 @@
"Create a new event": "Creu digwyddiad newydd",
"Moderation policy or code of conduct": "Polisi cymedroli neu god ymddygiad",
"Edit event": "Golygu digwyddiad",
- "Notify when posts are liked": "Hysbysu pryd mae swyddi'n cael eu hoffi"
+ "Notify when posts are liked": "Hysbysu pryd mae swyddi'n cael eu hoffi",
+ "Don't show the Like button": "Peidiwch â dangos y botwm Hoffi"
}
diff --git a/translations/de.json b/translations/de.json
index 99794eb22..957c54f6b 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -282,5 +282,6 @@
"Create a new event": "Erstellen Sie ein neues Ereignis",
"Moderation policy or code of conduct": "Moderationsrichtlinie oder Verhaltenskodex",
"Edit event": "Ereignis bearbeiten",
- "Notify when posts are liked": "Benachrichtigen, wenn Beiträge gefallen"
+ "Notify when posts are liked": "Benachrichtigen, wenn Beiträge gefallen",
+ "Don't show the Like button": "Zeigen Sie nicht die Schaltfläche \"Gefällt mir\" an"
}
diff --git a/translations/en.json b/translations/en.json
index 2476be31e..aaa545bc7 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -282,5 +282,6 @@
"Create a new event": "Create a new event",
"Moderation policy or code of conduct": "Moderation policy or code of conduct",
"Edit event": "Edit event",
- "Notify when posts are liked": "Notify when posts are liked"
+ "Notify when posts are liked": "Notify when posts are liked",
+ "Don't show the Like button": "Don't show the Like button"
}
diff --git a/translations/es.json b/translations/es.json
index a6969342a..07d010a93 100644
--- a/translations/es.json
+++ b/translations/es.json
@@ -282,5 +282,6 @@
"Create a new event": "Crea un nuevo evento",
"Moderation policy or code of conduct": "Política de moderación o código de conducta",
"Edit event": "Editar evento",
- "Notify when posts are liked": "Notificar cuando les gusten las publicaciones"
+ "Notify when posts are liked": "Notificar cuando les gusten las publicaciones",
+ "Don't show the Like button": "No mostrar el botón Me gusta"
}
diff --git a/translations/fr.json b/translations/fr.json
index b113e888b..2f85eecda 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -282,5 +282,6 @@
"Create a new event": "Créer un nouvel événement",
"Moderation policy or code of conduct": "Politique de modération ou code de conduite",
"Edit event": "Modifier l'événement",
- "Notify when posts are liked": "Notifier lorsque les messages sont aimés"
+ "Notify when posts are liked": "Notifier lorsque les messages sont aimés",
+ "Don't show the Like button": "Ne pas afficher le bouton J'aime"
}
diff --git a/translations/ga.json b/translations/ga.json
index 04ad6f2f3..f758411f2 100644
--- a/translations/ga.json
+++ b/translations/ga.json
@@ -282,5 +282,6 @@
"Create a new event": "Cruthaigh imeacht nua",
"Moderation policy or code of conduct": "Beartas modhnóireachta nó cód iompair",
"Edit event": "Cuir imeacht in eagar",
- "Notify when posts are liked": "Cuir in iúl cathain is maith poist"
+ "Notify when posts are liked": "Cuir in iúl cathain is maith poist",
+ "Don't show the Like button": "Ná taispeáin an cnaipe Cosúil"
}
diff --git a/translations/hi.json b/translations/hi.json
index a8f984adb..6da7225e2 100644
--- a/translations/hi.json
+++ b/translations/hi.json
@@ -282,5 +282,6 @@
"Create a new event": "एक नई घटना बनाएँ",
"Moderation policy or code of conduct": "मॉडरेशन पॉलिसी या आचार संहिता",
"Edit event": "घटना संपादित करें",
- "Notify when posts are liked": "पोस्ट पसंद आने पर सूचित करें"
+ "Notify when posts are liked": "पोस्ट पसंद आने पर सूचित करें",
+ "Don't show the Like button": "लाइक बटन न दिखाएं"
}
diff --git a/translations/it.json b/translations/it.json
index 35443ffa4..71952e1a6 100644
--- a/translations/it.json
+++ b/translations/it.json
@@ -282,5 +282,6 @@
"Create a new event": "Crea un nuovo evento",
"Moderation policy or code of conduct": "Politica di moderazione o codice di condotta",
"Edit event": "Modifica evento",
- "Notify when posts are liked": "Avvisa quando i post sono piaciuti"
+ "Notify when posts are liked": "Avvisa quando i post sono piaciuti",
+ "Don't show the Like button": "Non mostrare il pulsante Mi piace"
}
diff --git a/translations/ja.json b/translations/ja.json
index a11bf5ea1..384098456 100644
--- a/translations/ja.json
+++ b/translations/ja.json
@@ -282,5 +282,6 @@
"Create a new event": "新しいイベントを作成する",
"Moderation policy or code of conduct": "モデレートポリシーまたは行動規範",
"Edit event": "イベントを編集",
- "Notify when posts are liked": "投稿が高く評価されたときに通知する"
+ "Notify when posts are liked": "投稿が高く評価されたときに通知する",
+ "Don't show the Like button": "「いいね!」ボタンを表示しない"
}
diff --git a/translations/oc.json b/translations/oc.json
index 2a020527c..fae634148 100644
--- a/translations/oc.json
+++ b/translations/oc.json
@@ -278,5 +278,6 @@
"Create a new event": "Create a new event",
"Moderation policy or code of conduct": "Moderation policy or code of conduct",
"Edit event": "Edit event",
- "Notify when posts are liked": "Notify when posts are liked"
+ "Notify when posts are liked": "Notify when posts are liked",
+ "Don't show the Like button": "Don't show the Like button"
}
diff --git a/translations/pt.json b/translations/pt.json
index 27a0466bb..010df87da 100644
--- a/translations/pt.json
+++ b/translations/pt.json
@@ -282,5 +282,6 @@
"Create a new event": "Crie um novo evento",
"Moderation policy or code of conduct": "Política de moderação ou código de conduta",
"Edit event": "Editar evento",
- "Notify when posts are liked": "Notificar quando as postagens forem curtidas"
+ "Notify when posts are liked": "Notificar quando as postagens forem curtidas",
+ "Don't show the Like button": "Não mostrar o botão Curtir"
}
diff --git a/translations/ru.json b/translations/ru.json
index 2b5d61d44..f4742761f 100644
--- a/translations/ru.json
+++ b/translations/ru.json
@@ -282,5 +282,6 @@
"Create a new event": "Создать новое мероприятие",
"Moderation policy or code of conduct": "Политика модерации или кодекс поведения",
"Edit event": "Изменить мероприятие",
- "Notify when posts are liked": "Уведомлять, когда публикации нравятся"
+ "Notify when posts are liked": "Уведомлять, когда публикации нравятся",
+ "Don't show the Like button": "Не показывать кнопку \"Нравится\""
}
diff --git a/translations/zh.json b/translations/zh.json
index 3ce3f2d7d..7c3fffd88 100644
--- a/translations/zh.json
+++ b/translations/zh.json
@@ -282,5 +282,6 @@
"Create a new event": "建立新活动",
"Moderation policy or code of conduct": "审核政策或行为准则",
"Edit event": "编辑活动",
- "Notify when posts are liked": "通知喜欢的帖子"
+ "Notify when posts are liked": "通知喜欢的帖子",
+ "Don't show the Like button": "不显示“赞”按钮"
}
diff --git a/utils.py b/utils.py
index 073e820a8..f143bebbd 100644
--- a/utils.py
+++ b/utils.py
@@ -75,12 +75,12 @@ def saveJson(jsonObject: {}, filename: str) -> bool:
return False
-def loadJson(filename: str, delaySec=2) -> {}:
+def loadJson(filename: str, delaySec=2, maxTries=5) -> {}:
"""Makes a few attempts to load a json formatted file
"""
jsonObject = None
tries = 0
- while tries < 5:
+ while tries < maxTries:
try:
with open(filename, 'r') as fp:
data = fp.read()
@@ -351,7 +351,7 @@ def followPerson(baseDir: str, nickname: str, domain: str,
for line in lines:
if handleToFollow not in line:
newLines += line
- with open(unfollowedFilename, "w") as f:
+ with open(unfollowedFilename, 'w+') as f:
f.write(newLines)
if not os.path.isdir(baseDir + '/accounts'):
@@ -383,7 +383,7 @@ def followPerson(baseDir: str, nickname: str, domain: str,
followNickname, followDomain)
if debug:
print('DEBUG: creating new following file to follow ' + handleToFollow)
- with open(filename, "w") as followfile:
+ with open(filename, 'w+') as followfile:
followfile.write(handleToFollow + '\n')
return True
@@ -473,6 +473,8 @@ def isReplyToBlogPost(baseDir: str, nickname: str, domain: str,
return False
if not postJsonObject['object'].get('inReplyTo'):
return False
+ if not isinstance(postJsonObject['object']['inReplyTo'], str):
+ return False
blogsIndexFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/tlblogs.index'
if not os.path.isfile(blogsIndexFilename):
@@ -905,12 +907,20 @@ def searchBoxPosts(baseDir: str, nickname: str, domain: str,
def getFileCaseInsensitive(path: str) -> str:
"""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):
+ return path
+ if path != path.lower():
+ if os.path.isfile(path.lower()):
+ return path.lower()
directory, filename = os.path.split(path)
directory, filename = (directory or '.'), filename.lower()
for f in os.listdir(directory):
- newpath = os.path.join(directory, f)
- if os.path.isfile(newpath) and f.lower() == filename:
- return newpath
+ if f.lower() == filename:
+ newpath = os.path.join(directory, f)
+ if os.path.isfile(newpath):
+ return newpath
return path
diff --git a/webinterface.py b/webinterface.py
index a2e451b4d..778565009 100644
--- a/webinterface.py
+++ b/webinterface.py
@@ -199,7 +199,8 @@ def setBlogAddress(actorJson: {}, blogAddress: str) -> None:
def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
actor: str, avatarUrl: str,
- personCache: {}, force=False) -> str:
+ personCache: {}, allowDownloads: bool,
+ force=False) -> str:
"""Updates the cached avatar for the given actor
"""
if not avatarUrl:
@@ -232,7 +233,8 @@ def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
avatarImageFilename = avatarImagePath + '.webp'
else:
return None
- if not os.path.isfile(avatarImageFilename) or force:
+
+ if (not os.path.isfile(avatarImageFilename) or force) and allowDownloads:
try:
print('avatar image url: ' + avatarUrl)
result = session.get(avatarUrl,
@@ -282,18 +284,23 @@ def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
"public keys don't match when downloading actor for " +
actor)
return None
- storePersonInCache(baseDir, actor, personJson, personCache)
- return getPersonAvatarUrl(baseDir, actor, personCache)
+ storePersonInCache(baseDir, actor, personJson, personCache,
+ allowDownloads)
+ return getPersonAvatarUrl(baseDir, actor, personCache,
+ allowDownloads)
return None
return avatarImageFilename.replace(baseDir + '/cache', '')
-def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {}) -> str:
+def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {},
+ allowDownloads: bool) -> str:
"""Returns the avatar url for the person
"""
- personJson = getPersonFromCache(baseDir, personUrl, personCache)
+ personJson = \
+ getPersonFromCache(baseDir, personUrl, personCache, allowDownloads)
if not personJson:
return None
+
# get from locally stored image
actorStr = personJson['id'].replace('/', '-')
avatarImagePath = baseDir + '/cache/avatars/' + actorStr
@@ -796,7 +803,7 @@ def htmlHashtagSearch(nickname: str, domain: str, port: int,
showIndividualPostIcons = True
allowDeletion = False
hashtagSearchForm += \
- individualPostAsHtml(recentPostsCache,
+ individualPostAsHtml(True, recentPostsCache,
maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest,
@@ -1025,7 +1032,7 @@ def htmlHistorySearch(translate: {}, baseDir: str,
showIndividualPostIcons = True
allowDeletion = False
historySearchForm += \
- individualPostAsHtml(recentPostsCache,
+ individualPostAsHtml(True, recentPostsCache,
maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest,
@@ -1084,6 +1091,7 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str,
followDMs = ''
removeTwitter = ''
notifyLikes = ''
+ hideLikeButton = ''
mediaInstanceStr = ''
displayNickname = nickname
bioStr = ''
@@ -1134,6 +1142,9 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str,
if os.path.isfile(baseDir + '/accounts/' +
nickname + '@' + domain + '/.notifyLikes'):
notifyLikes = 'checked'
+ if os.path.isfile(baseDir + '/accounts/' +
+ nickname + '@' + domain + '/.hideLikeButton'):
+ hideLikeButton = 'checked'
mediaInstance = getConfigParam(baseDir, "mediaInstance")
if mediaInstance:
@@ -1473,6 +1484,10 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str,
' ' + \
translate['Notify when posts are liked'] + '
\n'
+ editProfileForm += \
+ ' ' + \
+ translate["Don't show the Like button"] + '
\n'
editProfileForm += \
'