| 
									
										
										
										
											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-04 17:18:32 +00:00
										 |  |  | from utils import isArtist | 
					
						
							| 
									
										
										
										
											2021-06-25 18:02:05 +00:00
										 |  |  | from utils import isAccountDir | 
					
						
							| 
									
										
										
										
											2021-01-10 23:06:38 +00:00
										 |  |  | from utils import getFullDomain | 
					
						
							| 
									
										
										
										
											2020-12-20 12:34:16 +00:00
										 |  |  | from utils import isEditor | 
					
						
							| 
									
										
										
										
											2020-12-20 11:00:17 +00:00
										 |  |  | from utils import loadJson | 
					
						
							| 
									
										
										
										
											2020-12-09 22:55:15 +00:00
										 |  |  | from utils import getNicknameFromActor | 
					
						
							|  |  |  | from utils import getDomainFromActor | 
					
						
							| 
									
										
										
										
											2021-01-11 19:46:21 +00:00
										 |  |  | from utils import getConfigParam | 
					
						
							| 
									
										
										
										
											2021-08-14 11:13:39 +00:00
										 |  |  | from utils import localActorUrl | 
					
						
							| 
									
										
										
										
											2021-01-11 10:08:05 +00:00
										 |  |  | from posts import downloadFollowCollection | 
					
						
							| 
									
										
										
										
											2020-12-16 16:43:51 +00:00
										 |  |  | from posts import getPublicPostInfo | 
					
						
							| 
									
										
										
										
											2020-12-20 12:09:29 +00:00
										 |  |  | from posts import isModerator | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | from session import createSession | 
					
						
							| 
									
										
										
										
											2020-11-10 10:25:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def htmlModeration(cssCache: {}, defaultTimeline: str, | 
					
						
							|  |  |  |                    recentPostsCache: {}, maxRecentPosts: int, | 
					
						
							|  |  |  |                    translate: {}, pageNumber: int, itemsPerPage: int, | 
					
						
							|  |  |  |                    session, baseDir: str, wfRequest: {}, personCache: {}, | 
					
						
							|  |  |  |                    nickname: str, domain: str, port: int, inboxJson: {}, | 
					
						
							|  |  |  |                    allowDeletion: bool, | 
					
						
							|  |  |  |                    httpPrefix: str, projectVersion: str, | 
					
						
							|  |  |  |                    YTReplacementDomain: str, | 
					
						
							| 
									
										
										
										
											2021-09-18 17:08:14 +00:00
										 |  |  |                    twitterReplacementDomain: str, | 
					
						
							| 
									
										
										
										
											2020-11-10 10:25:21 +00:00
										 |  |  |                    showPublishedDateOnly: bool, | 
					
						
							|  |  |  |                    newswire: {}, positiveVoting: bool, | 
					
						
							|  |  |  |                    showPublishAsIcon: bool, | 
					
						
							|  |  |  |                    fullWidthTimelineButtonHeader: bool, | 
					
						
							|  |  |  |                    iconsAsButtons: bool, | 
					
						
							|  |  |  |                    rssIconAtTop: bool, | 
					
						
							|  |  |  |                    publishButtonAtTop: bool, | 
					
						
							| 
									
										
										
										
											2020-12-21 23:09:00 +00:00
										 |  |  |                    authorized: bool, moderationActionStr: str, | 
					
						
							| 
									
										
										
										
											2021-01-30 11:47:09 +00:00
										 |  |  |                    theme: str, peertubeInstances: [], | 
					
						
							| 
									
										
										
										
											2021-02-05 19:14:27 +00:00
										 |  |  |                    allowLocalNetworkAccess: bool, | 
					
						
							| 
									
										
										
										
											2021-04-22 12:45:31 +00:00
										 |  |  |                    textModeBanner: str, | 
					
						
							| 
									
										
										
										
											2021-07-27 14:06:14 +00:00
										 |  |  |                    accessKeys: {}, systemLanguage: str, | 
					
						
							| 
									
										
										
										
											2021-08-03 10:04:45 +00:00
										 |  |  |                    maxLikeCount: int, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                    sharedItemsFederatedDomains: [], | 
					
						
							| 
									
										
										
										
											2021-10-21 13:08:21 +00:00
										 |  |  |                    signingPrivateKeyPem: str, | 
					
						
							| 
									
										
										
										
											2021-10-21 19:00:25 +00:00
										 |  |  |                    CWlists: {}, listsEnabled: 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-04 17:18:32 +00:00
										 |  |  |     artist = isArtist(baseDir, nickname) | 
					
						
							| 
									
										
										
										
											2020-11-10 10:25:21 +00:00
										 |  |  |     return htmlTimeline(cssCache, defaultTimeline, | 
					
						
							|  |  |  |                         recentPostsCache, maxRecentPosts, | 
					
						
							|  |  |  |                         translate, pageNumber, | 
					
						
							|  |  |  |                         itemsPerPage, session, baseDir, wfRequest, personCache, | 
					
						
							|  |  |  |                         nickname, domain, port, inboxJson, 'moderation', | 
					
						
							|  |  |  |                         allowDeletion, httpPrefix, projectVersion, True, False, | 
					
						
							| 
									
										
										
										
											2021-09-18 17:08:14 +00:00
										 |  |  |                         YTReplacementDomain, | 
					
						
							|  |  |  |                         twitterReplacementDomain, | 
					
						
							|  |  |  |                         showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2021-12-04 17:18:32 +00:00
										 |  |  |                         newswire, False, False, artist, positiveVoting, | 
					
						
							| 
									
										
										
										
											2020-11-10 10:25:21 +00:00
										 |  |  |                         showPublishAsIcon, fullWidthTimelineButtonHeader, | 
					
						
							|  |  |  |                         iconsAsButtons, rssIconAtTop, publishButtonAtTop, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                         authorized, moderationActionStr, theme, | 
					
						
							| 
									
										
										
										
											2021-02-05 19:14:27 +00:00
										 |  |  |                         peertubeInstances, allowLocalNetworkAccess, | 
					
						
							| 
									
										
										
										
											2021-07-27 14:06:14 +00:00
										 |  |  |                         textModeBanner, accessKeys, systemLanguage, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                         maxLikeCount, sharedItemsFederatedDomains, | 
					
						
							| 
									
										
										
										
											2021-10-21 19:00:25 +00:00
										 |  |  |                         signingPrivateKeyPem, CWlists, listsEnabled) | 
					
						
							| 
									
										
										
										
											2020-11-10 10:25:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-09 22:55:15 +00:00
										 |  |  | def htmlAccountInfo(cssCache: {}, translate: {}, | 
					
						
							|  |  |  |                     baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                     nickname: str, domain: str, port: int, | 
					
						
							| 
									
										
										
										
											2021-07-18 14:15:16 +00:00
										 |  |  |                     searchHandle: str, debug: bool, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                     systemLanguage: str, signingPrivateKeyPem: 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-09-15 14:05:08 +00:00
										 |  |  |     signingPrivateKeyPem = None | 
					
						
							| 
									
										
										
										
											2020-12-09 22:55:15 +00:00
										 |  |  |     msgStr1 = 'This account interacts with the following instances' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     infoForm = '' | 
					
						
							|  |  |  |     cssFilename = baseDir + '/epicyon-profile.css' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/epicyon.css'): | 
					
						
							|  |  |  |         cssFilename = baseDir + '/epicyon.css' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 19:46:21 +00:00
										 |  |  |     instanceTitle = \ | 
					
						
							|  |  |  |         getConfigParam(baseDir, 'instanceTitle') | 
					
						
							| 
									
										
										
										
											2021-11-07 10:38:11 +00:00
										 |  |  |     infoForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle, None) | 
					
						
							| 
									
										
										
										
											2020-12-09 22:55:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     searchNickname = getNicknameFromActor(searchHandle) | 
					
						
							|  |  |  |     searchDomain, searchPort = getDomainFromActor(searchHandle) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 10:21:54 +00:00
										 |  |  |     searchHandle = searchNickname + '@' + searchDomain | 
					
						
							| 
									
										
										
										
											2021-01-10 23:06:38 +00:00
										 |  |  |     searchActor = \ | 
					
						
							| 
									
										
										
										
											2021-08-14 11:13:39 +00:00
										 |  |  |         localActorUrl(httpPrefix, 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
										 |  |  | 
 | 
					
						
							|  |  |  |     proxyType = 'tor' | 
					
						
							| 
									
										
										
										
											2020-12-17 11:02:52 +00:00
										 |  |  |     if not os.path.isfile('/usr/bin/tor'): | 
					
						
							|  |  |  |         proxyType = None | 
					
						
							|  |  |  |     if domain.endswith('.i2p'): | 
					
						
							|  |  |  |         proxyType = None | 
					
						
							| 
									
										
										
										
											2021-01-10 23:06:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     session = createSession(proxyType) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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, | 
					
						
							| 
									
										
										
										
											2020-12-16 16:43:51 +00:00
										 |  |  |                                    baseDir, searchNickname, searchDomain, | 
					
						
							| 
									
										
										
										
											2021-09-15 14:05:08 +00:00
										 |  |  |                                    originDomain, | 
					
						
							| 
									
										
										
										
											2020-12-16 16:43:51 +00:00
										 |  |  |                                    proxyType, searchPort, | 
					
						
							|  |  |  |                                    httpPrefix, debug, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                                    __version__, wordFrequency, systemLanguage, | 
					
						
							|  |  |  |                                    signingPrivateKeyPem) | 
					
						
							| 
									
										
										
										
											2021-01-10 23:06:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # get a list of any blocked followers | 
					
						
							|  |  |  |     followersList = \ | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |         downloadFollowCollection(signingPrivateKeyPem, | 
					
						
							|  |  |  |                                  'followers', session, | 
					
						
							| 
									
										
										
										
											2021-10-29 22:40:09 +00:00
										 |  |  |                                  httpPrefix, searchActor, 1, 5, debug) | 
					
						
							| 
									
										
										
										
											2021-01-10 23:06:38 +00:00
										 |  |  |     blockedFollowers = [] | 
					
						
							|  |  |  |     for followerActor in followersList: | 
					
						
							|  |  |  |         followerNickname = getNicknameFromActor(followerActor) | 
					
						
							|  |  |  |         followerDomain, followerPort = getDomainFromActor(followerActor) | 
					
						
							|  |  |  |         followerDomainFull = getFullDomain(followerDomain, followerPort) | 
					
						
							|  |  |  |         if isBlocked(baseDir, nickname, domain, | 
					
						
							|  |  |  |                      followerNickname, followerDomainFull): | 
					
						
							|  |  |  |             blockedFollowers.append(followerActor) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 10:08:05 +00:00
										 |  |  |     # get a list of any blocked following | 
					
						
							|  |  |  |     followingList = \ | 
					
						
							| 
									
										
										
										
											2021-08-31 16:21:37 +00:00
										 |  |  |         downloadFollowCollection(signingPrivateKeyPem, | 
					
						
							|  |  |  |                                  'following', session, | 
					
						
							| 
									
										
										
										
											2021-10-29 22:40:09 +00:00
										 |  |  |                                  httpPrefix, searchActor, 1, 5, debug) | 
					
						
							| 
									
										
										
										
											2021-01-11 10:08:05 +00:00
										 |  |  |     blockedFollowing = [] | 
					
						
							|  |  |  |     for followingActor in followingList: | 
					
						
							|  |  |  |         followingNickname = getNicknameFromActor(followingActor) | 
					
						
							|  |  |  |         followingDomain, followingPort = getDomainFromActor(followingActor) | 
					
						
							|  |  |  |         followingDomainFull = getFullDomain(followingDomain, followingPort) | 
					
						
							|  |  |  |         if isBlocked(baseDir, nickname, domain, | 
					
						
							|  |  |  |                      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-07-23 13:50:32 +00:00
										 |  |  |             httpPrefix + '://' + postDomain + '" ' + \ | 
					
						
							|  |  |  |             'target="_blank" rel="nofollow noopener noreferrer">' + \ | 
					
						
							|  |  |  |             postDomain + '</a> ' | 
					
						
							| 
									
										
										
										
											2020-12-09 23:08:00 +00:00
										 |  |  |         if isBlockedDomain(baseDir, 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: | 
					
						
							|  |  |  |             followingNickname = getNicknameFromActor(actor) | 
					
						
							|  |  |  |             followingDomain, followingPort = getDomainFromActor(actor) | 
					
						
							|  |  |  |             followingDomainFull = \ | 
					
						
							|  |  |  |                 getFullDomain(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-01-10 23:16:10 +00:00
										 |  |  |             followerNickname = getNicknameFromActor(actor) | 
					
						
							|  |  |  |             followerDomain, followerPort = getDomainFromActor(actor) | 
					
						
							|  |  |  |             followerDomainFull = getFullDomain(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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 10:25:21 +00:00
										 |  |  | def htmlModerationInfo(cssCache: {}, translate: {}, | 
					
						
							| 
									
										
										
										
											2020-12-09 19:17:42 +00:00
										 |  |  |                        baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                        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 = '' | 
					
						
							|  |  |  |     cssFilename = baseDir + '/epicyon-profile.css' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/epicyon.css'): | 
					
						
							|  |  |  |         cssFilename = baseDir + '/epicyon.css' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 19:46:21 +00:00
										 |  |  |     instanceTitle = \ | 
					
						
							|  |  |  |         getConfigParam(baseDir, '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 = [] | 
					
						
							| 
									
										
										
										
											2020-12-20 11:00:17 +00:00
										 |  |  |     for subdir, dirs, files in os.walk(baseDir + '/accounts'): | 
					
						
							|  |  |  |         for acct in dirs: | 
					
						
							| 
									
										
										
										
											2021-06-25 18:02:05 +00:00
										 |  |  |             if not isAccountDir(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] | 
					
						
							|  |  |  |         accountDir = os.path.join(baseDir + '/accounts', acct) | 
					
						
							|  |  |  |         actorJson = loadJson(accountDir + '.json') | 
					
						
							|  |  |  |         if not actorJson: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         actor = actorJson['id'] | 
					
						
							|  |  |  |         avatarUrl = '' | 
					
						
							| 
									
										
										
										
											2020-12-20 13:28:33 +00:00
										 |  |  |         ext = '' | 
					
						
							| 
									
										
										
										
											2020-12-20 11:31:29 +00:00
										 |  |  |         if actorJson.get('icon'): | 
					
						
							|  |  |  |             if actorJson['icon'].get('url'): | 
					
						
							|  |  |  |                 avatarUrl = actorJson['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>' | 
					
						
							| 
									
										
										
										
											2020-12-20 12:43:22 +00:00
										 |  |  |         if isModerator(baseDir, acctNickname): | 
					
						
							| 
									
										
										
										
											2020-12-20 12:38:47 +00:00
										 |  |  |             infoForm += '<b><u>' + acctNickname + '</u></b>' | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             infoForm += acctNickname | 
					
						
							| 
									
										
										
										
											2020-12-20 12:34:16 +00:00
										 |  |  |         if isEditor(baseDir, 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     suspendedFilename = baseDir + '/accounts/suspended.txt' | 
					
						
							|  |  |  |     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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     blockingFilename = baseDir + '/accounts/blocking.txt' | 
					
						
							|  |  |  |     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
										 |  |  | 
 | 
					
						
							|  |  |  |     filtersFilename = baseDir + '/accounts/filters.txt' | 
					
						
							|  |  |  |     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 |