2020-11-10 10:25:21 +00:00
|
|
|
__filename__ = "webapp_moderation.py"
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
__license__ = "AGPL3+"
|
2021-01-26 10:07:42 +00:00
|
|
|
__version__ = "1.2.0"
|
2020-11-10 10:25:21 +00:00
|
|
|
__maintainer__ = "Bob Mottram"
|
2021-09-10 16:14:50 +00:00
|
|
|
__email__ = "bob@libreserver.org"
|
2020-11-10 10:25:21 +00:00
|
|
|
__status__ = "Production"
|
2021-06-26 11:27:14 +00:00
|
|
|
__module_group__ = "Moderation"
|
2020-11-10 10:25:21 +00:00
|
|
|
|
|
|
|
import os
|
2021-12-26 14:17:13 +00:00
|
|
|
from utils import is_artist
|
2021-12-26 18:46:43 +00:00
|
|
|
from utils import is_account_dir
|
2021-12-26 12:45:03 +00:00
|
|
|
from utils import get_full_domain
|
2021-12-26 13:27:57 +00:00
|
|
|
from utils import is_editor
|
2021-12-26 15:13:34 +00:00
|
|
|
from utils import load_json
|
2021-12-27 22:19:18 +00:00
|
|
|
from utils import get_nickname_from_actor
|
2021-12-27 19:05:25 +00:00
|
|
|
from utils import get_domain_from_actor
|
2021-12-26 14:08:58 +00:00
|
|
|
from utils import get_config_param
|
2021-12-26 10:19:59 +00:00
|
|
|
from utils import local_actor_url
|
2021-01-11 10:08:05 +00:00
|
|
|
from posts import downloadFollowCollection
|
2020-12-16 16:43:51 +00:00
|
|
|
from posts import getPublicPostInfo
|
2021-12-28 19:33:29 +00:00
|
|
|
from posts import is_moderator
|
2020-11-10 10:25:21 +00:00
|
|
|
from webapp_timeline import htmlTimeline
|
2020-12-20 11:00:17 +00:00
|
|
|
# from webapp_utils import getPersonAvatarUrl
|
2020-12-16 16:43:51 +00:00
|
|
|
from webapp_utils import getContentWarningButton
|
2020-11-12 17:05:38 +00:00
|
|
|
from webapp_utils import htmlHeaderWithExternalStyle
|
2020-11-10 10:25:21 +00:00
|
|
|
from webapp_utils import htmlFooter
|
2020-12-09 22:55:15 +00:00
|
|
|
from blocking import isBlockedDomain
|
2021-01-10 23:06:38 +00:00
|
|
|
from blocking import isBlocked
|
2021-12-28 16:56:57 +00:00
|
|
|
from session import create_session
|
2020-11-10 10:25:21 +00:00
|
|
|
|
|
|
|
|
2021-12-28 13:56:43 +00:00
|
|
|
def htmlModeration(css_cache: {}, defaultTimeline: str,
|
2021-12-26 20:01:37 +00:00
|
|
|
recent_posts_cache: {}, max_recent_posts: int,
|
2020-11-10 10:25:21 +00:00
|
|
|
translate: {}, pageNumber: int, itemsPerPage: int,
|
2021-12-25 22:17:49 +00:00
|
|
|
session, base_dir: str, wfRequest: {}, person_cache: {},
|
2020-11-10 10:25:21 +00:00
|
|
|
nickname: str, domain: str, port: int, inboxJson: {},
|
2021-12-25 21:29:53 +00:00
|
|
|
allow_deletion: bool,
|
2021-12-25 20:34:38 +00:00
|
|
|
http_prefix: str, project_version: str,
|
2021-12-25 17:15:52 +00:00
|
|
|
yt_replace_domain: str,
|
2021-12-25 20:55:47 +00:00
|
|
|
twitter_replacement_domain: str,
|
2021-12-25 20:06:27 +00:00
|
|
|
show_published_date_only: bool,
|
2021-12-25 20:14:45 +00:00
|
|
|
newswire: {}, positive_voting: bool,
|
2021-12-25 19:34:20 +00:00
|
|
|
show_publish_as_icon: bool,
|
2021-12-25 19:31:24 +00:00
|
|
|
full_width_tl_button_header: bool,
|
2021-12-25 19:19:14 +00:00
|
|
|
icons_as_buttons: bool,
|
2021-12-25 19:09:03 +00:00
|
|
|
rss_icon_at_top: bool,
|
2021-12-25 19:00:00 +00:00
|
|
|
publish_button_at_top: bool,
|
2020-12-21 23:09:00 +00:00
|
|
|
authorized: bool, moderationActionStr: str,
|
2021-12-25 23:38:53 +00:00
|
|
|
theme: str, peertube_instances: [],
|
2021-12-25 18:54:50 +00:00
|
|
|
allow_local_network_access: bool,
|
2021-12-25 23:09:49 +00:00
|
|
|
text_mode_banner: str,
|
2021-12-25 23:03:28 +00:00
|
|
|
accessKeys: {}, system_language: str,
|
2021-12-25 18:23:12 +00:00
|
|
|
max_like_count: int,
|
2021-12-25 18:05:01 +00:00
|
|
|
shared_items_federated_domains: [],
|
2021-12-25 23:03:28 +00:00
|
|
|
signing_priv_key_pem: str,
|
2021-12-25 23:26:38 +00:00
|
|
|
cw_lists: {}, lists_enabled: str) -> str:
|
2020-11-10 10:25:21 +00:00
|
|
|
"""Show the moderation feed as html
|
|
|
|
This is what you see when selecting the "mod" timeline
|
|
|
|
"""
|
2021-12-26 14:17:13 +00:00
|
|
|
artist = is_artist(base_dir, nickname)
|
2021-12-28 13:56:43 +00:00
|
|
|
return htmlTimeline(css_cache, defaultTimeline,
|
2021-12-26 20:01:37 +00:00
|
|
|
recent_posts_cache, max_recent_posts,
|
2020-11-10 10:25:21 +00:00
|
|
|
translate, pageNumber,
|
2021-12-25 16:17:53 +00:00
|
|
|
itemsPerPage, session, base_dir,
|
2021-12-25 22:17:49 +00:00
|
|
|
wfRequest, person_cache,
|
2020-11-10 10:25:21 +00:00
|
|
|
nickname, domain, port, inboxJson, 'moderation',
|
2021-12-25 21:29:53 +00:00
|
|
|
allow_deletion, http_prefix,
|
2021-12-25 20:34:38 +00:00
|
|
|
project_version, True, False,
|
2021-12-25 17:15:52 +00:00
|
|
|
yt_replace_domain,
|
2021-12-25 20:55:47 +00:00
|
|
|
twitter_replacement_domain,
|
2021-12-25 20:06:27 +00:00
|
|
|
show_published_date_only,
|
2021-12-25 20:14:45 +00:00
|
|
|
newswire, False, False, artist, positive_voting,
|
2021-12-25 19:34:20 +00:00
|
|
|
show_publish_as_icon,
|
2021-12-25 19:31:24 +00:00
|
|
|
full_width_tl_button_header,
|
2021-12-25 19:19:14 +00:00
|
|
|
icons_as_buttons, rss_icon_at_top,
|
|
|
|
publish_button_at_top,
|
2020-12-23 23:59:49 +00:00
|
|
|
authorized, moderationActionStr, theme,
|
2021-12-25 23:38:53 +00:00
|
|
|
peertube_instances, allow_local_network_access,
|
2021-12-25 23:09:49 +00:00
|
|
|
text_mode_banner, accessKeys, system_language,
|
2021-12-25 18:23:12 +00:00
|
|
|
max_like_count, shared_items_federated_domains,
|
2021-12-25 23:26:38 +00:00
|
|
|
signing_priv_key_pem, cw_lists, lists_enabled)
|
2020-11-10 10:25:21 +00:00
|
|
|
|
|
|
|
|
2021-12-28 13:56:43 +00:00
|
|
|
def htmlAccountInfo(css_cache: {}, translate: {},
|
2021-12-25 17:09:22 +00:00
|
|
|
base_dir: str, http_prefix: str,
|
2020-12-09 22:55:15 +00:00
|
|
|
nickname: str, domain: str, port: int,
|
2021-07-18 14:15:16 +00:00
|
|
|
searchHandle: str, debug: bool,
|
2021-12-25 23:03:28 +00:00
|
|
|
system_language: str, signing_priv_key_pem: str) -> str:
|
2020-12-09 22:55:15 +00:00
|
|
|
"""Shows which domains a search handle interacts with.
|
|
|
|
This screen is shown if a moderator enters a handle and selects info
|
|
|
|
on the moderation screen
|
|
|
|
"""
|
2021-12-25 23:03:28 +00:00
|
|
|
signing_priv_key_pem = None
|
2020-12-09 22:55:15 +00:00
|
|
|
msgStr1 = 'This account interacts with the following instances'
|
|
|
|
|
|
|
|
infoForm = ''
|
2021-12-25 16:17:53 +00:00
|
|
|
cssFilename = base_dir + '/epicyon-profile.css'
|
|
|
|
if os.path.isfile(base_dir + '/epicyon.css'):
|
|
|
|
cssFilename = base_dir + '/epicyon.css'
|
2020-12-09 22:55:15 +00:00
|
|
|
|
2021-01-11 19:46:21 +00:00
|
|
|
instanceTitle = \
|
2021-12-26 14:08:58 +00:00
|
|
|
get_config_param(base_dir, 'instanceTitle')
|
2021-11-07 10:38:11 +00:00
|
|
|
infoForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle, None)
|
2020-12-09 22:55:15 +00:00
|
|
|
|
2021-12-27 22:19:18 +00:00
|
|
|
searchNickname = get_nickname_from_actor(searchHandle)
|
2021-12-27 19:05:25 +00:00
|
|
|
searchDomain, searchPort = get_domain_from_actor(searchHandle)
|
2020-12-09 22:55:15 +00:00
|
|
|
|
2020-12-10 10:21:54 +00:00
|
|
|
searchHandle = searchNickname + '@' + searchDomain
|
2021-01-10 23:06:38 +00:00
|
|
|
searchActor = \
|
2021-12-26 10:19:59 +00:00
|
|
|
local_actor_url(http_prefix, searchNickname, searchDomain)
|
2020-12-09 22:55:15 +00:00
|
|
|
infoForm += \
|
2020-12-10 10:21:54 +00:00
|
|
|
'<center><h1><a href="/users/' + nickname + '/moderation">' + \
|
2021-01-10 23:06:38 +00:00
|
|
|
translate['Account Information'] + ':</a> <a href="' + searchActor + \
|
|
|
|
'">' + searchHandle + '</a></h1><br>\n'
|
2020-12-09 22:55:15 +00:00
|
|
|
|
2021-01-10 23:06:38 +00:00
|
|
|
infoForm += translate[msgStr1] + '</center><br><br>\n'
|
2020-12-09 22:55:15 +00:00
|
|
|
|
2021-12-25 21:09:22 +00:00
|
|
|
proxy_type = 'tor'
|
2020-12-17 11:02:52 +00:00
|
|
|
if not os.path.isfile('/usr/bin/tor'):
|
2021-12-25 21:09:22 +00:00
|
|
|
proxy_type = None
|
2020-12-17 11:02:52 +00:00
|
|
|
if domain.endswith('.i2p'):
|
2021-12-25 21:09:22 +00:00
|
|
|
proxy_type = None
|
2021-01-10 23:06:38 +00:00
|
|
|
|
2021-12-28 16:56:57 +00:00
|
|
|
session = create_session(proxy_type)
|
2021-01-10 23:06:38 +00:00
|
|
|
|
2021-01-11 13:14:22 +00:00
|
|
|
wordFrequency = {}
|
2021-09-15 14:05:08 +00:00
|
|
|
originDomain = None
|
2021-01-10 23:06:38 +00:00
|
|
|
domainDict = getPublicPostInfo(session,
|
2021-12-25 16:17:53 +00:00
|
|
|
base_dir, searchNickname, searchDomain,
|
2021-09-15 14:05:08 +00:00
|
|
|
originDomain,
|
2021-12-25 21:09:22 +00:00
|
|
|
proxy_type, searchPort,
|
2021-12-25 17:09:22 +00:00
|
|
|
http_prefix, debug,
|
2021-12-25 23:03:28 +00:00
|
|
|
__version__, wordFrequency, system_language,
|
|
|
|
signing_priv_key_pem)
|
2021-01-10 23:06:38 +00:00
|
|
|
|
|
|
|
# get a list of any blocked followers
|
|
|
|
followersList = \
|
2021-12-25 23:03:28 +00:00
|
|
|
downloadFollowCollection(signing_priv_key_pem,
|
2021-08-31 14:17:11 +00:00
|
|
|
'followers', session,
|
2021-12-25 17:09:22 +00:00
|
|
|
http_prefix, searchActor, 1, 5, debug)
|
2021-01-10 23:06:38 +00:00
|
|
|
blockedFollowers = []
|
|
|
|
for followerActor in followersList:
|
2021-12-27 22:19:18 +00:00
|
|
|
followerNickname = get_nickname_from_actor(followerActor)
|
2021-12-27 19:05:25 +00:00
|
|
|
followerDomain, followerPort = get_domain_from_actor(followerActor)
|
2021-12-26 12:45:03 +00:00
|
|
|
followerDomainFull = get_full_domain(followerDomain, followerPort)
|
2021-12-25 16:17:53 +00:00
|
|
|
if isBlocked(base_dir, nickname, domain,
|
2021-01-10 23:06:38 +00:00
|
|
|
followerNickname, followerDomainFull):
|
|
|
|
blockedFollowers.append(followerActor)
|
|
|
|
|
2021-01-11 10:08:05 +00:00
|
|
|
# get a list of any blocked following
|
|
|
|
followingList = \
|
2021-12-25 23:03:28 +00:00
|
|
|
downloadFollowCollection(signing_priv_key_pem,
|
2021-08-31 16:21:37 +00:00
|
|
|
'following', session,
|
2021-12-25 17:09:22 +00:00
|
|
|
http_prefix, searchActor, 1, 5, debug)
|
2021-01-11 10:08:05 +00:00
|
|
|
blockedFollowing = []
|
|
|
|
for followingActor in followingList:
|
2021-12-27 22:19:18 +00:00
|
|
|
followingNickname = get_nickname_from_actor(followingActor)
|
2021-12-27 19:05:25 +00:00
|
|
|
followingDomain, followingPort = get_domain_from_actor(followingActor)
|
2021-12-26 12:45:03 +00:00
|
|
|
followingDomainFull = get_full_domain(followingDomain, followingPort)
|
2021-12-25 16:17:53 +00:00
|
|
|
if isBlocked(base_dir, nickname, domain,
|
2021-01-11 10:08:05 +00:00
|
|
|
followingNickname, followingDomainFull):
|
|
|
|
blockedFollowing.append(followingActor)
|
|
|
|
|
2021-01-10 23:06:38 +00:00
|
|
|
infoForm += '<div class="accountInfoDomains">\n'
|
2020-12-09 22:55:15 +00:00
|
|
|
usersPath = '/users/' + nickname + '/accountinfo'
|
2020-12-16 16:43:51 +00:00
|
|
|
ctr = 1
|
2020-12-16 17:09:08 +00:00
|
|
|
for postDomain, blockedPostUrls in domainDict.items():
|
2020-12-09 22:55:15 +00:00
|
|
|
infoForm += '<a href="' + \
|
2021-12-25 17:09:22 +00:00
|
|
|
http_prefix + '://' + postDomain + '" ' + \
|
2021-07-23 13:50:32 +00:00
|
|
|
'target="_blank" rel="nofollow noopener noreferrer">' + \
|
|
|
|
postDomain + '</a> '
|
2021-12-25 16:17:53 +00:00
|
|
|
if isBlockedDomain(base_dir, postDomain):
|
2020-12-16 16:43:51 +00:00
|
|
|
blockedPostsLinks = ''
|
2020-12-16 17:24:56 +00:00
|
|
|
urlCtr = 0
|
2020-12-16 17:09:08 +00:00
|
|
|
for url in blockedPostUrls:
|
2020-12-16 17:24:56 +00:00
|
|
|
if urlCtr > 0:
|
|
|
|
blockedPostsLinks += '<br>'
|
2020-12-16 16:43:51 +00:00
|
|
|
blockedPostsLinks += \
|
2021-07-23 13:50:32 +00:00
|
|
|
'<a href="' + url + '" ' + \
|
|
|
|
'target="_blank" rel="nofollow noopener noreferrer">' + \
|
|
|
|
url + '</a>'
|
2020-12-16 17:24:56 +00:00
|
|
|
urlCtr += 1
|
2020-12-16 16:46:36 +00:00
|
|
|
blockedPostsHtml = ''
|
|
|
|
if blockedPostsLinks:
|
2020-12-22 21:24:46 +00:00
|
|
|
blockNoStr = 'blockNumber' + str(ctr)
|
2020-12-16 16:46:36 +00:00
|
|
|
blockedPostsHtml = \
|
2020-12-22 21:24:46 +00:00
|
|
|
getContentWarningButton(blockNoStr,
|
2020-12-16 16:46:36 +00:00
|
|
|
translate, blockedPostsLinks)
|
|
|
|
ctr += 1
|
2020-12-16 16:43:51 +00:00
|
|
|
|
2020-12-09 22:55:15 +00:00
|
|
|
infoForm += \
|
2020-12-10 10:21:54 +00:00
|
|
|
'<a href="' + usersPath + '?unblockdomain=' + postDomain + \
|
|
|
|
'?handle=' + searchHandle + '">'
|
2020-12-09 22:55:15 +00:00
|
|
|
infoForm += '<button class="buttonhighlighted"><span>' + \
|
2020-12-16 16:43:51 +00:00
|
|
|
translate['Unblock'] + '</span></button></a> ' + \
|
2021-01-10 23:06:38 +00:00
|
|
|
blockedPostsHtml + '\n'
|
2020-12-09 22:55:15 +00:00
|
|
|
else:
|
|
|
|
infoForm += \
|
2020-12-10 10:21:54 +00:00
|
|
|
'<a href="' + usersPath + '?blockdomain=' + postDomain + \
|
|
|
|
'?handle=' + searchHandle + '">'
|
2020-12-16 16:51:57 +00:00
|
|
|
if postDomain != domain:
|
|
|
|
infoForm += '<button class="button"><span>' + \
|
|
|
|
translate['Block'] + '</span></button>'
|
2021-01-10 23:06:38 +00:00
|
|
|
infoForm += '</a>\n'
|
|
|
|
infoForm += '<br>\n'
|
|
|
|
|
|
|
|
infoForm += '</div>\n'
|
|
|
|
|
2021-01-11 10:08:05 +00:00
|
|
|
if blockedFollowing:
|
|
|
|
blockedFollowing.sort()
|
|
|
|
infoForm += '<div class="accountInfoDomains">\n'
|
|
|
|
infoForm += '<h1>' + translate['Blocked following'] + '</h1>\n'
|
|
|
|
infoForm += \
|
|
|
|
'<p>' + \
|
|
|
|
translate['Receives posts from the following accounts'] + \
|
2021-01-11 20:46:57 +00:00
|
|
|
':</p>\n'
|
2021-01-11 10:08:05 +00:00
|
|
|
for actor in blockedFollowing:
|
2021-12-27 22:19:18 +00:00
|
|
|
followingNickname = get_nickname_from_actor(actor)
|
2021-12-27 19:05:25 +00:00
|
|
|
followingDomain, followingPort = get_domain_from_actor(actor)
|
2021-01-11 10:08:05 +00:00
|
|
|
followingDomainFull = \
|
2021-12-26 12:45:03 +00:00
|
|
|
get_full_domain(followingDomain, followingPort)
|
2021-07-23 13:50:32 +00:00
|
|
|
infoForm += '<a href="' + actor + '" ' + \
|
|
|
|
'target="_blank" rel="nofollow noopener noreferrer">' + \
|
2021-01-11 10:08:05 +00:00
|
|
|
followingNickname + '@' + followingDomainFull + \
|
|
|
|
'</a><br><br>\n'
|
|
|
|
infoForm += '</div>\n'
|
|
|
|
|
2021-01-10 23:06:38 +00:00
|
|
|
if blockedFollowers:
|
|
|
|
blockedFollowers.sort()
|
2021-01-10 23:17:29 +00:00
|
|
|
infoForm += '<div class="accountInfoDomains">\n'
|
2021-01-10 23:19:06 +00:00
|
|
|
infoForm += '<h1>' + translate['Blocked followers'] + '</h1>\n'
|
2021-01-11 10:08:05 +00:00
|
|
|
infoForm += \
|
|
|
|
'<p>' + \
|
|
|
|
translate['Sends out posts to the following accounts'] + \
|
2021-01-11 20:46:57 +00:00
|
|
|
':</p>\n'
|
2021-01-10 23:06:38 +00:00
|
|
|
for actor in blockedFollowers:
|
2021-12-27 22:19:18 +00:00
|
|
|
followerNickname = get_nickname_from_actor(actor)
|
2021-12-27 19:05:25 +00:00
|
|
|
followerDomain, followerPort = get_domain_from_actor(actor)
|
2021-12-26 12:45:03 +00:00
|
|
|
followerDomainFull = get_full_domain(followerDomain, followerPort)
|
2021-07-23 13:50:32 +00:00
|
|
|
infoForm += '<a href="' + actor + '" ' + \
|
|
|
|
'target="_blank" rel="nofollow noopener noreferrer">' + \
|
2021-01-10 23:16:10 +00:00
|
|
|
followerNickname + '@' + followerDomainFull + '</a><br><br>\n'
|
2021-01-10 23:06:38 +00:00
|
|
|
infoForm += '</div>\n'
|
2020-12-09 22:55:15 +00:00
|
|
|
|
2021-01-11 13:42:47 +00:00
|
|
|
if wordFrequency:
|
|
|
|
maxCount = 1
|
|
|
|
for word, count in wordFrequency.items():
|
|
|
|
if count > maxCount:
|
|
|
|
maxCount = count
|
|
|
|
minimumWordCount = int(maxCount / 2)
|
|
|
|
if minimumWordCount >= 3:
|
|
|
|
infoForm += '<div class="accountInfoDomains">\n'
|
|
|
|
infoForm += '<h1>' + translate['Word frequencies'] + '</h1>\n'
|
|
|
|
wordSwarm = ''
|
|
|
|
ctr = 0
|
|
|
|
for word, count in wordFrequency.items():
|
|
|
|
if count >= minimumWordCount:
|
|
|
|
if ctr > 0:
|
|
|
|
wordSwarm += ' '
|
|
|
|
if count < maxCount - int(maxCount / 4):
|
|
|
|
wordSwarm += word
|
|
|
|
else:
|
|
|
|
if count != maxCount:
|
|
|
|
wordSwarm += '<b>' + word + '</b>'
|
|
|
|
else:
|
|
|
|
wordSwarm += '<b><i>' + word + '</i></b>'
|
|
|
|
ctr += 1
|
|
|
|
infoForm += wordSwarm
|
|
|
|
infoForm += '</div>\n'
|
|
|
|
|
2020-12-09 22:55:15 +00:00
|
|
|
infoForm += htmlFooter()
|
|
|
|
return infoForm
|
|
|
|
|
|
|
|
|
2021-12-28 13:56:43 +00:00
|
|
|
def htmlModerationInfo(css_cache: {}, translate: {},
|
2021-12-25 17:09:22 +00:00
|
|
|
base_dir: str, http_prefix: str,
|
2020-12-09 19:17:42 +00:00
|
|
|
nickname: str) -> str:
|
2020-11-10 10:25:21 +00:00
|
|
|
msgStr1 = \
|
|
|
|
'These are globally blocked for all accounts on this instance'
|
|
|
|
msgStr2 = \
|
|
|
|
'Any blocks or suspensions made by moderators will be shown here.'
|
2020-12-09 22:55:15 +00:00
|
|
|
|
2020-11-10 10:25:21 +00:00
|
|
|
infoForm = ''
|
2021-12-25 16:17:53 +00:00
|
|
|
cssFilename = base_dir + '/epicyon-profile.css'
|
|
|
|
if os.path.isfile(base_dir + '/epicyon.css'):
|
|
|
|
cssFilename = base_dir + '/epicyon.css'
|
2020-11-10 10:25:21 +00:00
|
|
|
|
2021-01-11 19:46:21 +00:00
|
|
|
instanceTitle = \
|
2021-12-26 14:08:58 +00:00
|
|
|
get_config_param(base_dir, 'instanceTitle')
|
2021-11-07 10:38:11 +00:00
|
|
|
infoForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle, None)
|
2020-11-10 10:25:21 +00:00
|
|
|
|
2020-11-12 17:05:38 +00:00
|
|
|
infoForm += \
|
2020-12-09 19:17:42 +00:00
|
|
|
'<center><h1><a href="/users/' + nickname + '/moderation">' + \
|
2020-11-12 17:05:38 +00:00
|
|
|
translate['Moderation Information'] + \
|
2020-12-09 22:55:15 +00:00
|
|
|
'</a></h1></center><br>'
|
2020-11-10 10:25:21 +00:00
|
|
|
|
2020-11-12 17:05:38 +00:00
|
|
|
infoShown = False
|
2020-12-20 11:00:17 +00:00
|
|
|
|
2020-12-20 11:31:29 +00:00
|
|
|
accounts = []
|
2021-12-25 16:17:53 +00:00
|
|
|
for subdir, dirs, files in os.walk(base_dir + '/accounts'):
|
2020-12-20 11:00:17 +00:00
|
|
|
for acct in dirs:
|
2021-12-26 18:46:43 +00:00
|
|
|
if not is_account_dir(acct):
|
2020-12-20 11:00:17 +00:00
|
|
|
continue
|
2020-12-20 11:31:29 +00:00
|
|
|
accounts.append(acct)
|
2020-12-20 11:00:17 +00:00
|
|
|
break
|
2020-12-20 11:31:29 +00:00
|
|
|
accounts.sort()
|
|
|
|
|
2020-12-20 11:51:23 +00:00
|
|
|
cols = 5
|
|
|
|
if len(accounts) > 10:
|
|
|
|
infoForm += '<details><summary><b>' + translate['Show Accounts']
|
|
|
|
infoForm += '</b></summary>\n'
|
|
|
|
infoForm += '<div class="container">\n'
|
|
|
|
infoForm += '<table class="accountsTable">\n'
|
|
|
|
infoForm += ' <colgroup>\n'
|
|
|
|
for col in range(cols):
|
|
|
|
infoForm += ' <col span="1" class="accountsTableCol">\n'
|
|
|
|
infoForm += ' </colgroup>\n'
|
|
|
|
infoForm += '<tr>\n'
|
|
|
|
|
2020-12-20 11:31:29 +00:00
|
|
|
col = 0
|
|
|
|
for acct in accounts:
|
|
|
|
acctNickname = acct.split('@')[0]
|
2021-12-25 16:17:53 +00:00
|
|
|
accountDir = os.path.join(base_dir + '/accounts', acct)
|
2021-12-26 15:13:34 +00:00
|
|
|
actor_json = load_json(accountDir + '.json')
|
2021-12-26 10:29:52 +00:00
|
|
|
if not actor_json:
|
2020-12-20 11:31:29 +00:00
|
|
|
continue
|
2021-12-26 10:29:52 +00:00
|
|
|
actor = actor_json['id']
|
2020-12-20 11:31:29 +00:00
|
|
|
avatarUrl = ''
|
2020-12-20 13:28:33 +00:00
|
|
|
ext = ''
|
2021-12-26 10:29:52 +00:00
|
|
|
if actor_json.get('icon'):
|
|
|
|
if actor_json['icon'].get('url'):
|
|
|
|
avatarUrl = actor_json['icon']['url']
|
2020-12-20 13:28:33 +00:00
|
|
|
if '.' in avatarUrl:
|
2020-12-20 13:30:55 +00:00
|
|
|
ext = '.' + avatarUrl.split('.')[-1]
|
2020-12-20 11:31:29 +00:00
|
|
|
acctUrl = \
|
|
|
|
'/users/' + nickname + '?options=' + actor + ';1;' + \
|
2020-12-20 13:28:33 +00:00
|
|
|
'/members/' + acctNickname + ext
|
2020-12-20 11:31:29 +00:00
|
|
|
infoForm += '<td>\n<a href="' + acctUrl + '">'
|
|
|
|
infoForm += '<img loading="lazy" style="width:90%" '
|
|
|
|
infoForm += 'src="' + avatarUrl + '" />'
|
2020-12-20 12:09:29 +00:00
|
|
|
infoForm += '<br><center>'
|
2021-12-28 19:33:29 +00:00
|
|
|
if is_moderator(base_dir, acctNickname):
|
2020-12-20 12:38:47 +00:00
|
|
|
infoForm += '<b><u>' + acctNickname + '</u></b>'
|
|
|
|
else:
|
|
|
|
infoForm += acctNickname
|
2021-12-26 13:27:57 +00:00
|
|
|
if is_editor(base_dir, acctNickname):
|
2020-12-20 12:35:56 +00:00
|
|
|
infoForm += ' ✍'
|
2020-12-20 11:31:29 +00:00
|
|
|
infoForm += '</center></a>\n</td>\n'
|
|
|
|
col += 1
|
|
|
|
if col == cols:
|
|
|
|
# new row of accounts
|
|
|
|
infoForm += '</tr>\n<tr>\n'
|
2020-12-20 11:00:17 +00:00
|
|
|
infoForm += '</tr>\n</table>\n'
|
|
|
|
infoForm += '</div>\n'
|
2020-12-20 11:51:23 +00:00
|
|
|
if len(accounts) > 10:
|
|
|
|
infoForm += '</details>\n'
|
2020-12-20 11:00:17 +00:00
|
|
|
|
2021-12-25 16:17:53 +00:00
|
|
|
suspendedFilename = base_dir + '/accounts/suspended.txt'
|
2020-11-12 17:05:38 +00:00
|
|
|
if os.path.isfile(suspendedFilename):
|
2021-07-13 14:40:49 +00:00
|
|
|
with open(suspendedFilename, 'r') as f:
|
2020-11-12 17:05:38 +00:00
|
|
|
suspendedStr = f.read()
|
2020-12-20 11:00:17 +00:00
|
|
|
infoForm += '<div class="container">\n'
|
2020-11-12 17:05:38 +00:00
|
|
|
infoForm += ' <br><b>' + \
|
|
|
|
translate['Suspended accounts'] + '</b>'
|
|
|
|
infoForm += ' <br>' + \
|
|
|
|
translate['These are currently suspended']
|
|
|
|
infoForm += \
|
|
|
|
' <textarea id="message" ' + \
|
2021-02-28 14:26:04 +00:00
|
|
|
'name="suspended" style="height:200px" spellcheck="false">' + \
|
2020-12-20 11:00:17 +00:00
|
|
|
suspendedStr + '</textarea>\n'
|
|
|
|
infoForm += '</div>\n'
|
2020-11-12 17:05:38 +00:00
|
|
|
infoShown = True
|
2020-11-10 10:25:21 +00:00
|
|
|
|
2021-12-25 16:17:53 +00:00
|
|
|
blockingFilename = base_dir + '/accounts/blocking.txt'
|
2020-11-12 17:05:38 +00:00
|
|
|
if os.path.isfile(blockingFilename):
|
2021-07-13 14:40:49 +00:00
|
|
|
with open(blockingFilename, 'r') as f:
|
2020-11-12 17:05:38 +00:00
|
|
|
blockedStr = f.read()
|
2020-12-20 11:00:17 +00:00
|
|
|
infoForm += '<div class="container">\n'
|
2020-11-12 17:05:38 +00:00
|
|
|
infoForm += \
|
|
|
|
' <br><b>' + \
|
|
|
|
translate['Blocked accounts and hashtags'] + '</b>'
|
2020-11-10 10:25:21 +00:00
|
|
|
infoForm += \
|
2020-11-12 17:05:38 +00:00
|
|
|
' <br>' + \
|
|
|
|
translate[msgStr1]
|
|
|
|
infoForm += \
|
|
|
|
' <textarea id="message" ' + \
|
2021-02-28 14:26:04 +00:00
|
|
|
'name="blocked" style="height:700px" spellcheck="false">' + \
|
2020-12-20 11:00:17 +00:00
|
|
|
blockedStr + '</textarea>\n'
|
|
|
|
infoForm += '</div>\n'
|
2020-11-12 17:05:38 +00:00
|
|
|
infoShown = True
|
2020-12-19 11:33:38 +00:00
|
|
|
|
2021-12-25 16:17:53 +00:00
|
|
|
filtersFilename = base_dir + '/accounts/filters.txt'
|
2020-12-19 11:33:38 +00:00
|
|
|
if os.path.isfile(filtersFilename):
|
2021-07-13 14:40:49 +00:00
|
|
|
with open(filtersFilename, 'r') as f:
|
2020-12-19 11:33:38 +00:00
|
|
|
filteredStr = f.read()
|
2020-12-20 11:00:17 +00:00
|
|
|
infoForm += '<div class="container">\n'
|
2020-12-19 11:33:38 +00:00
|
|
|
infoForm += \
|
|
|
|
' <br><b>' + \
|
|
|
|
translate['Filtered words'] + '</b>'
|
|
|
|
infoForm += \
|
|
|
|
' <textarea id="message" ' + \
|
2021-02-28 14:26:04 +00:00
|
|
|
'name="filtered" style="height:700px" spellcheck="true">' + \
|
2020-12-20 11:00:17 +00:00
|
|
|
filteredStr + '</textarea>\n'
|
|
|
|
infoForm += '</div>\n'
|
2020-12-19 11:33:38 +00:00
|
|
|
infoShown = True
|
|
|
|
|
2020-11-12 17:05:38 +00:00
|
|
|
if not infoShown:
|
|
|
|
infoForm += \
|
|
|
|
'<center><p>' + \
|
|
|
|
translate[msgStr2] + \
|
2020-12-20 11:00:17 +00:00
|
|
|
'</p></center>\n'
|
2020-11-12 17:05:38 +00:00
|
|
|
infoForm += htmlFooter()
|
2020-11-10 10:25:21 +00:00
|
|
|
return infoForm
|