mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of gitlab.com:bashrc2/epicyon
commit
b76d4bf4c3
104
daemon.py
104
daemon.py
|
|
@ -392,6 +392,36 @@ def saveDomainQrcode(baseDir: str, httpPrefix: str,
|
||||||
class PubServer(BaseHTTPRequestHandler):
|
class PubServer(BaseHTTPRequestHandler):
|
||||||
protocol_version = 'HTTP/1.1'
|
protocol_version = 'HTTP/1.1'
|
||||||
|
|
||||||
|
def _updateKnownCrawlers(self, uaStr: str) -> None:
|
||||||
|
"""Updates a dictionary of known crawlers accessing nodeinfo
|
||||||
|
or the masto API
|
||||||
|
"""
|
||||||
|
if not uaStr:
|
||||||
|
return
|
||||||
|
|
||||||
|
currTime = int(time.time())
|
||||||
|
if self.server.knownCrawlers.get(uaStr):
|
||||||
|
self.server.knownCrawlers[uaStr]['hits'] += 1
|
||||||
|
self.server.knownCrawlers[uaStr]['lastseen'] = currTime
|
||||||
|
else:
|
||||||
|
self.server.knownCrawlers[uaStr] = {
|
||||||
|
"lastseen": currTime,
|
||||||
|
"hits": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if currTime - self.server.lastKnownCrawler >= 30:
|
||||||
|
# remove any old observations
|
||||||
|
removeCrawlers = []
|
||||||
|
for ua, item in self.server.knownCrawlers.items():
|
||||||
|
if currTime - item['lastseen'] >= 60 * 60 * 24 * 30:
|
||||||
|
removeCrawlers.append(ua)
|
||||||
|
for ua in removeCrawlers:
|
||||||
|
del self.server.knownCrawlers[ua]
|
||||||
|
# save the list of crawlers
|
||||||
|
saveJson(self.server.knownCrawlers,
|
||||||
|
self.server.baseDir + '/accounts/knownCrawlers.json')
|
||||||
|
self.server.lastKnownCrawler = currTime
|
||||||
|
|
||||||
def _getInstanceUrl(self, callingDomain: str) -> str:
|
def _getInstanceUrl(self, callingDomain: str) -> str:
|
||||||
"""Returns the URL for this instance
|
"""Returns the URL for this instance
|
||||||
"""
|
"""
|
||||||
|
|
@ -520,11 +550,22 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
def _blockedUserAgent(self, callingDomain: str, agentStr: str) -> bool:
|
def _blockedUserAgent(self, callingDomain: str, agentStr: str) -> bool:
|
||||||
"""Should a GET or POST be blocked based upon its user agent?
|
"""Should a GET or POST be blocked based upon its user agent?
|
||||||
"""
|
"""
|
||||||
|
if not agentStr:
|
||||||
|
return False
|
||||||
|
|
||||||
|
agentStrLower = agentStr.lower()
|
||||||
|
defaultAgentBlocks = [
|
||||||
|
'fedilist.com'
|
||||||
|
]
|
||||||
|
for uaBlock in defaultAgentBlocks:
|
||||||
|
if uaBlock in agentStrLower:
|
||||||
|
print('Blocked User agent: ' + uaBlock)
|
||||||
|
return True
|
||||||
|
|
||||||
agentDomain = None
|
agentDomain = None
|
||||||
|
|
||||||
if agentStr:
|
if agentStr:
|
||||||
# is this a web crawler? If so the block it
|
# is this a web crawler? If so the block it
|
||||||
agentStrLower = agentStr.lower()
|
|
||||||
if 'bot/' in agentStrLower or 'bot-' in agentStrLower:
|
if 'bot/' in agentStrLower or 'bot-' in agentStrLower:
|
||||||
if self.server.newsInstance:
|
if self.server.newsInstance:
|
||||||
return False
|
return False
|
||||||
|
|
@ -969,6 +1010,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _mastoApiV1(self, path: str, callingDomain: str,
|
def _mastoApiV1(self, path: str, callingDomain: str,
|
||||||
|
uaStr: str,
|
||||||
authorized: bool,
|
authorized: bool,
|
||||||
httpPrefix: str,
|
httpPrefix: str,
|
||||||
baseDir: str, nickname: str, domain: str,
|
baseDir: str, nickname: str, domain: str,
|
||||||
|
|
@ -989,10 +1031,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
print('mastodon api v1: ' + path)
|
print('mastodon api v1: ' + path)
|
||||||
print('mastodon api v1: authorized ' + str(authorized))
|
print('mastodon api v1: authorized ' + str(authorized))
|
||||||
print('mastodon api v1: nickname ' + str(nickname))
|
print('mastodon api v1: nickname ' + str(nickname))
|
||||||
|
self._updateKnownCrawlers(uaStr)
|
||||||
|
|
||||||
brochMode = brochModeIsActive(baseDir)
|
brochMode = brochModeIsActive(baseDir)
|
||||||
sendJson, sendJsonStr = mastoApiV1Response(path,
|
sendJson, sendJsonStr = mastoApiV1Response(path,
|
||||||
callingDomain,
|
callingDomain,
|
||||||
|
uaStr,
|
||||||
authorized,
|
authorized,
|
||||||
httpPrefix,
|
httpPrefix,
|
||||||
baseDir,
|
baseDir,
|
||||||
|
|
@ -1031,6 +1075,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _mastoApi(self, path: str, callingDomain: str,
|
def _mastoApi(self, path: str, callingDomain: str,
|
||||||
|
uaStr: str,
|
||||||
authorized: bool, httpPrefix: str,
|
authorized: bool, httpPrefix: str,
|
||||||
baseDir: str, nickname: str, domain: str,
|
baseDir: str, nickname: str, domain: str,
|
||||||
domainFull: str,
|
domainFull: str,
|
||||||
|
|
@ -1041,18 +1086,19 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
projectVersion: str,
|
projectVersion: str,
|
||||||
customEmoji: [],
|
customEmoji: [],
|
||||||
showNodeInfoAccounts: bool) -> bool:
|
showNodeInfoAccounts: bool) -> bool:
|
||||||
return self._mastoApiV1(path, callingDomain, authorized,
|
return self._mastoApiV1(path, callingDomain, uaStr, authorized,
|
||||||
httpPrefix, baseDir, nickname, domain,
|
httpPrefix, baseDir, nickname, domain,
|
||||||
domainFull, onionDomain, i2pDomain,
|
domainFull, onionDomain, i2pDomain,
|
||||||
translate, registration, systemLanguage,
|
translate, registration, systemLanguage,
|
||||||
projectVersion, customEmoji,
|
projectVersion, customEmoji,
|
||||||
showNodeInfoAccounts)
|
showNodeInfoAccounts)
|
||||||
|
|
||||||
def _nodeinfo(self, callingDomain: str) -> bool:
|
def _nodeinfo(self, uaStr: str, callingDomain: str) -> bool:
|
||||||
if not self.path.startswith('/nodeinfo/2.0'):
|
if not self.path.startswith('/nodeinfo/2.0'):
|
||||||
return False
|
return False
|
||||||
if self.server.debug:
|
if self.server.debug:
|
||||||
print('DEBUG: nodeinfo ' + self.path)
|
print('DEBUG: nodeinfo ' + self.path)
|
||||||
|
self._updateKnownCrawlers(uaStr)
|
||||||
|
|
||||||
# If we are in broch mode then don't show potentially
|
# If we are in broch mode then don't show potentially
|
||||||
# sensitive metadata.
|
# sensitive metadata.
|
||||||
|
|
@ -1091,7 +1137,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self._set_headers('application/ld+json', msglen,
|
self._set_headers('application/ld+json', msglen,
|
||||||
None, callingDomain, True)
|
None, callingDomain, True)
|
||||||
self._write(msg)
|
self._write(msg)
|
||||||
print('nodeinfo sent')
|
print('nodeinfo sent to ' + callingDomain)
|
||||||
return True
|
return True
|
||||||
self._404()
|
self._404()
|
||||||
return True
|
return True
|
||||||
|
|
@ -11819,6 +11865,36 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _showKnownCrawlers(self, callingDomain: str, path: str,
|
||||||
|
baseDir: str, knownCrawlers: {}) -> bool:
|
||||||
|
"""Show a list of known web crawlers
|
||||||
|
"""
|
||||||
|
if '/users/' not in path:
|
||||||
|
return False
|
||||||
|
if not path.endswith('/crawlers'):
|
||||||
|
return False
|
||||||
|
nickname = getNicknameFromActor(path)
|
||||||
|
if not nickname:
|
||||||
|
return False
|
||||||
|
if not isModerator(baseDir, nickname):
|
||||||
|
return False
|
||||||
|
crawlersList = []
|
||||||
|
currTime = int(time.time())
|
||||||
|
recentCrawlers = 60 * 60 * 24 * 30
|
||||||
|
for uaStr, item in knownCrawlers.items():
|
||||||
|
if item['lastseen'] - currTime < recentCrawlers:
|
||||||
|
crawlersList.append(str(item['hits']) + ' ' + uaStr)
|
||||||
|
crawlersList.sort(reverse=True)
|
||||||
|
msg = ''
|
||||||
|
for lineStr in crawlersList:
|
||||||
|
msg += lineStr + '\n'
|
||||||
|
msg = msg.encode('utf-8')
|
||||||
|
msglen = len(msg)
|
||||||
|
self._set_headers('text/plain; charset=utf-8', msglen,
|
||||||
|
None, callingDomain, True)
|
||||||
|
self._write(msg)
|
||||||
|
return True
|
||||||
|
|
||||||
def _editProfile(self, callingDomain: str, path: str,
|
def _editProfile(self, callingDomain: str, path: str,
|
||||||
translate: {}, baseDir: str,
|
translate: {}, baseDir: str,
|
||||||
httpPrefix: str, domain: str, port: int,
|
httpPrefix: str, domain: str, port: int,
|
||||||
|
|
@ -12113,7 +12189,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
# Since fediverse crawlers are quite active,
|
# Since fediverse crawlers are quite active,
|
||||||
# make returning info to them high priority
|
# make returning info to them high priority
|
||||||
# get nodeinfo endpoint
|
# get nodeinfo endpoint
|
||||||
if self._nodeinfo(callingDomain):
|
if self._nodeinfo(uaStr, callingDomain):
|
||||||
return
|
return
|
||||||
|
|
||||||
fitnessPerformance(GETstartTime, self.server.fitness,
|
fitnessPerformance(GETstartTime, self.server.fitness,
|
||||||
|
|
@ -12446,7 +12522,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
return
|
return
|
||||||
|
|
||||||
# minimal mastodon api
|
# minimal mastodon api
|
||||||
if self._mastoApi(self.path, callingDomain, authorized,
|
if self._mastoApi(self.path, callingDomain, uaStr,
|
||||||
|
authorized,
|
||||||
self.server.httpPrefix,
|
self.server.httpPrefix,
|
||||||
self.server.baseDir,
|
self.server.baseDir,
|
||||||
self.authorizedNickname,
|
self.authorizedNickname,
|
||||||
|
|
@ -14349,6 +14426,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.GETbusy = False
|
self.server.GETbusy = False
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# list of known crawlers accessing nodeinfo or masto API
|
||||||
|
if self._showKnownCrawlers(callingDomain, self.path,
|
||||||
|
self.server.baseDir,
|
||||||
|
self.server.knownCrawlers):
|
||||||
|
return
|
||||||
|
|
||||||
# edit profile in web interface
|
# edit profile in web interface
|
||||||
if self._editProfile(callingDomain, self.path,
|
if self._editProfile(callingDomain, self.path,
|
||||||
self.server.translate,
|
self.server.translate,
|
||||||
|
|
@ -17302,6 +17385,15 @@ def runDaemon(listsEnabled: str,
|
||||||
createNewsInbox(baseDir, domain, port, httpPrefix)
|
createNewsInbox(baseDir, domain, port, httpPrefix)
|
||||||
setConfigParam(baseDir, "listsEnabled", "Murdoch press")
|
setConfigParam(baseDir, "listsEnabled", "Murdoch press")
|
||||||
|
|
||||||
|
# dict of known web crawlers accessing nodeinfo or the masto API
|
||||||
|
# and how many times they have been seen
|
||||||
|
httpd.knownCrawlers = {}
|
||||||
|
knownCrawlersFilename = baseDir + '/accounts/knownCrawlers.json'
|
||||||
|
if os.path.isfile(knownCrawlersFilename):
|
||||||
|
httpd.knownCrawlers = loadJson(knownCrawlersFilename)
|
||||||
|
# when was the last crawler seen?
|
||||||
|
httpd.lastKnownCrawler = 0
|
||||||
|
|
||||||
if listsEnabled:
|
if listsEnabled:
|
||||||
httpd.listsEnabled = listsEnabled
|
httpd.listsEnabled = listsEnabled
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ def _getMastoApiV1Account(baseDir: str, nickname: str, domain: str) -> {}:
|
||||||
|
|
||||||
|
|
||||||
def mastoApiV1Response(path: str, callingDomain: str,
|
def mastoApiV1Response(path: str, callingDomain: str,
|
||||||
|
uaStr: str,
|
||||||
authorized: bool,
|
authorized: bool,
|
||||||
httpPrefix: str,
|
httpPrefix: str,
|
||||||
baseDir: str, nickname: str, domain: str,
|
baseDir: str, nickname: str, domain: str,
|
||||||
|
|
@ -100,12 +101,18 @@ def mastoApiV1Response(path: str, callingDomain: str,
|
||||||
"""
|
"""
|
||||||
sendJson = None
|
sendJson = None
|
||||||
sendJsonStr = ''
|
sendJsonStr = ''
|
||||||
|
if not uaStr:
|
||||||
|
uaStr = ''
|
||||||
|
|
||||||
# parts of the api needing authorization
|
# parts of the api needing authorization
|
||||||
if authorized and nickname:
|
if authorized and nickname:
|
||||||
if path == '/api/v1/accounts/verify_credentials':
|
if path == '/api/v1/accounts/verify_credentials':
|
||||||
sendJson = _getMastoApiV1Account(baseDir, nickname, domain)
|
sendJson = _getMastoApiV1Account(baseDir, nickname, domain)
|
||||||
sendJsonStr = 'masto API account sent for ' + nickname
|
sendJsonStr = \
|
||||||
|
'masto API account sent for ' + nickname + ' ' + uaStr
|
||||||
|
|
||||||
|
# information about where the request is coming from
|
||||||
|
callingInfo = ' ' + uaStr + ', ' + callingDomain
|
||||||
|
|
||||||
# Parts of the api which don't need authorization
|
# Parts of the api which don't need authorization
|
||||||
mastoId = _getMastApiV1Id(path)
|
mastoId = _getMastApiV1Id(path)
|
||||||
|
|
@ -121,57 +128,73 @@ def mastoApiV1Response(path: str, callingDomain: str,
|
||||||
path = path.split('?')[0]
|
path = path.split('?')[0]
|
||||||
if path.endswith('/followers'):
|
if path.endswith('/followers'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API followers sent for ' + nickname
|
sendJsonStr = \
|
||||||
|
'masto API followers sent for ' + nickname + \
|
||||||
|
callingInfo
|
||||||
elif path.endswith('/following'):
|
elif path.endswith('/following'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API following sent for ' + nickname
|
sendJsonStr = \
|
||||||
|
'masto API following sent for ' + nickname + \
|
||||||
|
callingInfo
|
||||||
elif path.endswith('/statuses'):
|
elif path.endswith('/statuses'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API statuses sent for ' + nickname
|
sendJsonStr = \
|
||||||
|
'masto API statuses sent for ' + nickname + \
|
||||||
|
callingInfo
|
||||||
elif path.endswith('/search'):
|
elif path.endswith('/search'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API search sent ' + originalPath
|
sendJsonStr = \
|
||||||
|
'masto API search sent ' + originalPath + \
|
||||||
|
callingInfo
|
||||||
elif path.endswith('/relationships'):
|
elif path.endswith('/relationships'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = \
|
sendJsonStr = \
|
||||||
'masto API relationships sent ' + originalPath
|
'masto API relationships sent ' + originalPath + \
|
||||||
|
callingInfo
|
||||||
else:
|
else:
|
||||||
sendJson = \
|
sendJson = \
|
||||||
_getMastoApiV1Account(baseDir, pathNickname, domain)
|
_getMastoApiV1Account(baseDir, pathNickname, domain)
|
||||||
sendJsonStr = 'masto API account sent for ' + nickname
|
sendJsonStr = \
|
||||||
|
'masto API account sent for ' + nickname + \
|
||||||
|
callingInfo
|
||||||
|
|
||||||
# NOTE: adding support for '/api/v1/directory seems to create
|
# NOTE: adding support for '/api/v1/directory seems to create
|
||||||
# federation problems, so avoid implementing that
|
# federation problems, so avoid implementing that
|
||||||
|
|
||||||
if path.startswith('/api/v1/blocks'):
|
if path.startswith('/api/v1/blocks'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API instance blocks sent ' + path
|
sendJsonStr = \
|
||||||
|
'masto API instance blocks sent ' + path + callingInfo
|
||||||
elif path.startswith('/api/v1/favorites'):
|
elif path.startswith('/api/v1/favorites'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API favorites sent ' + path
|
sendJsonStr = 'masto API favorites sent ' + path + callingInfo
|
||||||
elif path.startswith('/api/v1/follow_requests'):
|
elif path.startswith('/api/v1/follow_requests'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API follow requests sent ' + path
|
sendJsonStr = \
|
||||||
|
'masto API follow requests sent ' + path + callingInfo
|
||||||
elif path.startswith('/api/v1/mutes'):
|
elif path.startswith('/api/v1/mutes'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API mutes sent ' + path
|
sendJsonStr = \
|
||||||
|
'masto API mutes sent ' + path + callingInfo
|
||||||
elif path.startswith('/api/v1/notifications'):
|
elif path.startswith('/api/v1/notifications'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API notifications sent ' + path
|
sendJsonStr = \
|
||||||
|
'masto API notifications sent ' + path + callingInfo
|
||||||
elif path.startswith('/api/v1/reports'):
|
elif path.startswith('/api/v1/reports'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API reports sent ' + path
|
sendJsonStr = 'masto API reports sent ' + path + callingInfo
|
||||||
elif path.startswith('/api/v1/statuses'):
|
elif path.startswith('/api/v1/statuses'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API statuses sent ' + path
|
sendJsonStr = 'masto API statuses sent ' + path + callingInfo
|
||||||
elif path.startswith('/api/v1/timelines'):
|
elif path.startswith('/api/v1/timelines'):
|
||||||
sendJson = {
|
sendJson = {
|
||||||
'error': 'This method requires an authenticated user'
|
'error': 'This method requires an authenticated user'
|
||||||
}
|
}
|
||||||
sendJsonStr = 'masto API timelines sent ' + path
|
sendJsonStr = 'masto API timelines sent ' + path + callingInfo
|
||||||
elif path.startswith('/api/v1/custom_emojis'):
|
elif path.startswith('/api/v1/custom_emojis'):
|
||||||
sendJson = customEmoji
|
sendJson = customEmoji
|
||||||
sendJsonStr = 'masto API custom emojis sent ' + path
|
sendJsonStr = \
|
||||||
|
'masto API custom emojis sent ' + path + callingInfo
|
||||||
|
|
||||||
adminNickname = getConfigParam(baseDir, 'admin')
|
adminNickname = getConfigParam(baseDir, 'admin')
|
||||||
if adminNickname and path == '/api/v1/instance':
|
if adminNickname and path == '/api/v1/instance':
|
||||||
|
|
@ -208,7 +231,7 @@ def mastoApiV1Response(path: str, callingDomain: str,
|
||||||
registration,
|
registration,
|
||||||
systemLanguage,
|
systemLanguage,
|
||||||
projectVersion)
|
projectVersion)
|
||||||
sendJsonStr = 'masto API instance metadata sent'
|
sendJsonStr = 'masto API instance metadata sent ' + uaStr
|
||||||
elif path.startswith('/api/v1/instance/peers'):
|
elif path.startswith('/api/v1/instance/peers'):
|
||||||
# This is just a dummy result.
|
# This is just a dummy result.
|
||||||
# Showing the full list of peers would have privacy implications.
|
# Showing the full list of peers would have privacy implications.
|
||||||
|
|
@ -216,8 +239,8 @@ def mastoApiV1Response(path: str, callingDomain: str,
|
||||||
# small instances a full list of peers would convey a lot of
|
# small instances a full list of peers would convey a lot of
|
||||||
# information about the interests of a small number of accounts
|
# information about the interests of a small number of accounts
|
||||||
sendJson = ['mastodon.social', domainFull]
|
sendJson = ['mastodon.social', domainFull]
|
||||||
sendJsonStr = 'masto API peers metadata sent'
|
sendJsonStr = 'masto API peers metadata sent ' + uaStr
|
||||||
elif path.startswith('/api/v1/instance/activity'):
|
elif path.startswith('/api/v1/instance/activity'):
|
||||||
sendJson = []
|
sendJson = []
|
||||||
sendJsonStr = 'masto API activity metadata sent'
|
sendJsonStr = 'masto API activity metadata sent ' + uaStr
|
||||||
return sendJson, sendJsonStr
|
return sendJson, sendJsonStr
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "انضم",
|
"Join": "انضم",
|
||||||
"Leave": "يترك",
|
"Leave": "يترك",
|
||||||
"System Monitor": "مراقب النظام",
|
"System Monitor": "مراقب النظام",
|
||||||
"Add content warnings for the following sites": "أضف تحذيرات المحتوى للمواقع التالية"
|
"Add content warnings for the following sites": "أضف تحذيرات المحتوى للمواقع التالية",
|
||||||
|
"Known Web Crawlers": "برامج زحف الويب المعروفة"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Uneix-te",
|
"Join": "Uneix-te",
|
||||||
"Leave": "Marxa",
|
"Leave": "Marxa",
|
||||||
"System Monitor": "Monitor del sistema",
|
"System Monitor": "Monitor del sistema",
|
||||||
"Add content warnings for the following sites": "Afegiu advertiments de contingut per als llocs següents"
|
"Add content warnings for the following sites": "Afegiu advertiments de contingut per als llocs següents",
|
||||||
|
"Known Web Crawlers": "Exploradors web coneguts"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Ymunwch",
|
"Join": "Ymunwch",
|
||||||
"Leave": "Gadewch",
|
"Leave": "Gadewch",
|
||||||
"System Monitor": "Monitor System",
|
"System Monitor": "Monitor System",
|
||||||
"Add content warnings for the following sites": "Ychwanegwch rybuddion cynnwys ar gyfer y gwefannau canlynol"
|
"Add content warnings for the following sites": "Ychwanegwch rybuddion cynnwys ar gyfer y gwefannau canlynol",
|
||||||
|
"Known Web Crawlers": "Crawlers Gwe Hysbys"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Verbinden",
|
"Join": "Verbinden",
|
||||||
"Leave": "Verlassen",
|
"Leave": "Verlassen",
|
||||||
"System Monitor": "Systemmonitor",
|
"System Monitor": "Systemmonitor",
|
||||||
"Add content warnings for the following sites": "Inhaltswarnungen für die folgenden Websites hinzufügen"
|
"Add content warnings for the following sites": "Inhaltswarnungen für die folgenden Websites hinzufügen",
|
||||||
|
"Known Web Crawlers": "Bekannte Web-Crawler"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Join",
|
"Join": "Join",
|
||||||
"Leave": "Leave",
|
"Leave": "Leave",
|
||||||
"System Monitor": "System Monitor",
|
"System Monitor": "System Monitor",
|
||||||
"Add content warnings for the following sites": "Add content warnings for the following sites"
|
"Add content warnings for the following sites": "Add content warnings for the following sites",
|
||||||
|
"Known Web Crawlers": "Known Web Crawlers"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Entrar",
|
"Join": "Entrar",
|
||||||
"Leave": "Dejar",
|
"Leave": "Dejar",
|
||||||
"System Monitor": "Monitor del sistema",
|
"System Monitor": "Monitor del sistema",
|
||||||
"Add content warnings for the following sites": "Agregue advertencias de contenido para los siguientes sitios"
|
"Add content warnings for the following sites": "Agregue advertencias de contenido para los siguientes sitios",
|
||||||
|
"Known Web Crawlers": "Rastreadores web conocidos"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Rejoindre",
|
"Join": "Rejoindre",
|
||||||
"Leave": "Laisser",
|
"Leave": "Laisser",
|
||||||
"System Monitor": "Moniteur système",
|
"System Monitor": "Moniteur système",
|
||||||
"Add content warnings for the following sites": "Ajouter des avertissements de contenu pour les sites suivants"
|
"Add content warnings for the following sites": "Ajouter des avertissements de contenu pour les sites suivants",
|
||||||
|
"Known Web Crawlers": "Crawlers Web connus"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Bí páirteach",
|
"Join": "Bí páirteach",
|
||||||
"Leave": "Fág",
|
"Leave": "Fág",
|
||||||
"System Monitor": "Monatóir Córais",
|
"System Monitor": "Monatóir Córais",
|
||||||
"Add content warnings for the following sites": "Cuir rabhaidh ábhair leis na suíomhanna seo a leanas"
|
"Add content warnings for the following sites": "Cuir rabhaidh ábhair leis na suíomhanna seo a leanas",
|
||||||
|
"Known Web Crawlers": "Crawlers Gréasáin Aitheanta"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "शामिल हों",
|
"Join": "शामिल हों",
|
||||||
"Leave": "छोड़ना",
|
"Leave": "छोड़ना",
|
||||||
"System Monitor": "सिस्टम मॉनिटर",
|
"System Monitor": "सिस्टम मॉनिटर",
|
||||||
"Add content warnings for the following sites": "निम्नलिखित साइटों के लिए सामग्री चेतावनियाँ जोड़ें"
|
"Add content warnings for the following sites": "निम्नलिखित साइटों के लिए सामग्री चेतावनियाँ जोड़ें",
|
||||||
|
"Known Web Crawlers": "ज्ञात वेब क्रॉलर"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Aderire",
|
"Join": "Aderire",
|
||||||
"Leave": "Lasciare",
|
"Leave": "Lasciare",
|
||||||
"System Monitor": "Monitor di sistema",
|
"System Monitor": "Monitor di sistema",
|
||||||
"Add content warnings for the following sites": "Aggiungi avvisi sui contenuti per i seguenti siti"
|
"Add content warnings for the following sites": "Aggiungi avvisi sui contenuti per i seguenti siti",
|
||||||
|
"Known Web Crawlers": "Crawler Web conosciuti"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "加入",
|
"Join": "加入",
|
||||||
"Leave": "離れる",
|
"Leave": "離れる",
|
||||||
"System Monitor": "システムモニター",
|
"System Monitor": "システムモニター",
|
||||||
"Add content warnings for the following sites": "次のサイトのコンテンツ警告を追加します"
|
"Add content warnings for the following sites": "次のサイトのコンテンツ警告を追加します",
|
||||||
|
"Known Web Crawlers": "既知のWebクローラー"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Bihevgirêdan",
|
"Join": "Bihevgirêdan",
|
||||||
"Leave": "Terikandin",
|
"Leave": "Terikandin",
|
||||||
"System Monitor": "System Monitor",
|
"System Monitor": "System Monitor",
|
||||||
"Add content warnings for the following sites": "Ji bo malperên jêrîn hişyariyên naverokê zêde bikin"
|
"Add content warnings for the following sites": "Ji bo malperên jêrîn hişyariyên naverokê zêde bikin",
|
||||||
|
"Known Web Crawlers": "Crawlerên Webê yên naskirî"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -485,5 +485,6 @@
|
||||||
"Join": "Join",
|
"Join": "Join",
|
||||||
"Leave": "Leave",
|
"Leave": "Leave",
|
||||||
"System Monitor": "System Monitor",
|
"System Monitor": "System Monitor",
|
||||||
"Add content warnings for the following sites": "Add content warnings for the following sites"
|
"Add content warnings for the following sites": "Add content warnings for the following sites",
|
||||||
|
"Known Web Crawlers": "Known Web Crawlers"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Juntar",
|
"Join": "Juntar",
|
||||||
"Leave": "Sair",
|
"Leave": "Sair",
|
||||||
"System Monitor": "Monitor de Sistema",
|
"System Monitor": "Monitor de Sistema",
|
||||||
"Add content warnings for the following sites": "Adicione avisos de conteúdo para os seguintes sites"
|
"Add content warnings for the following sites": "Adicione avisos de conteúdo para os seguintes sites",
|
||||||
|
"Known Web Crawlers": "Rastreadores da Web conhecidos"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Присоединиться",
|
"Join": "Присоединиться",
|
||||||
"Leave": "Оставлять",
|
"Leave": "Оставлять",
|
||||||
"System Monitor": "Системный монитор",
|
"System Monitor": "Системный монитор",
|
||||||
"Add content warnings for the following sites": "Добавить предупреждения о содержании для следующих сайтов"
|
"Add content warnings for the following sites": "Добавить предупреждения о содержании для следующих сайтов",
|
||||||
|
"Known Web Crawlers": "Известные веб-сканеры"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "Jiunge",
|
"Join": "Jiunge",
|
||||||
"Leave": "Ondoka",
|
"Leave": "Ondoka",
|
||||||
"System Monitor": "Ufuatiliaji wa Mfumo",
|
"System Monitor": "Ufuatiliaji wa Mfumo",
|
||||||
"Add content warnings for the following sites": "Ongeza maonyo ya yaliyomo kwa wavuti zifuatazo"
|
"Add content warnings for the following sites": "Ongeza maonyo ya yaliyomo kwa wavuti zifuatazo",
|
||||||
|
"Known Web Crawlers": "Watambaji Wavuti Wanaojulikana"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,5 +489,6 @@
|
||||||
"Join": "加入",
|
"Join": "加入",
|
||||||
"Leave": "离开",
|
"Leave": "离开",
|
||||||
"System Monitor": "系统监视器",
|
"System Monitor": "系统监视器",
|
||||||
"Add content warnings for the following sites": "为以下网站添加内容警告"
|
"Add content warnings for the following sites": "为以下网站添加内容警告",
|
||||||
|
"Known Web Crawlers": "已知的网络爬虫"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
utils.py
2
utils.py
|
|
@ -715,7 +715,7 @@ def getStatusNumber(publishedStr: str = None) -> (str, str):
|
||||||
|
|
||||||
|
|
||||||
def evilIncarnate() -> []:
|
def evilIncarnate() -> []:
|
||||||
return ('gab.com', 'gabfed.com', 'spinster.xyz',
|
return ('fedilist.com', 'gab.com', 'gabfed.com', 'spinster.xyz',
|
||||||
'kiwifarms.cc', 'djitter.com')
|
'kiwifarms.cc', 'djitter.com')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1520,8 +1520,8 @@ def _htmlEditProfileSharedItems(baseDir: str, nickname: str, domain: str,
|
||||||
|
|
||||||
|
|
||||||
def _htmlEditProfileFiltering(baseDir: str, nickname: str, domain: str,
|
def _htmlEditProfileFiltering(baseDir: str, nickname: str, domain: str,
|
||||||
userAgentsBlocked: str, translate: {},
|
userAgentsBlocked: str,
|
||||||
replyIntervalHours: int,
|
translate: {}, replyIntervalHours: int,
|
||||||
CWlists: {}, listsEnabled: str) -> str:
|
CWlists: {}, listsEnabled: str) -> str:
|
||||||
"""Filtering and blocking section of edit profile screen
|
"""Filtering and blocking section of edit profile screen
|
||||||
"""
|
"""
|
||||||
|
|
@ -1669,6 +1669,10 @@ def _htmlEditProfileFiltering(baseDir: str, nickname: str, domain: str,
|
||||||
allowedInstancesStr + '</textarea>\n'
|
allowedInstancesStr + '</textarea>\n'
|
||||||
|
|
||||||
if isModerator(baseDir, nickname):
|
if isModerator(baseDir, nickname):
|
||||||
|
editProfileForm += \
|
||||||
|
'<a href="/users/' + nickname + '/crawlers">' + \
|
||||||
|
translate['Known Web Crawlers'] + '</a><br>\n'
|
||||||
|
|
||||||
userAgentsBlockedStr = ''
|
userAgentsBlockedStr = ''
|
||||||
for ua in userAgentsBlocked:
|
for ua in userAgentsBlocked:
|
||||||
if userAgentsBlockedStr:
|
if userAgentsBlockedStr:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue