| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | __filename__ = "webapp_profile.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2021-01-26 10:07:42 +00:00
										 |  |  | __version__ = "1.2.0" | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@freedombone.net" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | from pprint import pprint | 
					
						
							| 
									
										
										
										
											2021-05-16 15:10:39 +00:00
										 |  |  | from utils import getOccupationName | 
					
						
							| 
									
										
										
										
											2021-01-02 11:18:43 +00:00
										 |  |  | from utils import getLockedAccount | 
					
						
							| 
									
										
										
										
											2020-12-23 10:57:44 +00:00
										 |  |  | from utils import hasUsersPath | 
					
						
							| 
									
										
										
										
											2020-12-16 11:19:16 +00:00
										 |  |  | from utils import getFullDomain | 
					
						
							| 
									
										
										
										
											2021-05-17 17:52:33 +00:00
										 |  |  | from utils import isArtist | 
					
						
							| 
									
										
										
										
											2020-12-13 12:44:17 +00:00
										 |  |  | from utils import isDormant | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | from utils import getNicknameFromActor | 
					
						
							|  |  |  | from utils import getDomainFromActor | 
					
						
							|  |  |  | from utils import isSystemAccount | 
					
						
							|  |  |  | from utils import removeHtml | 
					
						
							|  |  |  | from utils import loadJson | 
					
						
							|  |  |  | from utils import getConfigParam | 
					
						
							| 
									
										
										
										
											2020-11-21 11:21:05 +00:00
										 |  |  | from utils import getImageFormats | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | from skills import getSkills | 
					
						
							|  |  |  | from theme import getThemesList | 
					
						
							|  |  |  | from person import personBoxJson | 
					
						
							|  |  |  | from webfinger import webfingerHandle | 
					
						
							|  |  |  | from session import getJson | 
					
						
							|  |  |  | from posts import parseUserFeed | 
					
						
							|  |  |  | from posts import getUserUrl | 
					
						
							|  |  |  | from posts import getPersonBox | 
					
						
							|  |  |  | from donate import getDonationUrl | 
					
						
							|  |  |  | from xmpp import getXmppAddress | 
					
						
							|  |  |  | from matrix import getMatrixAddress | 
					
						
							|  |  |  | from ssb import getSSBAddress | 
					
						
							|  |  |  | from pgp import getEmailAddress | 
					
						
							|  |  |  | from pgp import getPGPfingerprint | 
					
						
							|  |  |  | from pgp import getPGPpubKey | 
					
						
							|  |  |  | from tox import getToxAddress | 
					
						
							| 
									
										
										
										
											2020-12-24 16:49:57 +00:00
										 |  |  | from briar import getBriarAddress | 
					
						
							| 
									
										
										
										
											2020-11-29 12:50:41 +00:00
										 |  |  | from jami import getJamiAddress | 
					
						
							| 
									
										
										
										
											2020-12-19 10:32:48 +00:00
										 |  |  | from filters import isFiltered | 
					
						
							| 
									
										
										
										
											2021-01-02 12:00:07 +00:00
										 |  |  | from follow import isFollowerOfPerson | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  | from webapp_frontscreen import htmlFrontScreen | 
					
						
							| 
									
										
										
										
											2021-02-05 17:05:53 +00:00
										 |  |  | from webapp_utils import htmlKeyboardNavigation | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  | from webapp_utils import htmlHideFromScreenReader | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | from webapp_utils import scheduledPostsExist | 
					
						
							|  |  |  | from webapp_utils import getPersonAvatarUrl | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  | from webapp_utils import htmlHeaderWithExternalStyle | 
					
						
							| 
									
										
										
										
											2021-05-12 15:49:53 +00:00
										 |  |  | from webapp_utils import htmlHeaderWithPersonMarkup | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | from webapp_utils import htmlFooter | 
					
						
							|  |  |  | from webapp_utils import addEmojiToDisplayName | 
					
						
							|  |  |  | from webapp_utils import getBannerFile | 
					
						
							|  |  |  | from webapp_utils import htmlPostSeparator | 
					
						
							|  |  |  | from webapp_utils import getBlogAddress | 
					
						
							|  |  |  | from webapp_post import individualPostAsHtml | 
					
						
							|  |  |  | from webapp_timeline import htmlIndividualShare | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def htmlProfileAfterSearch(cssCache: {}, | 
					
						
							|  |  |  |                            recentPostsCache: {}, maxRecentPosts: int, | 
					
						
							|  |  |  |                            translate: {}, | 
					
						
							|  |  |  |                            baseDir: str, path: str, httpPrefix: str, | 
					
						
							|  |  |  |                            nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                            profileHandle: str, | 
					
						
							|  |  |  |                            session, cachedWebfingers: {}, personCache: {}, | 
					
						
							|  |  |  |                            debug: bool, projectVersion: str, | 
					
						
							|  |  |  |                            YTReplacementDomain: str, | 
					
						
							| 
									
										
										
										
											2020-11-12 23:50:25 +00:00
										 |  |  |                            showPublishedDateOnly: bool, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                            defaultTimeline: str, | 
					
						
							| 
									
										
										
										
											2021-01-30 11:47:09 +00:00
										 |  |  |                            peertubeInstances: [], | 
					
						
							| 
									
										
										
										
											2021-03-09 19:52:10 +00:00
										 |  |  |                            allowLocalNetworkAccess: bool, | 
					
						
							| 
									
										
										
										
											2021-04-23 12:04:42 +00:00
										 |  |  |                            themeName: str, | 
					
						
							|  |  |  |                            accessKeys: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Show a profile page after a search for a fediverse address
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-12-23 10:57:44 +00:00
										 |  |  |     if hasUsersPath(profileHandle) or '/@' in profileHandle: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         searchNickname = getNicknameFromActor(profileHandle) | 
					
						
							|  |  |  |         searchDomain, searchPort = getDomainFromActor(profileHandle) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         if '@' not in profileHandle: | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |             if debug: | 
					
						
							|  |  |  |                 print('DEBUG: no @ in ' + profileHandle) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             return None | 
					
						
							|  |  |  |         if profileHandle.startswith('@'): | 
					
						
							|  |  |  |             profileHandle = profileHandle[1:] | 
					
						
							|  |  |  |         if '@' not in profileHandle: | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |             if debug: | 
					
						
							|  |  |  |                 print('DEBUG: no @ in ' + profileHandle) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             return None | 
					
						
							|  |  |  |         searchNickname = profileHandle.split('@')[0] | 
					
						
							|  |  |  |         searchDomain = profileHandle.split('@')[1] | 
					
						
							|  |  |  |         searchPort = None | 
					
						
							|  |  |  |         if ':' in searchDomain: | 
					
						
							|  |  |  |             searchPortStr = searchDomain.split(':')[1] | 
					
						
							|  |  |  |             if searchPortStr.isdigit(): | 
					
						
							|  |  |  |                 searchPort = int(searchPortStr) | 
					
						
							|  |  |  |             searchDomain = searchDomain.split(':')[0] | 
					
						
							|  |  |  |     if searchPort: | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: Search for handle ' + | 
					
						
							|  |  |  |                   str(searchNickname) + '@' + str(searchDomain) + ':' + | 
					
						
							|  |  |  |                   str(searchPort)) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: Search for handle ' + | 
					
						
							|  |  |  |                   str(searchNickname) + '@' + str(searchDomain)) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     if not searchNickname: | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: No nickname found in ' + profileHandle) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         return None | 
					
						
							|  |  |  |     if not searchDomain: | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: No domain found in ' + profileHandle) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 11:19:16 +00:00
										 |  |  |     searchDomainFull = getFullDomain(searchDomain, searchPort) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     profileStr = '' | 
					
						
							|  |  |  |     cssFilename = baseDir + '/epicyon-profile.css' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/epicyon.css'): | 
					
						
							|  |  |  |         cssFilename = baseDir + '/epicyon.css' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     wf = \ | 
					
						
							|  |  |  |         webfingerHandle(session, | 
					
						
							|  |  |  |                         searchNickname + '@' + searchDomainFull, | 
					
						
							|  |  |  |                         httpPrefix, cachedWebfingers, | 
					
						
							| 
									
										
										
										
											2021-03-14 19:22:58 +00:00
										 |  |  |                         domain, projectVersion, debug) | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     if not wf: | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: Unable to webfinger ' + | 
					
						
							|  |  |  |                   searchNickname + '@' + searchDomainFull) | 
					
						
							|  |  |  |             print('DEBUG: cachedWebfingers ' + str(cachedWebfingers)) | 
					
						
							|  |  |  |             print('DEBUG: httpPrefix ' + httpPrefix) | 
					
						
							|  |  |  |             print('DEBUG: domain ' + domain) | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |         return None | 
					
						
							|  |  |  |     if not isinstance(wf, dict): | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('WARN: Webfinger search for ' + | 
					
						
							|  |  |  |                   searchNickname + '@' + searchDomainFull + | 
					
						
							|  |  |  |                   ' did not return a dict. ' + | 
					
						
							|  |  |  |                   str(wf)) | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |         return None | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     personUrl = None | 
					
						
							|  |  |  |     if wf.get('errors'): | 
					
						
							|  |  |  |         personUrl = httpPrefix + '://' + \ | 
					
						
							|  |  |  |             searchDomainFull + '/users/' + searchNickname | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     profileStr = 'https://www.w3.org/ns/activitystreams' | 
					
						
							|  |  |  |     asHeader = { | 
					
						
							|  |  |  |         'Accept': 'application/activity+json; profile="' + profileStr + '"' | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if not personUrl: | 
					
						
							| 
									
										
										
										
											2021-03-14 20:41:37 +00:00
										 |  |  |         personUrl = getUserUrl(wf, 0, debug) | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     if not personUrl: | 
					
						
							|  |  |  |         # try single user instance | 
					
						
							|  |  |  |         asHeader = { | 
					
						
							|  |  |  |             'Accept': 'application/ld+json; profile="' + profileStr + '"' | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         personUrl = httpPrefix + '://' + searchDomainFull | 
					
						
							|  |  |  |     profileJson = \ | 
					
						
							| 
									
										
										
										
											2021-03-14 20:55:37 +00:00
										 |  |  |         getJson(session, personUrl, asHeader, None, debug, | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |                 projectVersion, httpPrefix, domain) | 
					
						
							|  |  |  |     if not profileJson: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         asHeader = { | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |             'Accept': 'application/ld+json; profile="' + profileStr + '"' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         profileJson = \ | 
					
						
							| 
									
										
										
										
											2021-03-14 20:55:37 +00:00
										 |  |  |             getJson(session, personUrl, asHeader, None, debug, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                     projectVersion, httpPrefix, domain) | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     if not profileJson: | 
					
						
							|  |  |  |         print('DEBUG: No actor returned from ' + personUrl) | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     avatarUrl = '' | 
					
						
							|  |  |  |     if profileJson.get('icon'): | 
					
						
							|  |  |  |         if profileJson['icon'].get('url'): | 
					
						
							|  |  |  |             avatarUrl = profileJson['icon']['url'] | 
					
						
							|  |  |  |     if not avatarUrl: | 
					
						
							|  |  |  |         avatarUrl = getPersonAvatarUrl(baseDir, personUrl, | 
					
						
							|  |  |  |                                        personCache, True) | 
					
						
							|  |  |  |     displayName = searchNickname | 
					
						
							|  |  |  |     if profileJson.get('name'): | 
					
						
							|  |  |  |         displayName = profileJson['name'] | 
					
						
							| 
									
										
										
										
											2021-01-02 11:18:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     lockedAccount = getLockedAccount(profileJson) | 
					
						
							|  |  |  |     if lockedAccount: | 
					
						
							|  |  |  |         displayName += '🔒' | 
					
						
							| 
									
										
										
										
											2021-01-12 13:18:08 +00:00
										 |  |  |     movedTo = '' | 
					
						
							|  |  |  |     if profileJson.get('movedTo'): | 
					
						
							|  |  |  |         movedTo = profileJson['movedTo'] | 
					
						
							|  |  |  |         displayName += ' ⌂' | 
					
						
							| 
									
										
										
										
											2021-01-02 11:18:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 12:00:07 +00:00
										 |  |  |     followsYou = \ | 
					
						
							|  |  |  |         isFollowerOfPerson(baseDir, | 
					
						
							|  |  |  |                            nickname, domain, | 
					
						
							|  |  |  |                            searchNickname, | 
					
						
							|  |  |  |                            searchDomainFull) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     profileDescription = '' | 
					
						
							|  |  |  |     if profileJson.get('summary'): | 
					
						
							|  |  |  |         profileDescription = profileJson['summary'] | 
					
						
							|  |  |  |     outboxUrl = None | 
					
						
							|  |  |  |     if not profileJson.get('outbox'): | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             pprint(profileJson) | 
					
						
							|  |  |  |             print('DEBUG: No outbox found') | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     outboxUrl = profileJson['outbox'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # profileBackgroundImage = '' | 
					
						
							|  |  |  |     # if profileJson.get('image'): | 
					
						
							|  |  |  |     #     if profileJson['image'].get('url'): | 
					
						
							|  |  |  |     #         profileBackgroundImage = profileJson['image']['url'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # url to return to | 
					
						
							|  |  |  |     backUrl = path | 
					
						
							|  |  |  |     if not backUrl.endswith('/inbox'): | 
					
						
							|  |  |  |         backUrl += '/inbox' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     profileDescriptionShort = profileDescription | 
					
						
							|  |  |  |     if '\n' in profileDescription: | 
					
						
							|  |  |  |         if len(profileDescription.split('\n')) > 2: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             profileDescriptionShort = '' | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         if '<br>' in profileDescription: | 
					
						
							|  |  |  |             if len(profileDescription.split('<br>')) > 2: | 
					
						
							|  |  |  |                 profileDescriptionShort = '' | 
					
						
							|  |  |  |     # keep the profile description short | 
					
						
							|  |  |  |     if len(profileDescriptionShort) > 256: | 
					
						
							|  |  |  |         profileDescriptionShort = '' | 
					
						
							|  |  |  |     # remove formatting from profile description used on title | 
					
						
							|  |  |  |     avatarDescription = '' | 
					
						
							|  |  |  |     if profileJson.get('summary'): | 
					
						
							|  |  |  |         if isinstance(profileJson['summary'], str): | 
					
						
							|  |  |  |             avatarDescription = \ | 
					
						
							|  |  |  |                 profileJson['summary'].replace('<br>', '\n') | 
					
						
							|  |  |  |             avatarDescription = avatarDescription.replace('<p>', '') | 
					
						
							|  |  |  |             avatarDescription = avatarDescription.replace('</p>', '') | 
					
						
							|  |  |  |             if '<' in avatarDescription: | 
					
						
							|  |  |  |                 avatarDescription = removeHtml(avatarDescription) | 
					
						
							| 
									
										
										
										
											2020-11-12 22:41:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 23:44:16 +00:00
										 |  |  |     imageUrl = '' | 
					
						
							|  |  |  |     if profileJson.get('image'): | 
					
						
							|  |  |  |         if profileJson['image'].get('url'): | 
					
						
							|  |  |  |             imageUrl = profileJson['image']['url'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-22 20:48:52 +00:00
										 |  |  |     alsoKnownAs = None | 
					
						
							|  |  |  |     if profileJson.get('alsoKnownAs'): | 
					
						
							|  |  |  |         alsoKnownAs = profileJson['alsoKnownAs'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  |     joinedDate = None | 
					
						
							|  |  |  |     if profileJson.get('published'): | 
					
						
							|  |  |  |         if 'T' in profileJson['published']: | 
					
						
							|  |  |  |             joinedDate = profileJson['published'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 23:38:58 +00:00
										 |  |  |     profileStr = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getProfileHeaderAfterSearch(baseDir, | 
					
						
							|  |  |  |                                      nickname, defaultTimeline, | 
					
						
							|  |  |  |                                      searchNickname, | 
					
						
							|  |  |  |                                      searchDomainFull, | 
					
						
							|  |  |  |                                      translate, | 
					
						
							| 
									
										
										
										
											2021-01-02 12:00:07 +00:00
										 |  |  |                                      displayName, followsYou, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                                      profileDescriptionShort, | 
					
						
							| 
									
										
										
										
											2021-01-12 13:18:08 +00:00
										 |  |  |                                      avatarUrl, imageUrl, | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |                                      movedTo, profileJson['id'], | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  |                                      alsoKnownAs, accessKeys, | 
					
						
							|  |  |  |                                      joinedDate) | 
					
						
							| 
									
										
										
										
											2020-11-12 22:41:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 11:19:16 +00:00
										 |  |  |     domainFull = getFullDomain(domain, port) | 
					
						
							| 
									
										
										
										
											2020-11-20 12:14:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 12:20:34 +00:00
										 |  |  |     followIsPermitted = True | 
					
						
							|  |  |  |     if searchNickname == 'news' and searchDomainFull == domainFull: | 
					
						
							|  |  |  |         # currently the news actor is not something you can follow | 
					
						
							|  |  |  |         followIsPermitted = False | 
					
						
							|  |  |  |     elif searchNickname == nickname and searchDomainFull == domainFull: | 
					
						
							|  |  |  |         # don't follow yourself! | 
					
						
							|  |  |  |         followIsPermitted = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if followIsPermitted: | 
					
						
							| 
									
										
										
										
											2020-11-20 12:14:22 +00:00
										 |  |  |         profileStr += '<div class="container">\n' | 
					
						
							|  |  |  |         profileStr += '  <form method="POST" action="' + \ | 
					
						
							|  |  |  |             backUrl + '/followconfirm">\n' | 
					
						
							|  |  |  |         profileStr += '    <center>\n' | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							|  |  |  |             '      <input type="hidden" name="actor" value="' + \ | 
					
						
							|  |  |  |             personUrl + '">\n' | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2021-04-23 12:04:42 +00:00
										 |  |  |             '      <button type="submit" class="button" name="submitYes" ' + \ | 
					
						
							|  |  |  |             'accesskey="' + accessKeys['followButton'] + '">' + \ | 
					
						
							| 
									
										
										
										
											2020-11-20 12:14:22 +00:00
										 |  |  |             translate['Follow'] + '</button>\n' | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2021-04-23 12:04:42 +00:00
										 |  |  |             '      <button type="submit" class="button" name="submitView" ' + \ | 
					
						
							|  |  |  |             'accesskey="' + accessKeys['viewButton'] + '">' + \ | 
					
						
							| 
									
										
										
										
											2020-11-20 12:14:22 +00:00
										 |  |  |             translate['View'] + '</button>\n' | 
					
						
							|  |  |  |         profileStr += '    </center>\n' | 
					
						
							|  |  |  |         profileStr += '  </form>\n' | 
					
						
							|  |  |  |         profileStr += '</div>\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     i = 0 | 
					
						
							|  |  |  |     for item in parseUserFeed(session, outboxUrl, asHeader, | 
					
						
							|  |  |  |                               projectVersion, httpPrefix, domain): | 
					
						
							| 
									
										
										
										
											2021-02-17 22:14:41 +00:00
										 |  |  |         if not item.get('actor'): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if item['actor'] != personUrl: | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |         if not item.get('type'): | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2021-02-17 22:28:44 +00:00
										 |  |  |         if item['type'] != 'Create': | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |             continue | 
					
						
							|  |  |  |         if not item.get('object'): | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2020-12-18 18:12:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |             individualPostAsHtml(True, recentPostsCache, maxRecentPosts, | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                                  translate, None, baseDir, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:23:15 +00:00
										 |  |  |                                  session, cachedWebfingers, personCache, | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |                                  nickname, domain, port, | 
					
						
							|  |  |  |                                  item, avatarUrl, False, False, | 
					
						
							|  |  |  |                                  httpPrefix, projectVersion, 'inbox', | 
					
						
							|  |  |  |                                  YTReplacementDomain, | 
					
						
							|  |  |  |                                  showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2021-01-30 11:47:09 +00:00
										 |  |  |                                  peertubeInstances, allowLocalNetworkAccess, | 
					
						
							| 
									
										
										
										
											2021-04-22 17:05:10 +00:00
										 |  |  |                                  themeName, | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |                                  False, False, False, False, False) | 
					
						
							|  |  |  |         i += 1 | 
					
						
							|  |  |  |         if i >= 20: | 
					
						
							|  |  |  |             break | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 19:46:21 +00:00
										 |  |  |     instanceTitle = \ | 
					
						
							|  |  |  |         getConfigParam(baseDir, 'instanceTitle') | 
					
						
							|  |  |  |     return htmlHeaderWithExternalStyle(cssFilename, instanceTitle) + \ | 
					
						
							|  |  |  |         profileStr + htmlFooter() | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  | def _getProfileHeader(baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                       nickname: str, domain: str, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                       domainFull: str, translate: {}, | 
					
						
							|  |  |  |                       defaultTimeline: str, | 
					
						
							|  |  |  |                       displayName: str, | 
					
						
							|  |  |  |                       avatarDescription: str, | 
					
						
							|  |  |  |                       profileDescriptionShort: str, | 
					
						
							|  |  |  |                       loginButton: str, avatarUrl: str, | 
					
						
							| 
									
										
										
										
											2021-01-22 20:59:43 +00:00
										 |  |  |                       theme: str, movedTo: str, | 
					
						
							| 
									
										
										
										
											2021-01-24 18:09:21 +00:00
										 |  |  |                       alsoKnownAs: [], | 
					
						
							| 
									
										
										
										
											2021-04-23 12:04:42 +00:00
										 |  |  |                       pinnedContent: str, | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  |                       accessKeys: {}, | 
					
						
							| 
									
										
										
										
											2021-05-12 18:31:41 +00:00
										 |  |  |                       joinedDate: str, | 
					
						
							|  |  |  |                       occupationName: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-12 22:33:00 +00:00
										 |  |  |     """The header of the profile screen, containing background
 | 
					
						
							|  |  |  |     image and avatar | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-11-12 23:00:36 +00:00
										 |  |  |     htmlStr = '\n\n    <figure class="profileHeader">\n' | 
					
						
							|  |  |  |     htmlStr += '      <a href="/users/' + \ | 
					
						
							| 
									
										
										
										
											2020-11-12 22:33:00 +00:00
										 |  |  |         nickname + '/' + defaultTimeline + '" title="' + \ | 
					
						
							| 
									
										
										
										
											2021-05-30 17:05:09 +00:00
										 |  |  |         translate['Switch to timeline view'] + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 23:10:25 +00:00
										 |  |  |     htmlStr += '        <img class="profileBackground" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-01 19:53:41 +00:00
										 |  |  |         'alt="" ' + \ | 
					
						
							| 
									
										
										
										
											2020-12-20 18:23:54 +00:00
										 |  |  |         'src="/users/' + nickname + '/image_' + theme + '.png" /></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 23:00:36 +00:00
										 |  |  |     htmlStr += '      <figcaption>\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 22:33:00 +00:00
										 |  |  |     htmlStr += \ | 
					
						
							| 
									
										
										
										
											2020-11-12 23:17:37 +00:00
										 |  |  |         '        <a href="/users/' + \ | 
					
						
							|  |  |  |         nickname + '/' + defaultTimeline + '" title="' + \ | 
					
						
							|  |  |  |         translate['Switch to timeline view'] + '">\n' + \ | 
					
						
							|  |  |  |         '          <img loading="lazy" src="' + avatarUrl + '" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-01 19:53:41 +00:00
										 |  |  |         'alt=""  class="title"></a>\n' | 
					
						
							| 
									
										
										
										
											2021-05-12 18:31:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     occupationStr = '' | 
					
						
							|  |  |  |     if occupationName: | 
					
						
							|  |  |  |         occupationStr += \ | 
					
						
							|  |  |  |             '        <b>' + occupationName + '</b><br>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     htmlStr += '        <h1>' + displayName + '</h1>\n' + occupationStr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 22:33:00 +00:00
										 |  |  |     htmlStr += \ | 
					
						
							| 
									
										
										
										
											2020-11-12 23:00:36 +00:00
										 |  |  |         '    <p><b>@' + nickname + '@' + domainFull + '</b><br>\n' | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  |     if joinedDate: | 
					
						
							|  |  |  |         htmlStr += \ | 
					
						
							| 
									
										
										
										
											2021-05-08 18:00:59 +00:00
										 |  |  |             '    <p>' + translate['Joined'] + ' ' + \ | 
					
						
							|  |  |  |             joinedDate.split('T')[0] + '<br>\n' | 
					
						
							| 
									
										
										
										
											2021-01-12 13:18:08 +00:00
										 |  |  |     if movedTo: | 
					
						
							|  |  |  |         newNickname = getNicknameFromActor(movedTo) | 
					
						
							|  |  |  |         newDomain, newPort = getDomainFromActor(movedTo) | 
					
						
							|  |  |  |         newDomainFull = getFullDomain(newDomain, newPort) | 
					
						
							|  |  |  |         if newNickname and newDomain: | 
					
						
							|  |  |  |             htmlStr += \ | 
					
						
							|  |  |  |                 '    <p>' + translate['New account'] + ': ' + \ | 
					
						
							|  |  |  |                 '<a href="' + movedTo + '">@' + \ | 
					
						
							|  |  |  |                 newNickname + '@' + newDomainFull + '</a><br>\n' | 
					
						
							| 
									
										
										
										
											2021-01-22 20:59:43 +00:00
										 |  |  |     elif alsoKnownAs: | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |         otherAccountsHtml = \ | 
					
						
							| 
									
										
										
										
											2021-01-22 20:59:43 +00:00
										 |  |  |             '    <p>' + translate['Other accounts'] + ': ' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |         actor = httpPrefix + '://' + domainFull + '/users/' + nickname | 
					
						
							|  |  |  |         ctr = 0 | 
					
						
							| 
									
										
										
										
											2021-01-22 20:59:43 +00:00
										 |  |  |         if isinstance(alsoKnownAs, list): | 
					
						
							|  |  |  |             for altActor in alsoKnownAs: | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |                 if altActor == actor: | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2021-01-22 20:59:43 +00:00
										 |  |  |                 if ctr > 0: | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |                     otherAccountsHtml += ' ' | 
					
						
							| 
									
										
										
										
											2021-01-22 20:59:43 +00:00
										 |  |  |                 ctr += 1 | 
					
						
							|  |  |  |                 altDomain, altPort = getDomainFromActor(altActor) | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |                 otherAccountsHtml += \ | 
					
						
							| 
									
										
										
										
											2021-01-22 20:59:43 +00:00
										 |  |  |                     '<a href="' + altActor + '">' + altDomain + '</a>' | 
					
						
							|  |  |  |         elif isinstance(alsoKnownAs, str): | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |             if alsoKnownAs != actor: | 
					
						
							|  |  |  |                 ctr += 1 | 
					
						
							|  |  |  |                 altDomain, altPort = getDomainFromActor(alsoKnownAs) | 
					
						
							|  |  |  |                 otherAccountsHtml += \ | 
					
						
							|  |  |  |                     '<a href="' + alsoKnownAs + '">' + altDomain + '</a>' | 
					
						
							|  |  |  |         otherAccountsHtml += '</p>\n' | 
					
						
							|  |  |  |         if ctr > 0: | 
					
						
							|  |  |  |             htmlStr += otherAccountsHtml | 
					
						
							| 
									
										
										
										
											2020-11-12 22:33:00 +00:00
										 |  |  |     htmlStr += \ | 
					
						
							| 
									
										
										
										
											2020-11-12 23:00:36 +00:00
										 |  |  |         '    <a href="/users/' + nickname + \ | 
					
						
							| 
									
										
										
										
											2020-11-12 22:33:00 +00:00
										 |  |  |         '/qrcode.png" alt="' + translate['QR Code'] + '" title="' + \ | 
					
						
							|  |  |  |         translate['QR Code'] + '">' + \ | 
					
						
							| 
									
										
										
										
											2021-02-01 18:42:39 +00:00
										 |  |  |         '<img class="qrcode" alt="' + translate['QR Code'] + \ | 
					
						
							|  |  |  |         '" src="/icons/qrcode.png" /></a></p>\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 23:00:36 +00:00
										 |  |  |     htmlStr += '        <p>' + profileDescriptionShort + '</p>\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 22:33:00 +00:00
										 |  |  |     htmlStr += loginButton | 
					
						
							| 
									
										
										
										
											2021-01-24 18:09:21 +00:00
										 |  |  |     if pinnedContent: | 
					
						
							| 
									
										
										
										
											2021-01-28 14:21:51 +00:00
										 |  |  |         htmlStr += pinnedContent.replace('<p>', '<p>📎', 1) | 
					
						
							| 
									
										
										
										
											2021-01-24 18:18:19 +00:00
										 |  |  |     htmlStr += '      </figcaption>\n' | 
					
						
							|  |  |  |     htmlStr += '    </figure>\n\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 22:33:00 +00:00
										 |  |  |     return htmlStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getProfileHeaderAfterSearch(baseDir: str, | 
					
						
							|  |  |  |                                  nickname: str, defaultTimeline: str, | 
					
						
							|  |  |  |                                  searchNickname: str, | 
					
						
							|  |  |  |                                  searchDomainFull: str, | 
					
						
							|  |  |  |                                  translate: {}, | 
					
						
							|  |  |  |                                  displayName: str, | 
					
						
							| 
									
										
										
										
											2021-01-02 12:00:07 +00:00
										 |  |  |                                  followsYou: bool, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                                  profileDescriptionShort: str, | 
					
						
							| 
									
										
										
										
											2021-01-12 13:18:08 +00:00
										 |  |  |                                  avatarUrl: str, imageUrl: str, | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |                                  movedTo: str, actor: str, | 
					
						
							| 
									
										
										
										
											2021-04-23 12:04:42 +00:00
										 |  |  |                                  alsoKnownAs: [], | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  |                                  accessKeys: {}, | 
					
						
							|  |  |  |                                  joinedDate: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-12 23:38:58 +00:00
										 |  |  |     """The header of a searched for handle, containing background
 | 
					
						
							|  |  |  |     image and avatar | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     htmlStr = '\n\n    <figure class="profileHeader">\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 23:50:25 +00:00
										 |  |  |     htmlStr += '      <a href="/users/' + \ | 
					
						
							|  |  |  |         nickname + '/' + defaultTimeline + '" title="' + \ | 
					
						
							| 
									
										
										
										
											2021-04-23 12:04:42 +00:00
										 |  |  |         translate['Switch to timeline view'] + '" ' + \ | 
					
						
							|  |  |  |         'accesskey="' + accessKeys['menuTimeline'] + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 23:44:16 +00:00
										 |  |  |     htmlStr += '        <img class="profileBackground" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-01 19:53:41 +00:00
										 |  |  |         'alt="" ' + \ | 
					
						
							| 
									
										
										
										
											2020-11-12 23:44:16 +00:00
										 |  |  |         'src="' + imageUrl + '" /></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 23:38:58 +00:00
										 |  |  |     htmlStr += '      <figcaption>\n' | 
					
						
							|  |  |  |     if avatarUrl: | 
					
						
							| 
									
										
										
										
											2020-11-12 23:50:25 +00:00
										 |  |  |         htmlStr += '      <a href="/users/' + \ | 
					
						
							|  |  |  |             nickname + '/' + defaultTimeline + '" title="' + \ | 
					
						
							|  |  |  |             translate['Switch to timeline view'] + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 23:38:58 +00:00
										 |  |  |         htmlStr += \ | 
					
						
							|  |  |  |             '          <img loading="lazy" src="' + avatarUrl + '" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-01 19:53:41 +00:00
										 |  |  |             'alt="" class="title"></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-12 23:38:58 +00:00
										 |  |  |     htmlStr += '        <h1>' + displayName + '</h1>\n' | 
					
						
							|  |  |  |     htmlStr += \ | 
					
						
							|  |  |  |         '    <p><b>@' + searchNickname + '@' + searchDomainFull + '</b><br>\n' | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  |     if joinedDate: | 
					
						
							| 
									
										
										
										
											2021-05-08 18:00:59 +00:00
										 |  |  |         htmlStr += '        <p>' + translate['Joined'] + ' ' + \ | 
					
						
							|  |  |  |             joinedDate.split('T')[0] + '</p>\n' | 
					
						
							| 
									
										
										
										
											2021-01-02 12:00:07 +00:00
										 |  |  |     if followsYou: | 
					
						
							|  |  |  |         htmlStr += '        <p><b>' + translate['Follows you'] + '</b></p>\n' | 
					
						
							| 
									
										
										
										
											2021-01-12 13:18:08 +00:00
										 |  |  |     if movedTo: | 
					
						
							|  |  |  |         newNickname = getNicknameFromActor(movedTo) | 
					
						
							|  |  |  |         newDomain, newPort = getDomainFromActor(movedTo) | 
					
						
							|  |  |  |         newDomainFull = getFullDomain(newDomain, newPort) | 
					
						
							|  |  |  |         if newNickname and newDomain: | 
					
						
							|  |  |  |             newHandle = newNickname + '@' + newDomainFull | 
					
						
							|  |  |  |             htmlStr += '        <p>' + translate['New account'] + \ | 
					
						
							|  |  |  |                 ': < a href="' + movedTo + '">@' + newHandle + '</a></p>\n' | 
					
						
							| 
									
										
										
										
											2021-01-22 20:48:52 +00:00
										 |  |  |     elif alsoKnownAs: | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |         otherAccountshtml = \ | 
					
						
							| 
									
										
										
										
											2021-01-22 20:48:52 +00:00
										 |  |  |             '        <p>' + translate['Other accounts'] + ': ' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |         ctr = 0 | 
					
						
							| 
									
										
										
										
											2021-01-22 20:48:52 +00:00
										 |  |  |         if isinstance(alsoKnownAs, list): | 
					
						
							|  |  |  |             for altActor in alsoKnownAs: | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |                 if altActor == actor: | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2021-01-22 20:48:52 +00:00
										 |  |  |                 if ctr > 0: | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |                     otherAccountshtml += ' ' | 
					
						
							| 
									
										
										
										
											2021-01-22 20:48:52 +00:00
										 |  |  |                 ctr += 1 | 
					
						
							|  |  |  |                 altDomain, altPort = getDomainFromActor(altActor) | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |                 otherAccountshtml += \ | 
					
						
							| 
									
										
										
										
											2021-01-22 20:48:52 +00:00
										 |  |  |                     '<a href="' + altActor + '">' + altDomain + '</a>' | 
					
						
							|  |  |  |         elif isinstance(alsoKnownAs, str): | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |             if alsoKnownAs != actor: | 
					
						
							|  |  |  |                 ctr += 1 | 
					
						
							|  |  |  |                 altDomain, altPort = getDomainFromActor(alsoKnownAs) | 
					
						
							|  |  |  |                 otherAccountshtml += \ | 
					
						
							|  |  |  |                     '<a href="' + alsoKnownAs + '">' + altDomain + '</a>' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         otherAccountshtml += '</p>\n' | 
					
						
							|  |  |  |         if ctr > 0: | 
					
						
							|  |  |  |             htmlStr += otherAccountshtml | 
					
						
							| 
									
										
										
										
											2021-01-12 13:18:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 23:38:58 +00:00
										 |  |  |     htmlStr += '        <p>' + profileDescriptionShort + '</p>\n' | 
					
						
							|  |  |  |     htmlStr += '      </figcaption>\n' | 
					
						
							|  |  |  |     htmlStr += '    </figure>\n\n' | 
					
						
							|  |  |  |     return htmlStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | def htmlProfile(rssIconAtTop: bool, | 
					
						
							|  |  |  |                 cssCache: {}, iconsAsButtons: bool, | 
					
						
							|  |  |  |                 defaultTimeline: str, | 
					
						
							|  |  |  |                 recentPostsCache: {}, maxRecentPosts: int, | 
					
						
							|  |  |  |                 translate: {}, projectVersion: str, | 
					
						
							|  |  |  |                 baseDir: str, httpPrefix: str, authorized: bool, | 
					
						
							|  |  |  |                 profileJson: {}, selected: str, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                 session, cachedWebfingers: {}, personCache: {}, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                 YTReplacementDomain: str, | 
					
						
							|  |  |  |                 showPublishedDateOnly: bool, | 
					
						
							| 
									
										
										
										
											2020-12-20 17:26:38 +00:00
										 |  |  |                 newswire: {}, theme: str, dormantMonths: int, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                 peertubeInstances: [], | 
					
						
							| 
									
										
										
										
											2021-01-30 11:47:09 +00:00
										 |  |  |                 allowLocalNetworkAccess: bool, | 
					
						
							| 
									
										
										
										
											2021-02-05 19:14:27 +00:00
										 |  |  |                 textModeBanner: str, | 
					
						
							| 
									
										
										
										
											2021-05-16 09:20:24 +00:00
										 |  |  |                 debug: bool, accessKeys: {}, city: str, | 
					
						
							| 
									
										
										
										
											2020-12-13 12:44:17 +00:00
										 |  |  |                 extraJson=None, pageNumber=None, | 
					
						
							|  |  |  |                 maxItemsPerPage=None) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Show the profile page as html
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     nickname = profileJson['preferredUsername'] | 
					
						
							|  |  |  |     if not nickname: | 
					
						
							|  |  |  |         return "" | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     if isSystemAccount(nickname): | 
					
						
							|  |  |  |         return htmlFrontScreen(rssIconAtTop, | 
					
						
							|  |  |  |                                cssCache, iconsAsButtons, | 
					
						
							|  |  |  |                                defaultTimeline, | 
					
						
							|  |  |  |                                recentPostsCache, maxRecentPosts, | 
					
						
							|  |  |  |                                translate, projectVersion, | 
					
						
							|  |  |  |                                baseDir, httpPrefix, authorized, | 
					
						
							|  |  |  |                                profileJson, selected, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                                session, cachedWebfingers, personCache, | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |                                YTReplacementDomain, | 
					
						
							|  |  |  |                                showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2020-12-20 17:26:38 +00:00
										 |  |  |                                newswire, theme, extraJson, | 
					
						
							| 
									
										
										
										
											2021-04-23 16:29:03 +00:00
										 |  |  |                                allowLocalNetworkAccess, accessKeys, | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |                                pageNumber, maxItemsPerPage) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     domain, port = getDomainFromActor(profileJson['id']) | 
					
						
							|  |  |  |     if not domain: | 
					
						
							|  |  |  |         return "" | 
					
						
							|  |  |  |     displayName = \ | 
					
						
							|  |  |  |         addEmojiToDisplayName(baseDir, httpPrefix, | 
					
						
							|  |  |  |                               nickname, domain, | 
					
						
							|  |  |  |                               profileJson['name'], True) | 
					
						
							|  |  |  |     domainFull = domain | 
					
						
							|  |  |  |     if port: | 
					
						
							|  |  |  |         domainFull = domain + ':' + str(port) | 
					
						
							|  |  |  |     profileDescription = \ | 
					
						
							|  |  |  |         addEmojiToDisplayName(baseDir, httpPrefix, | 
					
						
							|  |  |  |                               nickname, domain, | 
					
						
							|  |  |  |                               profileJson['summary'], False) | 
					
						
							|  |  |  |     postsButton = 'button' | 
					
						
							|  |  |  |     followingButton = 'button' | 
					
						
							|  |  |  |     followersButton = 'button' | 
					
						
							|  |  |  |     rolesButton = 'button' | 
					
						
							|  |  |  |     skillsButton = 'button' | 
					
						
							|  |  |  |     sharesButton = 'button' | 
					
						
							|  |  |  |     if selected == 'posts': | 
					
						
							|  |  |  |         postsButton = 'buttonselected' | 
					
						
							|  |  |  |     elif selected == 'following': | 
					
						
							|  |  |  |         followingButton = 'buttonselected' | 
					
						
							|  |  |  |     elif selected == 'followers': | 
					
						
							|  |  |  |         followersButton = 'buttonselected' | 
					
						
							|  |  |  |     elif selected == 'roles': | 
					
						
							|  |  |  |         rolesButton = 'buttonselected' | 
					
						
							|  |  |  |     elif selected == 'skills': | 
					
						
							|  |  |  |         skillsButton = 'buttonselected' | 
					
						
							|  |  |  |     elif selected == 'shares': | 
					
						
							|  |  |  |         sharesButton = 'buttonselected' | 
					
						
							|  |  |  |     loginButton = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     followApprovalsSection = '' | 
					
						
							|  |  |  |     followApprovals = False | 
					
						
							|  |  |  |     editProfileStr = '' | 
					
						
							|  |  |  |     logoutStr = '' | 
					
						
							|  |  |  |     actor = profileJson['id'] | 
					
						
							|  |  |  |     usersPath = '/users/' + actor.split('/users/')[1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     donateSection = '' | 
					
						
							|  |  |  |     donateUrl = getDonationUrl(profileJson) | 
					
						
							|  |  |  |     PGPpubKey = getPGPpubKey(profileJson) | 
					
						
							|  |  |  |     PGPfingerprint = getPGPfingerprint(profileJson) | 
					
						
							|  |  |  |     emailAddress = getEmailAddress(profileJson) | 
					
						
							|  |  |  |     xmppAddress = getXmppAddress(profileJson) | 
					
						
							|  |  |  |     matrixAddress = getMatrixAddress(profileJson) | 
					
						
							|  |  |  |     ssbAddress = getSSBAddress(profileJson) | 
					
						
							|  |  |  |     toxAddress = getToxAddress(profileJson) | 
					
						
							| 
									
										
										
										
											2020-12-24 16:48:03 +00:00
										 |  |  |     briarAddress = getBriarAddress(profileJson) | 
					
						
							| 
									
										
										
										
											2020-11-29 12:50:41 +00:00
										 |  |  |     jamiAddress = getJamiAddress(profileJson) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     if donateUrl or xmppAddress or matrixAddress or \ | 
					
						
							| 
									
										
										
										
											2020-12-24 16:48:03 +00:00
										 |  |  |        ssbAddress or toxAddress or briarAddress or \ | 
					
						
							|  |  |  |        jamiAddress or PGPpubKey or \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |        PGPfingerprint or emailAddress: | 
					
						
							|  |  |  |         donateSection = '<div class="container">\n' | 
					
						
							|  |  |  |         donateSection += '  <center>\n' | 
					
						
							|  |  |  |         if donateUrl and not isSystemAccount(nickname): | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '    <p><a href="' + donateUrl + \ | 
					
						
							|  |  |  |                 '"><button class="donateButton">' + translate['Donate'] + \ | 
					
						
							|  |  |  |                 '</button></a></p>\n' | 
					
						
							|  |  |  |         if emailAddress: | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '<p>' + translate['Email'] + ': <a href="mailto:' + \ | 
					
						
							|  |  |  |                 emailAddress + '">' + emailAddress + '</a></p>\n' | 
					
						
							|  |  |  |         if xmppAddress: | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '<p>' + translate['XMPP'] + ': <a href="xmpp:' + \ | 
					
						
							|  |  |  |                 xmppAddress + '">'+xmppAddress + '</a></p>\n' | 
					
						
							|  |  |  |         if matrixAddress: | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '<p>' + translate['Matrix'] + ': ' + matrixAddress + '</p>\n' | 
					
						
							|  |  |  |         if ssbAddress: | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '<p>SSB: <label class="ssbaddr">' + \ | 
					
						
							|  |  |  |                 ssbAddress + '</label></p>\n' | 
					
						
							|  |  |  |         if toxAddress: | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '<p>Tox: <label class="toxaddr">' + \ | 
					
						
							|  |  |  |                 toxAddress + '</label></p>\n' | 
					
						
							| 
									
										
										
										
											2020-12-24 16:48:03 +00:00
										 |  |  |         if briarAddress: | 
					
						
							| 
									
										
										
										
											2020-12-24 17:11:18 +00:00
										 |  |  |             if briarAddress.startswith('briar://'): | 
					
						
							|  |  |  |                 donateSection += \ | 
					
						
							|  |  |  |                     '<p><label class="toxaddr">' + \ | 
					
						
							|  |  |  |                     briarAddress + '</label></p>\n' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 donateSection += \ | 
					
						
							|  |  |  |                     '<p>briar://<label class="toxaddr">' + \ | 
					
						
							|  |  |  |                     briarAddress + '</label></p>\n' | 
					
						
							| 
									
										
										
										
											2020-11-29 12:50:41 +00:00
										 |  |  |         if jamiAddress: | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '<p>Jami: <label class="toxaddr">' + \ | 
					
						
							|  |  |  |                 jamiAddress + '</label></p>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         if PGPfingerprint: | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '<p class="pgp">PGP: ' + \ | 
					
						
							|  |  |  |                 PGPfingerprint.replace('\n', '<br>') + '</p>\n' | 
					
						
							|  |  |  |         if PGPpubKey: | 
					
						
							|  |  |  |             donateSection += \ | 
					
						
							|  |  |  |                 '<p class="pgp">' + PGPpubKey.replace('\n', '<br>') + '</p>\n' | 
					
						
							|  |  |  |         donateSection += '  </center>\n' | 
					
						
							|  |  |  |         donateSection += '</div>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     if authorized: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         editProfileStr = \ | 
					
						
							|  |  |  |             '<a class="imageAnchor" href="' + usersPath + '/editprofile">' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |             '<img loading="lazy" src="/icons' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             '/edit.png" title="' + translate['Edit'] + \ | 
					
						
							|  |  |  |             '" alt="| ' + translate['Edit'] + '" class="timelineicon"/></a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         logoutStr = \ | 
					
						
							|  |  |  |             '<a class="imageAnchor" href="/logout">' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |             '<img loading="lazy" src="/icons' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             '/logout.png" title="' + translate['Logout'] + \ | 
					
						
							|  |  |  |             '" alt="| ' + translate['Logout'] + \ | 
					
						
							|  |  |  |             '" class="timelineicon"/></a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # are there any follow requests? | 
					
						
							|  |  |  |         followRequestsFilename = \ | 
					
						
							|  |  |  |             baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |             nickname + '@' + domain + '/followrequests.txt' | 
					
						
							|  |  |  |         if os.path.isfile(followRequestsFilename): | 
					
						
							|  |  |  |             with open(followRequestsFilename, 'r') as f: | 
					
						
							|  |  |  |                 for line in f: | 
					
						
							|  |  |  |                     if len(line) > 0: | 
					
						
							|  |  |  |                         followApprovals = True | 
					
						
							|  |  |  |                         followersButton = 'buttonhighlighted' | 
					
						
							|  |  |  |                         if selected == 'followers': | 
					
						
							|  |  |  |                             followersButton = 'buttonselectedhighlighted' | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |         if selected == 'followers': | 
					
						
							|  |  |  |             if followApprovals: | 
					
						
							|  |  |  |                 with open(followRequestsFilename, 'r') as f: | 
					
						
							|  |  |  |                     for followerHandle in f: | 
					
						
							|  |  |  |                         if len(line) > 0: | 
					
						
							|  |  |  |                             if '://' in followerHandle: | 
					
						
							|  |  |  |                                 followerActor = followerHandle | 
					
						
							|  |  |  |                             else: | 
					
						
							|  |  |  |                                 followerActor = \ | 
					
						
							|  |  |  |                                     httpPrefix + '://' + \ | 
					
						
							|  |  |  |                                     followerHandle.split('@')[1] + \ | 
					
						
							|  |  |  |                                     '/users/' + followerHandle.split('@')[0] | 
					
						
							|  |  |  |                             basePath = '/users/' + nickname | 
					
						
							|  |  |  |                             followApprovalsSection += '<div class="container">' | 
					
						
							|  |  |  |                             followApprovalsSection += \ | 
					
						
							|  |  |  |                                 '<a href="' + followerActor + '">' | 
					
						
							|  |  |  |                             followApprovalsSection += \ | 
					
						
							|  |  |  |                                 '<span class="followRequestHandle">' + \ | 
					
						
							|  |  |  |                                 followerHandle + '</span></a>' | 
					
						
							|  |  |  |                             followApprovalsSection += \ | 
					
						
							|  |  |  |                                 '<a href="' + basePath + \ | 
					
						
							|  |  |  |                                 '/followapprove=' + followerHandle + '">' | 
					
						
							|  |  |  |                             followApprovalsSection += \ | 
					
						
							|  |  |  |                                 '<button class="followApprove">' + \ | 
					
						
							|  |  |  |                                 translate['Approve'] + '</button></a><br><br>' | 
					
						
							|  |  |  |                             followApprovalsSection += \ | 
					
						
							|  |  |  |                                 '<a href="' + basePath + \ | 
					
						
							|  |  |  |                                 '/followdeny=' + followerHandle + '">' | 
					
						
							|  |  |  |                             followApprovalsSection += \ | 
					
						
							|  |  |  |                                 '<button class="followDeny">' + \ | 
					
						
							|  |  |  |                                 translate['Deny'] + '</button></a>' | 
					
						
							|  |  |  |                             followApprovalsSection += '</div>' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     profileDescriptionShort = profileDescription | 
					
						
							|  |  |  |     if '\n' in profileDescription: | 
					
						
							|  |  |  |         if len(profileDescription.split('\n')) > 2: | 
					
						
							|  |  |  |             profileDescriptionShort = '' | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         if '<br>' in profileDescription: | 
					
						
							|  |  |  |             if len(profileDescription.split('<br>')) > 2: | 
					
						
							|  |  |  |                 profileDescriptionShort = '' | 
					
						
							|  |  |  |                 profileDescription = profileDescription.replace('<br>', '\n') | 
					
						
							|  |  |  |     # keep the profile description short | 
					
						
							|  |  |  |     if len(profileDescriptionShort) > 256: | 
					
						
							|  |  |  |         profileDescriptionShort = '' | 
					
						
							|  |  |  |     # remove formatting from profile description used on title | 
					
						
							|  |  |  |     avatarDescription = '' | 
					
						
							|  |  |  |     if profileJson.get('summary'): | 
					
						
							|  |  |  |         avatarDescription = profileJson['summary'].replace('<br>', '\n') | 
					
						
							|  |  |  |         avatarDescription = avatarDescription.replace('<p>', '') | 
					
						
							|  |  |  |         avatarDescription = avatarDescription.replace('</p>', '') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-12 13:18:08 +00:00
										 |  |  |     movedTo = '' | 
					
						
							|  |  |  |     if profileJson.get('movedTo'): | 
					
						
							|  |  |  |         movedTo = profileJson['movedTo'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-22 20:59:43 +00:00
										 |  |  |     alsoKnownAs = None | 
					
						
							|  |  |  |     if profileJson.get('alsoKnownAs'): | 
					
						
							|  |  |  |         alsoKnownAs = profileJson['alsoKnownAs'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  |     joinedDate = None | 
					
						
							|  |  |  |     if profileJson.get('published'): | 
					
						
							|  |  |  |         if 'T' in profileJson['published']: | 
					
						
							|  |  |  |             joinedDate = profileJson['published'] | 
					
						
							| 
									
										
										
										
											2021-05-12 18:31:41 +00:00
										 |  |  |     occupationName = None | 
					
						
							| 
									
										
										
										
											2021-05-13 11:35:36 +00:00
										 |  |  |     if profileJson.get('hasOccupation'): | 
					
						
							| 
									
										
										
										
											2021-05-16 15:10:39 +00:00
										 |  |  |         occupationName = getOccupationName(profileJson) | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     avatarUrl = profileJson['icon']['url'] | 
					
						
							| 
									
										
										
										
											2021-01-24 18:09:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # get pinned post content | 
					
						
							|  |  |  |     accountDir = baseDir + '/accounts/' + nickname + '@' + domain | 
					
						
							|  |  |  |     pinnedFilename = accountDir + '/pinToProfile.txt' | 
					
						
							|  |  |  |     pinnedContent = None | 
					
						
							|  |  |  |     if os.path.isfile(pinnedFilename): | 
					
						
							|  |  |  |         with open(pinnedFilename, 'r') as pinFile: | 
					
						
							|  |  |  |             pinnedContent = pinFile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     profileHeaderStr = \ | 
					
						
							| 
									
										
										
										
											2021-01-23 10:03:50 +00:00
										 |  |  |         _getProfileHeader(baseDir, httpPrefix, | 
					
						
							|  |  |  |                           nickname, domain, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                           domainFull, translate, | 
					
						
							|  |  |  |                           defaultTimeline, displayName, | 
					
						
							|  |  |  |                           avatarDescription, | 
					
						
							|  |  |  |                           profileDescriptionShort, | 
					
						
							| 
									
										
										
										
											2021-01-12 13:18:08 +00:00
										 |  |  |                           loginButton, avatarUrl, theme, | 
					
						
							| 
									
										
										
										
											2021-01-24 18:09:21 +00:00
										 |  |  |                           movedTo, alsoKnownAs, | 
					
						
							| 
									
										
										
										
											2021-05-08 17:57:57 +00:00
										 |  |  |                           pinnedContent, accessKeys, | 
					
						
							| 
									
										
										
										
											2021-05-12 18:31:41 +00:00
										 |  |  |                           joinedDate, occupationName) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-05 15:30:51 +00:00
										 |  |  |     # keyboard navigation | 
					
						
							| 
									
										
										
										
											2021-02-05 17:05:53 +00:00
										 |  |  |     userPathStr = '/users/' + nickname | 
					
						
							| 
									
										
										
										
											2021-02-05 17:44:50 +00:00
										 |  |  |     deft = defaultTimeline | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuTimeline = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('🏠') + ' ' + \ | 
					
						
							|  |  |  |         translate['Switch to timeline view'] | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuEdit = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('✍') + ' ' + translate['Edit'] | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuFollowing = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('👥') + ' ' + translate['Following'] | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuFollowers = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('👪') + ' ' + translate['Followers'] | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuRoles = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('🤚') + ' ' + translate['Roles'] | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuSkills = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('🛠') + ' ' + translate['Skills'] | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuShares = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('🤝') + ' ' + translate['Shares'] | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuLogout = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('❎') + ' ' + translate['Logout'] | 
					
						
							| 
									
										
										
										
											2021-02-05 17:05:53 +00:00
										 |  |  |     navLinks = { | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |         menuTimeline: userPathStr + '/' + deft, | 
					
						
							|  |  |  |         menuEdit: userPathStr + '/editprofile', | 
					
						
							|  |  |  |         menuFollowing: userPathStr + '/following#timeline', | 
					
						
							|  |  |  |         menuFollowers: userPathStr + '/followers#timeline', | 
					
						
							|  |  |  |         menuRoles: userPathStr + '/roles#timeline', | 
					
						
							|  |  |  |         menuSkills: userPathStr + '/skills#timeline', | 
					
						
							|  |  |  |         menuShares: userPathStr + '/shares#timeline', | 
					
						
							|  |  |  |         menuLogout: '/logout' | 
					
						
							| 
									
										
										
										
											2021-02-05 17:55:49 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-22 14:12:59 +00:00
										 |  |  |     navAccessKeys = {} | 
					
						
							|  |  |  |     for variableName, key in accessKeys.items(): | 
					
						
							|  |  |  |         if not locals().get(variableName): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         navAccessKeys[locals()[variableName]] = key | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-22 11:51:19 +00:00
										 |  |  |     profileStr = htmlKeyboardNavigation(textModeBanner, | 
					
						
							| 
									
										
										
										
											2021-04-22 11:57:35 +00:00
										 |  |  |                                         navLinks, navAccessKeys) | 
					
						
							| 
									
										
										
										
											2021-02-01 17:21:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     profileStr += profileHeaderStr + donateSection | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     profileStr += '<div class="container" id="buttonheader">\n' | 
					
						
							|  |  |  |     profileStr += '  <center>' | 
					
						
							|  |  |  |     profileStr += \ | 
					
						
							|  |  |  |         '    <a href="' + usersPath + '#buttonheader"><button class="' + \ | 
					
						
							|  |  |  |         postsButton + '"><span>' + translate['Posts'] + \ | 
					
						
							|  |  |  |         ' </span></button></a>' | 
					
						
							|  |  |  |     profileStr += \ | 
					
						
							|  |  |  |         '    <a href="' + usersPath + '/following#buttonheader">' + \ | 
					
						
							|  |  |  |         '<button class="' + followingButton + '"><span>' + \ | 
					
						
							|  |  |  |         translate['Following'] + ' </span></button></a>' | 
					
						
							|  |  |  |     profileStr += \ | 
					
						
							|  |  |  |         '    <a href="' + usersPath + '/followers#buttonheader">' + \ | 
					
						
							|  |  |  |         '<button class="' + followersButton + \ | 
					
						
							|  |  |  |         '"><span>' + translate['Followers'] + ' </span></button></a>' | 
					
						
							|  |  |  |     profileStr += \ | 
					
						
							|  |  |  |         '    <a href="' + usersPath + '/roles#buttonheader">' + \ | 
					
						
							|  |  |  |         '<button class="' + rolesButton + '"><span>' + \ | 
					
						
							|  |  |  |         translate['Roles'] + \ | 
					
						
							|  |  |  |         ' </span></button></a>' | 
					
						
							|  |  |  |     profileStr += \ | 
					
						
							|  |  |  |         '    <a href="' + usersPath + '/skills#buttonheader">' + \ | 
					
						
							|  |  |  |         '<button class="' + skillsButton + '"><span>' + \ | 
					
						
							|  |  |  |         translate['Skills'] + ' </span></button></a>' | 
					
						
							|  |  |  |     profileStr += \ | 
					
						
							|  |  |  |         '    <a href="' + usersPath + '/shares#buttonheader">' + \ | 
					
						
							|  |  |  |         '<button class="' + sharesButton + '"><span>' + \ | 
					
						
							|  |  |  |         translate['Shares'] + ' </span></button></a>' | 
					
						
							|  |  |  |     profileStr += logoutStr + editProfileStr | 
					
						
							|  |  |  |     profileStr += '  </center>' | 
					
						
							|  |  |  |     profileStr += '</div>' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-05 17:55:49 +00:00
										 |  |  |     # start of #timeline | 
					
						
							|  |  |  |     profileStr += '<div id="timeline">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     profileStr += followApprovalsSection | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cssFilename = baseDir + '/epicyon-profile.css' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/epicyon.css'): | 
					
						
							|  |  |  |         cssFilename = baseDir + '/epicyon.css' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     licenseStr = \ | 
					
						
							|  |  |  |         '<a href="https://gitlab.com/bashrc2/epicyon">' + \ | 
					
						
							|  |  |  |         '<img loading="lazy" class="license" alt="' + \ | 
					
						
							|  |  |  |         translate['Get the source code'] + '" title="' + \ | 
					
						
							|  |  |  |         translate['Get the source code'] + '" src="/icons/agpl.png" /></a>' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if selected == 'posts': | 
					
						
							| 
									
										
										
										
											2020-11-27 18:50:54 +00:00
										 |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _htmlProfilePosts(recentPostsCache, maxRecentPosts, | 
					
						
							|  |  |  |                               translate, | 
					
						
							|  |  |  |                               baseDir, httpPrefix, authorized, | 
					
						
							|  |  |  |                               nickname, domain, port, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                               session, cachedWebfingers, personCache, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                               projectVersion, | 
					
						
							|  |  |  |                               YTReplacementDomain, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                               showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2021-01-30 11:47:09 +00:00
										 |  |  |                               peertubeInstances, | 
					
						
							| 
									
										
										
										
											2021-03-09 19:52:10 +00:00
										 |  |  |                               allowLocalNetworkAccess, | 
					
						
							|  |  |  |                               theme) + licenseStr | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     elif selected == 'following': | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _htmlProfileFollowing(translate, baseDir, httpPrefix, | 
					
						
							|  |  |  |                                   authorized, nickname, | 
					
						
							|  |  |  |                                   domain, port, session, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                                   cachedWebfingers, personCache, extraJson, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                                   projectVersion, ["unfollow"], selected, | 
					
						
							|  |  |  |                                   usersPath, pageNumber, maxItemsPerPage, | 
					
						
							| 
									
										
										
										
											2021-03-14 19:22:58 +00:00
										 |  |  |                                   dormantMonths, debug) | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     elif selected == 'followers': | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _htmlProfileFollowing(translate, baseDir, httpPrefix, | 
					
						
							|  |  |  |                                   authorized, nickname, | 
					
						
							|  |  |  |                                   domain, port, session, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                                   cachedWebfingers, personCache, extraJson, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                                   projectVersion, ["block"], | 
					
						
							|  |  |  |                                   selected, usersPath, pageNumber, | 
					
						
							| 
									
										
										
										
											2021-03-14 19:22:58 +00:00
										 |  |  |                                   maxItemsPerPage, dormantMonths, debug) | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     elif selected == 'roles': | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _htmlProfileRoles(translate, nickname, domainFull, | 
					
						
							|  |  |  |                               extraJson) | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     elif selected == 'skills': | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _htmlProfileSkills(translate, nickname, domainFull, extraJson) | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |     elif selected == 'shares': | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _htmlProfileShares(actor, translate, | 
					
						
							|  |  |  |                                nickname, domainFull, | 
					
						
							|  |  |  |                                extraJson) + licenseStr | 
					
						
							| 
									
										
										
										
											2021-02-05 17:55:49 +00:00
										 |  |  |     # end of #timeline | 
					
						
							|  |  |  |     profileStr += '</div>' | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 19:46:21 +00:00
										 |  |  |     instanceTitle = \ | 
					
						
							|  |  |  |         getConfigParam(baseDir, 'instanceTitle') | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     profileStr = \ | 
					
						
							| 
									
										
										
										
											2021-05-16 09:20:24 +00:00
										 |  |  |         htmlHeaderWithPersonMarkup(cssFilename, instanceTitle, | 
					
						
							|  |  |  |                                    profileJson, city) + \ | 
					
						
							| 
									
										
										
										
											2020-11-28 10:11:36 +00:00
										 |  |  |         profileStr + htmlFooter() | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     return profileStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int, | 
					
						
							|  |  |  |                       translate: {}, | 
					
						
							|  |  |  |                       baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                       authorized: bool, | 
					
						
							|  |  |  |                       nickname: str, domain: str, port: int, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                       session, cachedWebfingers: {}, personCache: {}, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                       projectVersion: str, | 
					
						
							|  |  |  |                       YTReplacementDomain: str, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                       showPublishedDateOnly: bool, | 
					
						
							| 
									
										
										
										
											2021-01-30 11:47:09 +00:00
										 |  |  |                       peertubeInstances: [], | 
					
						
							| 
									
										
										
										
											2021-03-09 19:52:10 +00:00
										 |  |  |                       allowLocalNetworkAccess: bool, | 
					
						
							|  |  |  |                       themeName: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Shows posts on the profile screen
 | 
					
						
							|  |  |  |     These should only be public posts | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     separatorStr = htmlPostSeparator(baseDir, None) | 
					
						
							|  |  |  |     profileStr = '' | 
					
						
							|  |  |  |     maxItems = 4 | 
					
						
							|  |  |  |     ctr = 0 | 
					
						
							|  |  |  |     currPage = 1 | 
					
						
							| 
									
										
										
										
											2020-11-27 12:29:20 +00:00
										 |  |  |     boxName = 'outbox' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     while ctr < maxItems and currPage < 4: | 
					
						
							| 
									
										
										
										
											2020-12-22 21:24:46 +00:00
										 |  |  |         outboxFeedPathStr = \ | 
					
						
							|  |  |  |             '/users/' + nickname + '/' + boxName + '?page=' + \ | 
					
						
							|  |  |  |             str(currPage) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         outboxFeed = \ | 
					
						
							|  |  |  |             personBoxJson({}, session, baseDir, domain, | 
					
						
							|  |  |  |                           port, | 
					
						
							| 
									
										
										
										
											2020-12-22 21:24:46 +00:00
										 |  |  |                           outboxFeedPathStr, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                           httpPrefix, | 
					
						
							| 
									
										
										
										
											2020-11-27 12:29:20 +00:00
										 |  |  |                           10, boxName, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                           authorized, 0, False, 0) | 
					
						
							|  |  |  |         if not outboxFeed: | 
					
						
							| 
									
										
										
										
											2020-11-27 16:14:54 +00:00
										 |  |  |             break | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         if len(outboxFeed['orderedItems']) == 0: | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |         for item in outboxFeed['orderedItems']: | 
					
						
							|  |  |  |             if item['type'] == 'Create': | 
					
						
							|  |  |  |                 postStr = \ | 
					
						
							|  |  |  |                     individualPostAsHtml(True, recentPostsCache, | 
					
						
							|  |  |  |                                          maxRecentPosts, | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                                          translate, None, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                                          baseDir, session, cachedWebfingers, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                                          personCache, | 
					
						
							|  |  |  |                                          nickname, domain, port, item, | 
					
						
							|  |  |  |                                          None, True, False, | 
					
						
							|  |  |  |                                          httpPrefix, projectVersion, 'inbox', | 
					
						
							|  |  |  |                                          YTReplacementDomain, | 
					
						
							|  |  |  |                                          showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                                          peertubeInstances, | 
					
						
							| 
									
										
										
										
											2021-01-30 11:47:09 +00:00
										 |  |  |                                          allowLocalNetworkAccess, | 
					
						
							| 
									
										
										
										
											2021-04-22 17:05:10 +00:00
										 |  |  |                                          themeName, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                                          False, False, False, True, False) | 
					
						
							|  |  |  |                 if postStr: | 
					
						
							| 
									
										
										
										
											2020-11-18 21:18:51 +00:00
										 |  |  |                     profileStr += postStr + separatorStr | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                     ctr += 1 | 
					
						
							|  |  |  |                     if ctr >= maxItems: | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |         currPage += 1 | 
					
						
							|  |  |  |     return profileStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _htmlProfileFollowing(translate: {}, baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                           authorized: bool, | 
					
						
							|  |  |  |                           nickname: str, domain: str, port: int, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                           session, cachedWebfingers: {}, personCache: {}, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                           followingJson: {}, projectVersion: str, | 
					
						
							|  |  |  |                           buttons: [], | 
					
						
							|  |  |  |                           feedName: str, actor: str, | 
					
						
							|  |  |  |                           pageNumber: int, | 
					
						
							|  |  |  |                           maxItemsPerPage: int, | 
					
						
							| 
									
										
										
										
											2021-03-14 19:22:58 +00:00
										 |  |  |                           dormantMonths: int, debug: bool) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Shows following on the profile screen
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     profileStr = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if authorized and pageNumber: | 
					
						
							|  |  |  |         if authorized and pageNumber > 1: | 
					
						
							|  |  |  |             # page up arrow | 
					
						
							|  |  |  |             profileStr += \ | 
					
						
							|  |  |  |                 '  <center>\n' + \ | 
					
						
							|  |  |  |                 '    <a href="' + actor + '/' + feedName + \ | 
					
						
							| 
									
										
										
										
											2020-11-24 14:49:07 +00:00
										 |  |  |                 '?page=' + str(pageNumber - 1) + '#buttonheader' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                 '"><img loading="lazy" class="pageicon" src="/' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |                 'icons/pageup.png" title="' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                 translate['Page up'] + '" alt="' + \ | 
					
						
							|  |  |  |                 translate['Page up'] + '"></a>\n' + \ | 
					
						
							|  |  |  |                 '  </center>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-13 12:44:17 +00:00
										 |  |  |     for followingActor in followingJson['orderedItems']: | 
					
						
							| 
									
										
										
										
											2020-12-13 12:48:04 +00:00
										 |  |  |         # is this a dormant followed account? | 
					
						
							| 
									
										
										
										
											2020-12-13 12:44:17 +00:00
										 |  |  |         dormant = False | 
					
						
							| 
									
										
										
										
											2020-12-13 12:45:29 +00:00
										 |  |  |         if authorized and feedName == 'following': | 
					
						
							| 
									
										
										
										
											2020-12-13 12:44:17 +00:00
										 |  |  |             dormant = \ | 
					
						
							|  |  |  |                 isDormant(baseDir, nickname, domain, followingActor, | 
					
						
							|  |  |  |                           dormantMonths) | 
					
						
							| 
									
										
										
										
											2020-12-13 12:48:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         profileStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _individualFollowAsHtml(translate, baseDir, session, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                                     cachedWebfingers, personCache, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                                     domain, followingActor, | 
					
						
							|  |  |  |                                     authorized, nickname, | 
					
						
							|  |  |  |                                     httpPrefix, projectVersion, dormant, | 
					
						
							| 
									
										
										
										
											2021-03-14 19:22:58 +00:00
										 |  |  |                                     debug, buttons) | 
					
						
							| 
									
										
										
										
											2020-12-13 12:48:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     if authorized and maxItemsPerPage and pageNumber: | 
					
						
							|  |  |  |         if len(followingJson['orderedItems']) >= maxItemsPerPage: | 
					
						
							|  |  |  |             # page down arrow | 
					
						
							|  |  |  |             profileStr += \ | 
					
						
							|  |  |  |                 '  <center>\n' + \ | 
					
						
							|  |  |  |                 '    <a href="' + actor + '/' + feedName + \ | 
					
						
							| 
									
										
										
										
											2020-11-24 14:49:07 +00:00
										 |  |  |                 '?page=' + str(pageNumber + 1) + '#buttonheader' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                 '"><img loading="lazy" class="pageicon" src="/' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |                 'icons/pagedown.png" title="' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                 translate['Page down'] + '" alt="' + \ | 
					
						
							|  |  |  |                 translate['Page down'] + '"></a>\n' + \ | 
					
						
							|  |  |  |                 '  </center>\n' | 
					
						
							|  |  |  |     return profileStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _htmlProfileRoles(translate: {}, nickname: str, domain: str, | 
					
						
							| 
									
										
										
										
											2021-05-13 19:58:16 +00:00
										 |  |  |                       rolesList: []) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Shows roles on the profile screen
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     profileStr = '' | 
					
						
							| 
									
										
										
										
											2021-05-13 19:58:16 +00:00
										 |  |  |     profileStr += \ | 
					
						
							|  |  |  |         '<div class="roles">\n<div class="roles-inner">\n' | 
					
						
							|  |  |  |     for role in rolesList: | 
					
						
							|  |  |  |         if translate.get(role): | 
					
						
							|  |  |  |             profileStr += '<h3>' + translate[role] + '</h3>\n' | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             profileStr += '<h3>' + role + '</h3>\n' | 
					
						
							|  |  |  |     profileStr += '</div></div>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     if len(profileStr) == 0: | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							|  |  |  |             '<p>@' + nickname + '@' + domain + ' has no roles assigned</p>\n' | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         profileStr = '<div>' + profileStr + '</div>\n' | 
					
						
							|  |  |  |     return profileStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _htmlProfileSkills(translate: {}, nickname: str, domain: str, | 
					
						
							|  |  |  |                        skillsJson: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Shows skills on the profile screen
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     profileStr = '' | 
					
						
							|  |  |  |     for skill, level in skillsJson.items(): | 
					
						
							|  |  |  |         profileStr += \ | 
					
						
							|  |  |  |             '<div>' + skill + \ | 
					
						
							|  |  |  |             '<br><div id="myProgress"><div id="myBar" style="width:' + \ | 
					
						
							|  |  |  |             str(level) + '%"></div></div></div>\n<br>\n' | 
					
						
							|  |  |  |     if len(profileStr) > 0: | 
					
						
							|  |  |  |         profileStr = '<center><div class="skill-title">' + \ | 
					
						
							|  |  |  |             profileStr + '</div></center>\n' | 
					
						
							|  |  |  |     return profileStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _htmlProfileShares(actor: str, translate: {}, | 
					
						
							|  |  |  |                        nickname: str, domain: str, sharesJson: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Shows shares on the profile screen
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     profileStr = '' | 
					
						
							|  |  |  |     for item in sharesJson['orderedItems']: | 
					
						
							|  |  |  |         profileStr += htmlIndividualShare(actor, item, translate, False, False) | 
					
						
							|  |  |  |     if len(profileStr) > 0: | 
					
						
							|  |  |  |         profileStr = '<div class="share-title">' + profileStr + '</div>\n' | 
					
						
							|  |  |  |     return profileStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, | 
					
						
							|  |  |  |                     domain: str, port: int, httpPrefix: str, | 
					
						
							| 
									
										
										
										
											2020-12-24 11:42:23 +00:00
										 |  |  |                     defaultTimeline: str, theme: str, | 
					
						
							| 
									
										
										
										
											2021-02-05 19:14:27 +00:00
										 |  |  |                     peertubeInstances: [], | 
					
						
							| 
									
										
										
										
											2021-05-30 14:27:26 +00:00
										 |  |  |                     textModeBanner: str, city: str, | 
					
						
							|  |  |  |                     accessKeys: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Shows the edit profile screen
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-11-21 11:21:05 +00:00
										 |  |  |     imageFormats = getImageFormats() | 
					
						
							| 
									
										
										
										
											2021-05-17 21:25:17 +00:00
										 |  |  |     themeFormats = '.zip, .gz' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     path = path.replace('/inbox', '').replace('/outbox', '') | 
					
						
							|  |  |  |     path = path.replace('/shares', '') | 
					
						
							|  |  |  |     nickname = getNicknameFromActor(path) | 
					
						
							|  |  |  |     if not nickname: | 
					
						
							|  |  |  |         return '' | 
					
						
							| 
									
										
										
										
											2020-12-16 11:19:16 +00:00
										 |  |  |     domainFull = getFullDomain(domain, port) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     actorFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + nickname + '@' + domain + '.json' | 
					
						
							|  |  |  |     if not os.path.isfile(actorFilename): | 
					
						
							|  |  |  |         return '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # filename of the banner shown at the top | 
					
						
							| 
									
										
										
										
											2020-12-20 18:16:53 +00:00
										 |  |  |     bannerFile, bannerFilename = \ | 
					
						
							|  |  |  |         getBannerFile(baseDir, nickname, domain, theme) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     isBot = '' | 
					
						
							|  |  |  |     isGroup = '' | 
					
						
							|  |  |  |     followDMs = '' | 
					
						
							|  |  |  |     removeTwitter = '' | 
					
						
							|  |  |  |     notifyLikes = '' | 
					
						
							|  |  |  |     hideLikeButton = '' | 
					
						
							|  |  |  |     mediaInstanceStr = '' | 
					
						
							|  |  |  |     blogsInstanceStr = '' | 
					
						
							|  |  |  |     newsInstanceStr = '' | 
					
						
							|  |  |  |     displayNickname = nickname | 
					
						
							|  |  |  |     bioStr = '' | 
					
						
							|  |  |  |     donateUrl = '' | 
					
						
							|  |  |  |     emailAddress = '' | 
					
						
							|  |  |  |     PGPpubKey = '' | 
					
						
							|  |  |  |     PGPfingerprint = '' | 
					
						
							|  |  |  |     xmppAddress = '' | 
					
						
							|  |  |  |     matrixAddress = '' | 
					
						
							|  |  |  |     ssbAddress = '' | 
					
						
							|  |  |  |     blogAddress = '' | 
					
						
							|  |  |  |     toxAddress = '' | 
					
						
							| 
									
										
										
										
											2020-12-24 16:48:03 +00:00
										 |  |  |     briarAddress = '' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     manuallyApprovesFollowers = '' | 
					
						
							| 
									
										
										
										
											2021-01-12 12:35:30 +00:00
										 |  |  |     movedTo = '' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     actorJson = loadJson(actorFilename) | 
					
						
							|  |  |  |     if actorJson: | 
					
						
							| 
									
										
										
										
											2021-01-12 12:35:30 +00:00
										 |  |  |         if actorJson.get('movedTo'): | 
					
						
							|  |  |  |             movedTo = actorJson['movedTo'] | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         donateUrl = getDonationUrl(actorJson) | 
					
						
							|  |  |  |         xmppAddress = getXmppAddress(actorJson) | 
					
						
							|  |  |  |         matrixAddress = getMatrixAddress(actorJson) | 
					
						
							|  |  |  |         ssbAddress = getSSBAddress(actorJson) | 
					
						
							|  |  |  |         blogAddress = getBlogAddress(actorJson) | 
					
						
							|  |  |  |         toxAddress = getToxAddress(actorJson) | 
					
						
							| 
									
										
										
										
											2020-12-24 16:48:03 +00:00
										 |  |  |         briarAddress = getBriarAddress(actorJson) | 
					
						
							| 
									
										
										
										
											2020-11-29 12:50:41 +00:00
										 |  |  |         jamiAddress = getJamiAddress(actorJson) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         emailAddress = getEmailAddress(actorJson) | 
					
						
							|  |  |  |         PGPpubKey = getPGPpubKey(actorJson) | 
					
						
							|  |  |  |         PGPfingerprint = getPGPfingerprint(actorJson) | 
					
						
							|  |  |  |         if actorJson.get('name'): | 
					
						
							| 
									
										
										
										
											2020-12-19 12:55:40 +00:00
										 |  |  |             if not isFiltered(baseDir, nickname, domain, actorJson['name']): | 
					
						
							|  |  |  |                 displayNickname = actorJson['name'] | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         if actorJson.get('summary'): | 
					
						
							|  |  |  |             bioStr = \ | 
					
						
							|  |  |  |                 actorJson['summary'].replace('<p>', '').replace('</p>', '') | 
					
						
							| 
									
										
										
										
											2020-12-19 12:51:13 +00:00
										 |  |  |             if isFiltered(baseDir, nickname, domain, bioStr): | 
					
						
							|  |  |  |                 bioStr = '' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         if actorJson.get('manuallyApprovesFollowers'): | 
					
						
							|  |  |  |             if actorJson['manuallyApprovesFollowers']: | 
					
						
							|  |  |  |                 manuallyApprovesFollowers = 'checked' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 manuallyApprovesFollowers = '' | 
					
						
							|  |  |  |         if actorJson.get('type'): | 
					
						
							|  |  |  |             if actorJson['type'] == 'Service': | 
					
						
							|  |  |  |                 isBot = 'checked' | 
					
						
							|  |  |  |                 isGroup = '' | 
					
						
							|  |  |  |             elif actorJson['type'] == 'Group': | 
					
						
							|  |  |  |                 isGroup = 'checked' | 
					
						
							|  |  |  |                 isBot = '' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/accounts/' + | 
					
						
							|  |  |  |                       nickname + '@' + domain + '/.followDMs'): | 
					
						
							|  |  |  |         followDMs = 'checked' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/accounts/' + | 
					
						
							|  |  |  |                       nickname + '@' + domain + '/.removeTwitter'): | 
					
						
							|  |  |  |         removeTwitter = 'checked' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/accounts/' + | 
					
						
							|  |  |  |                       nickname + '@' + domain + '/.notifyLikes'): | 
					
						
							|  |  |  |         notifyLikes = 'checked' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/accounts/' + | 
					
						
							|  |  |  |                       nickname + '@' + domain + '/.hideLikeButton'): | 
					
						
							|  |  |  |         hideLikeButton = 'checked' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mediaInstance = getConfigParam(baseDir, "mediaInstance") | 
					
						
							|  |  |  |     if mediaInstance: | 
					
						
							|  |  |  |         if mediaInstance is True: | 
					
						
							|  |  |  |             mediaInstanceStr = 'checked' | 
					
						
							|  |  |  |             blogsInstanceStr = '' | 
					
						
							|  |  |  |             newsInstanceStr = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     newsInstance = getConfigParam(baseDir, "newsInstance") | 
					
						
							|  |  |  |     if newsInstance: | 
					
						
							|  |  |  |         if newsInstance is True: | 
					
						
							|  |  |  |             newsInstanceStr = 'checked' | 
					
						
							|  |  |  |             blogsInstanceStr = '' | 
					
						
							|  |  |  |             mediaInstanceStr = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     blogsInstance = getConfigParam(baseDir, "blogsInstance") | 
					
						
							|  |  |  |     if blogsInstance: | 
					
						
							|  |  |  |         if blogsInstance is True: | 
					
						
							|  |  |  |             blogsInstanceStr = 'checked' | 
					
						
							|  |  |  |             mediaInstanceStr = '' | 
					
						
							|  |  |  |             newsInstanceStr = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     filterStr = '' | 
					
						
							|  |  |  |     filterFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + nickname + '@' + domain + '/filters.txt' | 
					
						
							|  |  |  |     if os.path.isfile(filterFilename): | 
					
						
							|  |  |  |         with open(filterFilename, 'r') as filterfile: | 
					
						
							|  |  |  |             filterStr = filterfile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switchStr = '' | 
					
						
							|  |  |  |     switchFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |         nickname + '@' + domain + '/replacewords.txt' | 
					
						
							|  |  |  |     if os.path.isfile(switchFilename): | 
					
						
							|  |  |  |         with open(switchFilename, 'r') as switchfile: | 
					
						
							|  |  |  |             switchStr = switchfile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     autoTags = '' | 
					
						
							|  |  |  |     autoTagsFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |         nickname + '@' + domain + '/autotags.txt' | 
					
						
							|  |  |  |     if os.path.isfile(autoTagsFilename): | 
					
						
							|  |  |  |         with open(autoTagsFilename, 'r') as autoTagsFile: | 
					
						
							|  |  |  |             autoTags = autoTagsFile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     autoCW = '' | 
					
						
							|  |  |  |     autoCWFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |         nickname + '@' + domain + '/autocw.txt' | 
					
						
							|  |  |  |     if os.path.isfile(autoCWFilename): | 
					
						
							|  |  |  |         with open(autoCWFilename, 'r') as autoCWFile: | 
					
						
							|  |  |  |             autoCW = autoCWFile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     blockedStr = '' | 
					
						
							|  |  |  |     blockedFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |         nickname + '@' + domain + '/blocking.txt' | 
					
						
							|  |  |  |     if os.path.isfile(blockedFilename): | 
					
						
							|  |  |  |         with open(blockedFilename, 'r') as blockedfile: | 
					
						
							|  |  |  |             blockedStr = blockedfile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-22 09:56:40 +00:00
										 |  |  |     dmAllowedInstancesStr = '' | 
					
						
							|  |  |  |     dmAllowedInstancesFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |         nickname + '@' + domain + '/dmAllowedInstances.txt' | 
					
						
							|  |  |  |     if os.path.isfile(dmAllowedInstancesFilename): | 
					
						
							|  |  |  |         with open(dmAllowedInstancesFilename, 'r') as dmAllowedInstancesFile: | 
					
						
							|  |  |  |             dmAllowedInstancesStr = dmAllowedInstancesFile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     allowedInstancesStr = '' | 
					
						
							|  |  |  |     allowedInstancesFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |         nickname + '@' + domain + '/allowedinstances.txt' | 
					
						
							|  |  |  |     if os.path.isfile(allowedInstancesFilename): | 
					
						
							|  |  |  |         with open(allowedInstancesFilename, 'r') as allowedInstancesFile: | 
					
						
							|  |  |  |             allowedInstancesStr = allowedInstancesFile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gitProjectsStr = '' | 
					
						
							|  |  |  |     gitProjectsFilename = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |         nickname + '@' + domain + '/gitprojects.txt' | 
					
						
							|  |  |  |     if os.path.isfile(gitProjectsFilename): | 
					
						
							|  |  |  |         with open(gitProjectsFilename, 'r') as gitProjectsFile: | 
					
						
							|  |  |  |             gitProjectsStr = gitProjectsFile.read() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     skills = getSkills(baseDir, nickname, domain) | 
					
						
							|  |  |  |     skillsStr = '' | 
					
						
							|  |  |  |     skillCtr = 1 | 
					
						
							|  |  |  |     if skills: | 
					
						
							|  |  |  |         for skillDesc, skillValue in skills.items(): | 
					
						
							| 
									
										
										
										
											2020-12-19 10:32:48 +00:00
										 |  |  |             if isFiltered(baseDir, nickname, domain, skillDesc): | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             skillsStr += \ | 
					
						
							|  |  |  |                 '<p><input type="text" placeholder="' + translate['Skill'] + \ | 
					
						
							|  |  |  |                 ' ' + str(skillCtr) + '" name="skillName' + str(skillCtr) + \ | 
					
						
							|  |  |  |                 '" value="' + skillDesc + '" style="width:40%">' | 
					
						
							|  |  |  |             skillsStr += \ | 
					
						
							|  |  |  |                 '<input type="range" min="1" max="100" ' + \ | 
					
						
							|  |  |  |                 'class="slider" name="skillValue' + \ | 
					
						
							|  |  |  |                 str(skillCtr) + '" value="' + str(skillValue) + '"></p>' | 
					
						
							|  |  |  |             skillCtr += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     skillsStr += \ | 
					
						
							|  |  |  |         '<p><input type="text" placeholder="Skill ' + str(skillCtr) + \ | 
					
						
							|  |  |  |         '" name="skillName' + str(skillCtr) + \ | 
					
						
							|  |  |  |         '" value="" style="width:40%">' | 
					
						
							|  |  |  |     skillsStr += \ | 
					
						
							|  |  |  |         '<input type="range" min="1" max="100" ' + \ | 
					
						
							|  |  |  |         'class="slider" name="skillValue' + \ | 
					
						
							|  |  |  |         str(skillCtr) + '" value="50"></p>' | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     skillsStr += '    </div></details>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cssFilename = baseDir + '/epicyon-profile.css' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/epicyon.css'): | 
					
						
							|  |  |  |         cssFilename = baseDir + '/epicyon.css' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     themesDropdown = '' | 
					
						
							|  |  |  |     instanceStr = '' | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |     roleAssignStr = '' | 
					
						
							| 
									
										
										
										
											2020-12-24 11:56:17 +00:00
										 |  |  |     peertubeStr = '' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     adminNickname = getConfigParam(baseDir, 'admin') | 
					
						
							| 
									
										
										
										
											2021-05-17 17:52:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if isArtist(baseDir, nickname) or \ | 
					
						
							|  |  |  |        path.startswith('/users/' + str(adminNickname) + '/'): | 
					
						
							|  |  |  |         graphicsStr = '<details><summary class="cw">' + \ | 
					
						
							|  |  |  |             translate['Graphic Design'] + '</summary>\n' | 
					
						
							|  |  |  |         graphicsStr += '<div class="container">' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Themes section | 
					
						
							|  |  |  |         themes = getThemesList(baseDir) | 
					
						
							| 
									
										
										
										
											2021-05-17 17:57:37 +00:00
										 |  |  |         themesDropdown += '  <label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2021-05-17 17:52:33 +00:00
										 |  |  |             translate['Theme'] + '</label><br>\n' | 
					
						
							|  |  |  |         grayscaleFilename = \ | 
					
						
							|  |  |  |             baseDir + '/accounts/.grayscale' | 
					
						
							|  |  |  |         grayscale = '' | 
					
						
							|  |  |  |         if os.path.isfile(grayscaleFilename): | 
					
						
							|  |  |  |             grayscale = 'checked' | 
					
						
							|  |  |  |         themesDropdown += \ | 
					
						
							|  |  |  |             '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |             'name="grayscale" ' + grayscale + \ | 
					
						
							|  |  |  |             '> ' + translate['Grayscale'] + '<br>' | 
					
						
							|  |  |  |         themesDropdown += '  <select id="themeDropdown" ' + \ | 
					
						
							|  |  |  |             'name="themeDropdown" class="theme">' | 
					
						
							|  |  |  |         for themeName in themes: | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |             translatedThemeName = themeName | 
					
						
							|  |  |  |             if translate.get(themeName): | 
					
						
							|  |  |  |                 translatedThemeName = translate[themeName] | 
					
						
							| 
									
										
										
										
											2021-05-17 17:52:33 +00:00
										 |  |  |             themesDropdown += '    <option value="' + \ | 
					
						
							|  |  |  |                 themeName.lower() + '">' + \ | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |                 translatedThemeName + '</option>' | 
					
						
							| 
									
										
										
										
											2021-05-17 17:52:33 +00:00
										 |  |  |         themesDropdown += '  </select><br>' | 
					
						
							|  |  |  |         if os.path.isfile(baseDir + '/fonts/custom.woff') or \ | 
					
						
							|  |  |  |            os.path.isfile(baseDir + '/fonts/custom.woff2') or \ | 
					
						
							|  |  |  |            os.path.isfile(baseDir + '/fonts/custom.otf') or \ | 
					
						
							|  |  |  |            os.path.isfile(baseDir + '/fonts/custom.ttf'): | 
					
						
							|  |  |  |             themesDropdown += \ | 
					
						
							|  |  |  |                 '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                 'name="removeCustomFont"> ' + \ | 
					
						
							|  |  |  |                 translate['Remove the custom font'] + '<br>' | 
					
						
							|  |  |  |         themeName = getConfigParam(baseDir, 'theme') | 
					
						
							|  |  |  |         themesDropdown = \ | 
					
						
							|  |  |  |             themesDropdown.replace('<option value="' + themeName + '">', | 
					
						
							|  |  |  |                                    '<option value="' + themeName + | 
					
						
							|  |  |  |                                    '" selected>') | 
					
						
							|  |  |  |         graphicsStr += themesDropdown | 
					
						
							| 
									
										
										
										
											2021-05-17 21:25:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         graphicsStr += \ | 
					
						
							|  |  |  |             '      <label class="labels">' + \ | 
					
						
							|  |  |  |             translate['Import Theme'] + '</label>\n' | 
					
						
							|  |  |  |         graphicsStr += '      <input type="file" id="importTheme" ' | 
					
						
							| 
									
										
										
										
											2021-05-29 11:04:03 +00:00
										 |  |  |         graphicsStr += 'name="submitImportTheme" ' | 
					
						
							| 
									
										
										
										
											2021-05-17 21:25:17 +00:00
										 |  |  |         graphicsStr += 'accept="' + themeFormats + '">\n' | 
					
						
							| 
									
										
										
										
											2021-05-17 21:27:27 +00:00
										 |  |  |         graphicsStr += \ | 
					
						
							|  |  |  |             '      <label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2021-05-17 21:32:45 +00:00
										 |  |  |             translate['Export Theme'] + '</label><br>\n' | 
					
						
							| 
									
										
										
										
											2021-05-17 21:25:17 +00:00
										 |  |  |         graphicsStr += \ | 
					
						
							|  |  |  |             '      <button type="submit" class="button" ' + \ | 
					
						
							| 
									
										
										
										
											2021-05-28 21:39:34 +00:00
										 |  |  |             'name="submitExportTheme">➤</button>\n' | 
					
						
							| 
									
										
										
										
											2021-05-17 21:25:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 17:52:33 +00:00
										 |  |  |         graphicsStr += '    </div></details>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     if adminNickname: | 
					
						
							|  |  |  |         if path.startswith('/users/' + adminNickname + '/'): | 
					
						
							| 
									
										
										
										
											2021-03-06 12:23:51 +00:00
										 |  |  |             # Instance details section | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             instanceDescription = \ | 
					
						
							|  |  |  |                 getConfigParam(baseDir, 'instanceDescription') | 
					
						
							| 
									
										
										
										
											2021-05-30 17:38:41 +00:00
										 |  |  |             customSubmitText = \ | 
					
						
							|  |  |  |                 getConfigParam(baseDir, 'customSubmitText') | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             instanceDescriptionShort = \ | 
					
						
							|  |  |  |                 getConfigParam(baseDir, 'instanceDescriptionShort') | 
					
						
							|  |  |  |             instanceTitle = \ | 
					
						
							|  |  |  |                 getConfigParam(baseDir, 'instanceTitle') | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             instanceStr = '<details><summary class="cw">' + \ | 
					
						
							|  |  |  |                 translate['Instance Settings'] + '</summary>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             instanceStr += '<div class="container">' | 
					
						
							|  |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '  <label class="labels">' + \ | 
					
						
							|  |  |  |                 translate['Instance Title'] + '</label>' | 
					
						
							|  |  |  |             if instanceTitle: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '  <input type="text" name="instanceTitle" value="' + \ | 
					
						
							|  |  |  |                     instanceTitle + '"><br>' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '  <input type="text" name="instanceTitle" value=""><br>' | 
					
						
							|  |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '  <label class="labels">' + \ | 
					
						
							|  |  |  |                 translate['Instance Short Description'] + '</label>' | 
					
						
							|  |  |  |             if instanceDescriptionShort: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '  <input type="text" ' + \ | 
					
						
							|  |  |  |                     'name="instanceDescriptionShort" value="' + \ | 
					
						
							|  |  |  |                     instanceDescriptionShort + '"><br>' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '  <input type="text" ' + \ | 
					
						
							|  |  |  |                     'name="instanceDescriptionShort" value=""><br>' | 
					
						
							|  |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '  <label class="labels">' + \ | 
					
						
							|  |  |  |                 translate['Instance Description'] + '</label>' | 
					
						
							|  |  |  |             if instanceDescription: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '  <textarea id="message" name="instanceDescription" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |                     'style="height:200px" spellcheck="true">' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                     instanceDescription + '</textarea>' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '  <textarea id="message" name="instanceDescription" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |                     'style="height:200px" spellcheck="true"></textarea>' | 
					
						
							| 
									
										
										
										
											2021-05-30 17:38:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '  <label class="labels">' + \ | 
					
						
							|  |  |  |                 translate['Custom post submit button text'] + '</label>' | 
					
						
							|  |  |  |             if customSubmitText: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '  <input type="text" ' + \ | 
					
						
							|  |  |  |                     'name="customSubmitText" value="' + \ | 
					
						
							|  |  |  |                     customSubmitText + '"><br>' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '  <input type="text" ' + \ | 
					
						
							|  |  |  |                     'name="customSubmitText" value=""><br>' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '  <label class="labels">' + \ | 
					
						
							|  |  |  |                 translate['Instance Logo'] + '</label>' | 
					
						
							|  |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '  <input type="file" id="instanceLogo" name="instanceLogo"' | 
					
						
							| 
									
										
										
										
											2021-03-06 13:35:42 +00:00
										 |  |  |             instanceStr += '      accept="' + imageFormats + '"><br>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 13:55:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 13:33:25 +00:00
										 |  |  |             instanceStr += \ | 
					
						
							| 
									
										
										
										
											2021-03-06 13:34:25 +00:00
										 |  |  |                 '  <br><label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2021-03-06 13:33:25 +00:00
										 |  |  |                 translate['Security'] + '</label><br>\n' | 
					
						
							| 
									
										
										
										
											2021-05-03 10:59:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             nodeInfoStr = \ | 
					
						
							|  |  |  |                 translate['Show numbers of accounts within instance metadata'] | 
					
						
							|  |  |  |             if getConfigParam(baseDir, "showNodeInfoAccounts"): | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                     'name="showNodeInfoAccounts" checked> ' + \ | 
					
						
							|  |  |  |                     nodeInfoStr + '<br>\n' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                     'name="showNodeInfoAccounts"> ' + \ | 
					
						
							|  |  |  |                     nodeInfoStr + '<br>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             nodeInfoStr = \ | 
					
						
							|  |  |  |                 translate['Show version number within instance metadata'] | 
					
						
							|  |  |  |             if getConfigParam(baseDir, "showNodeInfoVersion"): | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                     'name="showNodeInfoVersion" checked> ' + \ | 
					
						
							|  |  |  |                     nodeInfoStr + '<br>\n' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                     'name="showNodeInfoVersion"> ' + \ | 
					
						
							|  |  |  |                     nodeInfoStr + '<br>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-05 10:52:37 +00:00
										 |  |  |             if getConfigParam(baseDir, "verifyAllSignatures"): | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                     'name="verifyallsignatures" checked> ' + \ | 
					
						
							|  |  |  |                     translate['Verify all signatures'] + '<br>\n' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                     'name="verifyallsignatures"> ' + \ | 
					
						
							|  |  |  |                     translate['Verify all signatures'] + '<br>\n' | 
					
						
							| 
									
										
										
										
											2021-05-03 10:59:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 13:33:25 +00:00
										 |  |  |             instanceStr += translate['Enabling broch mode'] + '<br>\n' | 
					
						
							| 
									
										
										
										
											2021-02-15 22:06:53 +00:00
										 |  |  |             if getConfigParam(baseDir, "brochMode"): | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                     'name="brochMode" checked> ' + \ | 
					
						
							|  |  |  |                     translate['Broch mode'] + '<br>\n' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 instanceStr += \ | 
					
						
							|  |  |  |                     '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                     'name="brochMode"> ' + \ | 
					
						
							|  |  |  |                     translate['Broch mode'] + '<br>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 12:28:32 +00:00
										 |  |  |             # Instance type | 
					
						
							| 
									
										
										
										
											2021-03-06 12:59:14 +00:00
										 |  |  |             instanceStr += \ | 
					
						
							| 
									
										
										
										
											2021-03-06 13:34:25 +00:00
										 |  |  |                 '  <br><label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:59:14 +00:00
										 |  |  |                 translate['Type of instance'] + '</label><br>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 12:28:32 +00:00
										 |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                 'name="mediaInstance" ' + mediaInstanceStr + '> ' + \ | 
					
						
							|  |  |  |                 translate['This is a media instance'] + '<br>\n' | 
					
						
							|  |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                 'name="blogsInstance" ' + blogsInstanceStr + '> ' + \ | 
					
						
							|  |  |  |                 translate['This is a blogging instance'] + '<br>\n' | 
					
						
							|  |  |  |             instanceStr += \ | 
					
						
							|  |  |  |                 '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |                 'name="newsInstance" ' + newsInstanceStr + '> ' + \ | 
					
						
							|  |  |  |                 translate['This is a news instance'] + '<br>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |             instanceStr += '    </div></details>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             # Role assignments section | 
					
						
							| 
									
										
										
										
											2021-03-06 12:08:17 +00:00
										 |  |  |             moderators = '' | 
					
						
							|  |  |  |             moderatorsFile = baseDir + '/accounts/moderators.txt' | 
					
						
							|  |  |  |             if os.path.isfile(moderatorsFile): | 
					
						
							|  |  |  |                 with open(moderatorsFile, "r") as f: | 
					
						
							|  |  |  |                     moderators = f.read() | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             # site moderators | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |             roleAssignStr = '<details><summary class="cw">' + \ | 
					
						
							|  |  |  |                 translate['Role Assignment'] + '</summary>\n' | 
					
						
							|  |  |  |             roleAssignStr += '<div class="container">' | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             roleAssignStr += '  <b><label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:23:51 +00:00
										 |  |  |                 translate['Moderators'] + '</label></b><br>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             roleAssignStr += '  ' + \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:08:17 +00:00
										 |  |  |                 translate['A list of moderator nicknames. One per line.'] | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             roleAssignStr += \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:08:17 +00:00
										 |  |  |                 '  <textarea id="message" name="moderators" placeholder="' + \ | 
					
						
							|  |  |  |                 translate['List of moderator nicknames'] + \ | 
					
						
							|  |  |  |                 '..." style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |                 moderators + '</textarea>' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             # site editors | 
					
						
							| 
									
										
										
										
											2021-03-06 12:08:17 +00:00
										 |  |  |             editors = '' | 
					
						
							|  |  |  |             editorsFile = baseDir + '/accounts/editors.txt' | 
					
						
							|  |  |  |             if os.path.isfile(editorsFile): | 
					
						
							|  |  |  |                 with open(editorsFile, "r") as f: | 
					
						
							|  |  |  |                     editors = f.read() | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             roleAssignStr += '  <b><label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:23:51 +00:00
										 |  |  |                 translate['Site Editors'] + '</label></b><br>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             roleAssignStr += '  ' + \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:08:17 +00:00
										 |  |  |                 translate['A list of editor nicknames. One per line.'] | 
					
						
							| 
									
										
										
										
											2021-03-06 13:40:47 +00:00
										 |  |  |             roleAssignStr += \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:08:17 +00:00
										 |  |  |                 '  <textarea id="message" name="editors" placeholder="" ' + \ | 
					
						
							|  |  |  |                 'style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |                 editors + '</textarea>' | 
					
						
							| 
									
										
										
										
											2021-03-08 23:03:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # counselors | 
					
						
							|  |  |  |             counselors = '' | 
					
						
							|  |  |  |             counselorsFile = baseDir + '/accounts/counselors.txt' | 
					
						
							|  |  |  |             if os.path.isfile(counselorsFile): | 
					
						
							|  |  |  |                 with open(counselorsFile, "r") as f: | 
					
						
							|  |  |  |                     counselors = f.read() | 
					
						
							|  |  |  |             roleAssignStr += '  <b><label class="labels">' + \ | 
					
						
							|  |  |  |                 translate['Counselors'] + '</label></b><br>\n' | 
					
						
							|  |  |  |             roleAssignStr += \ | 
					
						
							|  |  |  |                 '  <textarea id="message" name="counselors" ' + \ | 
					
						
							|  |  |  |                 'placeholder="" ' + \ | 
					
						
							|  |  |  |                 'style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |                 counselors + '</textarea>' | 
					
						
							| 
									
										
										
										
											2021-03-06 12:08:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 16:13:56 +00:00
										 |  |  |             # artists | 
					
						
							|  |  |  |             artists = '' | 
					
						
							|  |  |  |             artistsFile = baseDir + '/accounts/artists.txt' | 
					
						
							|  |  |  |             if os.path.isfile(artistsFile): | 
					
						
							|  |  |  |                 with open(artistsFile, "r") as f: | 
					
						
							|  |  |  |                     artists = f.read() | 
					
						
							|  |  |  |             roleAssignStr += '  <b><label class="labels">' + \ | 
					
						
							|  |  |  |                 translate['Artists'] + '</label></b><br>\n' | 
					
						
							|  |  |  |             roleAssignStr += \ | 
					
						
							|  |  |  |                 '  <textarea id="message" name="artists" ' + \ | 
					
						
							|  |  |  |                 'placeholder="" ' + \ | 
					
						
							|  |  |  |                 'style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |                 artists + '</textarea>' | 
					
						
							|  |  |  |             roleAssignStr += '    </div></details>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 13:33:25 +00:00
										 |  |  |             # Video section | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |             peertubeStr = '    <details><summary class="cw">' + \ | 
					
						
							|  |  |  |                 translate['Video Settings'] + '</summary>\n' | 
					
						
							|  |  |  |             peertubeStr += '    <div class="container">\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 12:08:17 +00:00
										 |  |  |             peertubeStr += \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:09:59 +00:00
										 |  |  |                 '      <b><label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2020-12-24 11:56:17 +00:00
										 |  |  |                 translate['Peertube Instances'] + '</label></b>\n' | 
					
						
							|  |  |  |             idx = 'Show video previews for the following Peertube sites.' | 
					
						
							|  |  |  |             peertubeStr += \ | 
					
						
							|  |  |  |                 '      <br><label class="labels">' + \ | 
					
						
							|  |  |  |                 translate[idx] + '</label>\n' | 
					
						
							|  |  |  |             peertubeInstancesStr = '' | 
					
						
							|  |  |  |             for url in peertubeInstances: | 
					
						
							|  |  |  |                 peertubeInstancesStr += url + '\n' | 
					
						
							|  |  |  |             peertubeStr += \ | 
					
						
							|  |  |  |                 '      <textarea id="message" name="ptInstances" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |                 'style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |                 peertubeInstancesStr + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 13:04:28 +00:00
										 |  |  |             peertubeStr += \ | 
					
						
							|  |  |  |                 '      <br><b><label class="labels">' + \ | 
					
						
							|  |  |  |                 translate['YouTube Replacement Domain'] + '</label></b>\n' | 
					
						
							|  |  |  |             YTReplacementDomain = getConfigParam(baseDir, "youtubedomain") | 
					
						
							|  |  |  |             if not YTReplacementDomain: | 
					
						
							|  |  |  |                 YTReplacementDomain = '' | 
					
						
							|  |  |  |             peertubeStr += \ | 
					
						
							|  |  |  |                 '      <input type="text" name="ytdomain" value="' + \ | 
					
						
							|  |  |  |                 YTReplacementDomain + '">\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |             peertubeStr += '    </div></details>\n' | 
					
						
							| 
									
										
										
										
											2020-12-24 11:56:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 19:46:21 +00:00
										 |  |  |     instanceTitle = \ | 
					
						
							|  |  |  |         getConfigParam(baseDir, 'instanceTitle') | 
					
						
							|  |  |  |     editProfileForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-05 15:24:46 +00:00
										 |  |  |     # keyboard navigation | 
					
						
							| 
									
										
										
										
											2021-02-05 17:05:53 +00:00
										 |  |  |     userPathStr = '/users/' + nickname | 
					
						
							|  |  |  |     userTimalineStr = '/users/' + nickname + '/' + defaultTimeline | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuTimeline = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('🏠') + ' ' + \ | 
					
						
							|  |  |  |         translate['Switch to timeline view'] | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |     menuProfile = \ | 
					
						
							| 
									
										
										
										
											2021-02-06 10:46:03 +00:00
										 |  |  |         htmlHideFromScreenReader('👤') + ' ' + \ | 
					
						
							|  |  |  |         translate['Switch to profile view'] | 
					
						
							| 
									
										
										
										
											2021-02-05 17:05:53 +00:00
										 |  |  |     navLinks = { | 
					
						
							| 
									
										
										
										
											2021-02-06 10:35:47 +00:00
										 |  |  |         menuProfile: userPathStr, | 
					
						
							|  |  |  |         menuTimeline: userTimalineStr | 
					
						
							| 
									
										
										
										
											2021-02-05 17:05:53 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-22 11:51:19 +00:00
										 |  |  |     navAccessKeys = { | 
					
						
							|  |  |  |         menuProfile: 'p', | 
					
						
							|  |  |  |         menuTimeline: 't' | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     editProfileForm += htmlKeyboardNavigation(textModeBanner, | 
					
						
							|  |  |  |                                               navLinks, navAccessKeys) | 
					
						
							| 
									
										
										
										
											2021-02-05 15:24:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # top banner | 
					
						
							| 
									
										
										
										
											2021-02-05 15:46:05 +00:00
										 |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '<a href="/users/' + nickname + '/' + defaultTimeline + '">' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '<img loading="lazy" class="timeline-banner" src="' + \ | 
					
						
							| 
									
										
										
										
											2021-02-05 15:24:46 +00:00
										 |  |  |         '/users/' + nickname + '/' + bannerFile + '" alt="" /></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '<form enctype="multipart/form-data" method="POST" ' + \ | 
					
						
							|  |  |  |         'accept-charset="UTF-8" action="' + path + '/profiledata">\n' | 
					
						
							|  |  |  |     editProfileForm += '  <div class="vertical-center">\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							| 
									
										
										
										
											2020-11-21 09:56:45 +00:00
										 |  |  |         '    <h1>' + translate['Profile for'] + \ | 
					
						
							|  |  |  |         ' ' + nickname + '@' + domainFull + '</h1>' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <center>\n' + \ | 
					
						
							| 
									
										
										
										
											2021-05-30 14:27:26 +00:00
										 |  |  |         '        <input type="submit" name="submitProfile" ' + \ | 
					
						
							|  |  |  |         'accesskey="' + accessKeys['submitButton'] + '" ' + \ | 
					
						
							|  |  |  |         'value="' + translate['Submit'] + '">\n' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         '      </center>\n' | 
					
						
							|  |  |  |     editProfileForm += '    </div>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if scheduledPostsExist(baseDir, nickname, domain): | 
					
						
							|  |  |  |         editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |         editProfileForm += \ | 
					
						
							|  |  |  |             '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |             'name="removeScheduledPosts"> ' + \ | 
					
						
							|  |  |  |             translate['Remove scheduled posts'] + '<br>\n' | 
					
						
							|  |  |  |         editProfileForm += '    </div>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |     editProfileForm += '      <label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Nickname'] + '</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="displayNickname" value="' + \ | 
					
						
							|  |  |  |         displayNickname + '"><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <label class="labels">' + translate['Your bio'] + '</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         '      <textarea id="message" name="bio" style="height:200px" ' + \ | 
					
						
							|  |  |  |         'spellcheck="true">' + bioStr + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <label class="labels">' + translate['Avatar image'] + \ | 
					
						
							|  |  |  |         '</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="file" id="avatar" name="avatar"' | 
					
						
							|  |  |  |     editProfileForm += '            accept="' + imageFormats + '">\n' | 
					
						
							| 
									
										
										
										
											2021-01-12 12:35:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-12 18:11:53 +00:00
										 |  |  |     occupationName = '' | 
					
						
							| 
									
										
										
										
											2021-05-13 11:35:36 +00:00
										 |  |  |     if actorJson.get('hasOccupation'): | 
					
						
							| 
									
										
										
										
											2021-05-16 15:10:39 +00:00
										 |  |  |         occupationName = getOccupationName(actorJson) | 
					
						
							| 
									
										
										
										
											2021-05-12 18:11:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += '<label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Occupation'] + ':</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" ' + \ | 
					
						
							|  |  |  |         'name="occupationName" value="' + occupationName + '">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-22 22:12:31 +00:00
										 |  |  |     alsoKnownAsStr = '' | 
					
						
							|  |  |  |     if actorJson.get('alsoKnownAs'): | 
					
						
							|  |  |  |         alsoKnownAs = actorJson['alsoKnownAs'] | 
					
						
							|  |  |  |         ctr = 0 | 
					
						
							|  |  |  |         for altActor in alsoKnownAs: | 
					
						
							|  |  |  |             if ctr > 0: | 
					
						
							|  |  |  |                 alsoKnownAsStr += ', ' | 
					
						
							|  |  |  |             ctr += 1 | 
					
						
							|  |  |  |             alsoKnownAsStr += altActor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += '<label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Other accounts'] + ':</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" placeholder="https://..." ' + \ | 
					
						
							| 
									
										
										
										
											2021-01-22 22:16:25 +00:00
										 |  |  |         'name="alsoKnownAs" value="' + alsoKnownAsStr + '">\n' | 
					
						
							| 
									
										
										
										
											2021-01-22 22:12:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-12 12:35:30 +00:00
										 |  |  |     editProfileForm += '<label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Moved to new account address'] + ':</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" placeholder="https://..." ' + \ | 
					
						
							|  |  |  |         'name="movedTo" value="' + movedTo + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '<label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Donations link'] + '</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" placeholder="https://..." ' + \ | 
					
						
							|  |  |  |         'name="donateUrl" value="' + donateUrl + '">\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:42:29 +00:00
										 |  |  |     editProfileForm += '<label class="labels">Blog</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="blogAddress" value="' + \ | 
					
						
							|  |  |  |         blogAddress + '">\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:55:09 +00:00
										 |  |  |     editProfileForm += '    </div>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:42:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 11:57:40 +00:00
										 |  |  |     # Option checkboxes | 
					
						
							|  |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |         'name="approveFollowers" ' + manuallyApprovesFollowers + \ | 
					
						
							|  |  |  |         '> ' + translate['Approve follower requests'] + '<br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="checkbox" ' + \ | 
					
						
							|  |  |  |         'class="profilecheckbox" name="isBot" ' + \ | 
					
						
							|  |  |  |         isBot + '> ' + translate['This is a bot account'] + '<br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="checkbox" ' + \ | 
					
						
							|  |  |  |         'class="profilecheckbox" name="isGroup" ' + isGroup + '> ' + \ | 
					
						
							|  |  |  |         translate['This is a group account'] + '<br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |         'name="followDMs" ' + followDMs + '> ' + \ | 
					
						
							|  |  |  |         translate['Only people I follow can send me DMs'] + '<br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |         'name="removeTwitter" ' + removeTwitter + '> ' + \ | 
					
						
							|  |  |  |         translate['Remove Twitter posts'] + '<br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |         'name="notifyLikes" ' + notifyLikes + '> ' + \ | 
					
						
							|  |  |  |         translate['Notify when posts are liked'] + '<br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="checkbox" class="profilecheckbox" ' + \ | 
					
						
							|  |  |  |         'name="hideLikeButton" ' + hideLikeButton + '> ' + \ | 
					
						
							|  |  |  |         translate["Don't show the Like button"] + '<br>\n' | 
					
						
							|  |  |  |     editProfileForm += '    </div>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 11:42:29 +00:00
										 |  |  |     # Contact information | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += '    <details><summary class="cw">' + \ | 
					
						
							|  |  |  |         translate['Contact Details'] + '</summary>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:44:28 +00:00
										 |  |  |     editProfileForm += '<div class="container">' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:42:29 +00:00
										 |  |  |     editProfileForm += '<label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Email'] + '</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="email" value="' + emailAddress + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '<label class="labels">' + translate['XMPP'] + '</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="xmppAddress" value="' + \ | 
					
						
							|  |  |  |         xmppAddress + '">\n' | 
					
						
							|  |  |  |     editProfileForm += '<label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Matrix'] + '</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="matrixAddress" value="' + \ | 
					
						
							|  |  |  |         matrixAddress+'">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += '<label class="labels">SSB</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="ssbAddress" value="' + \ | 
					
						
							|  |  |  |         ssbAddress + '">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += '<label class="labels">Tox</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="toxAddress" value="' + \ | 
					
						
							|  |  |  |         toxAddress + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-29 12:50:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-24 16:48:03 +00:00
										 |  |  |     editProfileForm += '<label class="labels">Briar</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="briarAddress" value="' + \ | 
					
						
							|  |  |  |         briarAddress + '">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-29 12:50:41 +00:00
										 |  |  |     editProfileForm += '<label class="labels">Jami</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="jamiAddress" value="' + \ | 
					
						
							|  |  |  |         jamiAddress + '">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '<label class="labels">' + \ | 
					
						
							|  |  |  |         translate['PGP Fingerprint'] + '</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="openpgp" value="' + \ | 
					
						
							|  |  |  |         PGPfingerprint + '">\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '<label class="labels">' + translate['PGP'] + '</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <textarea id="message" placeholder=' + \ | 
					
						
							|  |  |  |         '"-----BEGIN PGP PUBLIC KEY BLOCK-----" name="pgp" ' + \ | 
					
						
							| 
									
										
										
										
											2021-03-06 15:29:10 +00:00
										 |  |  |         'style="height:600px" spellcheck="false">' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         PGPpubKey + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '<a href="/users/' + nickname + \ | 
					
						
							|  |  |  |         '/followingaccounts"><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Following'] + '</label></a><br>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += '    </div></details>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:55:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Customize images and banners | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += '    <details><summary class="cw">' + \ | 
					
						
							|  |  |  |         translate['Background Images'] + '</summary>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |     idx = 'The files attached below should be no larger than ' + \ | 
					
						
							|  |  |  |         '10MB in total uploaded at once.' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <label class="labels">' + translate[idx] + '</label><br><br>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 14:35:15 +00:00
										 |  |  |     if not newsInstance: | 
					
						
							|  |  |  |         editProfileForm += \ | 
					
						
							| 
									
										
										
										
											2021-03-06 15:16:33 +00:00
										 |  |  |             '      <label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2020-12-21 14:35:15 +00:00
										 |  |  |             translate['Background image'] + '</label>\n' | 
					
						
							|  |  |  |         editProfileForm += '      <input type="file" id="image" name="image"' | 
					
						
							|  |  |  |         editProfileForm += '            accept="' + imageFormats + '">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         editProfileForm += '      <br><label class="labels">' + \ | 
					
						
							|  |  |  |             translate['Timeline banner image'] + '</label>\n' | 
					
						
							|  |  |  |         editProfileForm += '      <input type="file" id="banner" name="banner"' | 
					
						
							|  |  |  |         editProfileForm += '            accept="' + imageFormats + '">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         editProfileForm += '      <br><label class="labels">' + \ | 
					
						
							|  |  |  |             translate['Search banner image'] + '</label>\n' | 
					
						
							|  |  |  |         editProfileForm += '      <input type="file" id="search_banner" ' | 
					
						
							|  |  |  |         editProfileForm += 'name="search_banner"' | 
					
						
							|  |  |  |         editProfileForm += '            accept="' + imageFormats + '">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         editProfileForm += '      <br><label class="labels">' + \ | 
					
						
							|  |  |  |             translate['Left column image'] + '</label>\n' | 
					
						
							|  |  |  |         editProfileForm += '      <input type="file" id="left_col_image" ' | 
					
						
							|  |  |  |         editProfileForm += 'name="left_col_image"' | 
					
						
							|  |  |  |         editProfileForm += '            accept="' + imageFormats + '">\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         editProfileForm += '      <br><label class="labels">' + \ | 
					
						
							|  |  |  |             translate['Right column image'] + '</label>\n' | 
					
						
							|  |  |  |         editProfileForm += '      <input type="file" id="right_col_image" ' | 
					
						
							|  |  |  |         editProfileForm += 'name="right_col_image"' | 
					
						
							|  |  |  |         editProfileForm += '            accept="' + imageFormats + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += '    </div></details>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:55:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Change password | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += '    <details><summary class="cw">' + \ | 
					
						
							|  |  |  |         translate['Change Password'] + '</summary>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '<label class="labels">' + translate['Change Password'] + \ | 
					
						
							|  |  |  |         '</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += '      <input type="text" name="password" ' + \ | 
					
						
							|  |  |  |         'value=""><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '<label class="labels">' + translate['Confirm Password'] + \ | 
					
						
							|  |  |  |         '</label><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="text" name="passwordconfirm" value="">\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += '    </div></details>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 13:04:28 +00:00
										 |  |  |     # Filtering and blocking section | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += '<details><summary class="cw">' + \ | 
					
						
							|  |  |  |         translate['Filtering and Blocking'] + '</summary>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:42:29 +00:00
										 |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							| 
									
										
										
										
											2021-05-09 21:21:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '<label class="labels">' + \ | 
					
						
							|  |  |  |         translate['City for spoofed GPS image metadata'] + \ | 
					
						
							|  |  |  |         '</label><br>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cityFilename = baseDir + '/accounts/' + \ | 
					
						
							|  |  |  |         nickname + '@' + domain + '/city.txt' | 
					
						
							|  |  |  |     if os.path.isfile(cityFilename): | 
					
						
							|  |  |  |         with open(cityFilename, 'r') as fp: | 
					
						
							|  |  |  |             city = fp.read().replace('\n', '') | 
					
						
							|  |  |  |     locationsFilename = baseDir + '/custom_locations.txt' | 
					
						
							|  |  |  |     if not os.path.isfile(locationsFilename): | 
					
						
							|  |  |  |         locationsFilename = baseDir + '/locations.txt' | 
					
						
							|  |  |  |     cities = [] | 
					
						
							|  |  |  |     with open(locationsFilename, "r") as f: | 
					
						
							|  |  |  |         cities = f.readlines() | 
					
						
							| 
									
										
										
										
											2021-05-09 21:58:29 +00:00
										 |  |  |         cities.sort() | 
					
						
							| 
									
										
										
										
											2021-05-09 21:21:45 +00:00
										 |  |  |     editProfileForm += '  <select id="cityDropdown" ' + \ | 
					
						
							|  |  |  |         'name="cityDropdown" class="theme">\n' | 
					
						
							|  |  |  |     city = city.lower() | 
					
						
							|  |  |  |     for cityName in cities: | 
					
						
							|  |  |  |         if ':' not in cityName: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         citySelected = '' | 
					
						
							|  |  |  |         cityName = cityName.split(':')[0] | 
					
						
							|  |  |  |         cityName = cityName.lower() | 
					
						
							|  |  |  |         if city in cityName: | 
					
						
							|  |  |  |             citySelected = ' selected' | 
					
						
							|  |  |  |         editProfileForm += \ | 
					
						
							|  |  |  |             '    <option value="' + cityName + \ | 
					
						
							|  |  |  |             '"' + citySelected.title() + '>' + \ | 
					
						
							|  |  |  |             cityName + '</option>\n' | 
					
						
							|  |  |  |     editProfileForm += '  </select><br>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += \ | 
					
						
							| 
									
										
										
										
											2021-03-06 12:25:21 +00:00
										 |  |  |         '      <b><label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         translate['Filtered words'] + '</label></b>\n' | 
					
						
							|  |  |  |     editProfileForm += '      <br><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['One per line'] + '</label>\n' | 
					
						
							|  |  |  |     editProfileForm += '      <textarea id="message" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         'name="filteredWords" style="height:200px" spellcheck="false">' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         filterStr + '</textarea>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><b><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Word Replacements'] + '</label></b>\n' | 
					
						
							|  |  |  |     editProfileForm += '      <br><label class="labels">A -> B</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <textarea id="message" name="switchWords" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         'style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |         switchStr + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><b><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Autogenerated Hashtags'] + '</label></b>\n' | 
					
						
							|  |  |  |     editProfileForm += '      <br><label class="labels">A -> #B</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <textarea id="message" name="autoTags" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         'style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |         autoTags + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><b><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Autogenerated Content Warnings'] + '</label></b>\n' | 
					
						
							|  |  |  |     editProfileForm += '      <br><label class="labels">A -> B</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <textarea id="message" name="autoCW" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         'style="height:200px" spellcheck="true">' + autoCW + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><b><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Blocked accounts'] + '</label></b>\n' | 
					
						
							|  |  |  |     idx = 'Blocked accounts, one per line, in the form ' + \ | 
					
						
							|  |  |  |         'nickname@domain or *@blockeddomain' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><label class="labels">' + translate[idx] + '</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         '      <textarea id="message" name="blocked" style="height:200px" ' + \ | 
					
						
							|  |  |  |         'spellcheck="false">' + blockedStr + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-22 09:56:40 +00:00
										 |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><b><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Direct Message permitted instances'] + '</label></b>\n' | 
					
						
							|  |  |  |     idx = 'Direct messages are always allowed from these instances.' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><label class="labels">' + \ | 
					
						
							|  |  |  |         translate[idx] + '</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <textarea id="message" name="dmAllowedInstances" ' + \ | 
					
						
							|  |  |  |         'style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |         dmAllowedInstancesStr + '</textarea>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><b><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Federation list'] + '</label></b>\n' | 
					
						
							|  |  |  |     idx = 'Federate only with a defined set of instances. ' + \ | 
					
						
							|  |  |  |         'One domain name per line.' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <br><label class="labels">' + \ | 
					
						
							|  |  |  |         translate[idx] + '</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <textarea id="message" name="allowedInstances" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         'style="height:200px" spellcheck="false">' + \ | 
					
						
							|  |  |  |         allowedInstancesStr + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-03 10:03:03 +00:00
										 |  |  |     editProfileForm += '    </div></details>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += '<details><summary class="cw">' + \ | 
					
						
							|  |  |  |         translate['Git Projects'] + '</summary>\n' | 
					
						
							|  |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     idx = 'List of project names that you wish to receive git patches for' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							| 
									
										
										
										
											2021-04-03 10:53:34 +00:00
										 |  |  |         '      <label class="labels">' + \ | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         translate[idx] + '</label>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <textarea id="message" name="gitProjects" ' + \ | 
					
						
							| 
									
										
										
										
											2021-02-28 13:52:45 +00:00
										 |  |  |         'style="height:100px" spellcheck="false">' + \ | 
					
						
							|  |  |  |         gitProjectsStr + '</textarea>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 15:13:56 +00:00
										 |  |  |     editProfileForm += '    </div></details>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Skills section | 
					
						
							|  |  |  |     editProfileForm += '<details><summary class="cw">' + \ | 
					
						
							|  |  |  |         translate['Skills'] + '</summary>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <b><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Skills'] + '</label></b><br>\n' | 
					
						
							|  |  |  |     idx = 'If you want to participate within organizations then you ' + \ | 
					
						
							|  |  |  |         'can indicate some skills that you have and approximate ' + \ | 
					
						
							|  |  |  |         'proficiency levels. This helps organizers to construct ' + \ | 
					
						
							|  |  |  |         'teams with an appropriate combination of skills.' | 
					
						
							|  |  |  |     editProfileForm += '      <label class="labels">' + \ | 
					
						
							|  |  |  |         translate[idx] + '</label>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 11:42:29 +00:00
										 |  |  |     editProfileForm += skillsStr | 
					
						
							| 
									
										
										
										
											2021-05-17 17:52:33 +00:00
										 |  |  |     editProfileForm += roleAssignStr + peertubeStr + graphicsStr + instanceStr | 
					
						
							| 
									
										
										
										
											2021-03-06 15:18:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # danger zone section | 
					
						
							|  |  |  |     editProfileForm += '    <details><summary class="cw">' + \ | 
					
						
							| 
									
										
										
										
											2021-03-06 18:12:43 +00:00
										 |  |  |         translate['Danger Zone'] + '</summary>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |     editProfileForm += '      <b><label class="labels">' + \ | 
					
						
							|  |  |  |         translate['Danger Zone'] + '</label></b><br>\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <input type="checkbox" class=dangercheckbox" ' + \ | 
					
						
							|  |  |  |         'name="deactivateThisAccount"> ' + \ | 
					
						
							|  |  |  |         translate['Deactivate this account'] + '<br>\n' | 
					
						
							| 
									
										
										
										
											2021-03-06 15:18:56 +00:00
										 |  |  |     editProfileForm += '    </div></details>\n' | 
					
						
							| 
									
										
										
										
											2021-05-30 14:19:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     editProfileForm += '    <div class="container">\n' | 
					
						
							|  |  |  |     editProfileForm += \ | 
					
						
							|  |  |  |         '      <center>\n' + \ | 
					
						
							|  |  |  |         '        <input type="submit" name="submitProfile" value="' + \ | 
					
						
							|  |  |  |         translate['Submit'] + '">\n' + \ | 
					
						
							|  |  |  |         '      </center>\n' | 
					
						
							|  |  |  |     editProfileForm += '    </div>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     editProfileForm += '  </div>\n' | 
					
						
							|  |  |  |     editProfileForm += '</form>\n' | 
					
						
							|  |  |  |     editProfileForm += htmlFooter() | 
					
						
							|  |  |  |     return editProfileForm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _individualFollowAsHtml(translate: {}, | 
					
						
							| 
									
										
										
										
											2020-12-31 12:46:35 +00:00
										 |  |  |                             baseDir: str, session, | 
					
						
							|  |  |  |                             cachedWebfingers: {}, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                             personCache: {}, domain: str, | 
					
						
							|  |  |  |                             followUrl: str, | 
					
						
							|  |  |  |                             authorized: bool, | 
					
						
							|  |  |  |                             actorNickname: str, | 
					
						
							|  |  |  |                             httpPrefix: str, | 
					
						
							|  |  |  |                             projectVersion: str, | 
					
						
							|  |  |  |                             dormant: bool, | 
					
						
							| 
									
										
										
										
											2021-03-14 19:22:58 +00:00
										 |  |  |                             debug: bool, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                             buttons=[]) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """An individual follow entry on the profile screen
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-01-12 10:18:00 +00:00
										 |  |  |     followUrlNickname = getNicknameFromActor(followUrl) | 
					
						
							|  |  |  |     followUrlDomain, followUrlPort = getDomainFromActor(followUrl) | 
					
						
							|  |  |  |     followUrlDomainFull = getFullDomain(followUrlDomain, followUrlPort) | 
					
						
							|  |  |  |     titleStr = '@' + followUrlNickname + '@' + followUrlDomainFull | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     avatarUrl = getPersonAvatarUrl(baseDir, followUrl, personCache, True) | 
					
						
							|  |  |  |     if not avatarUrl: | 
					
						
							|  |  |  |         avatarUrl = followUrl + '/avatar.png' | 
					
						
							| 
									
										
										
										
											2021-01-12 10:18:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # lookup the correct webfinger for the followUrl | 
					
						
							|  |  |  |     followUrlHandle = followUrlNickname + '@' + followUrlDomainFull | 
					
						
							|  |  |  |     followUrlWf = \ | 
					
						
							|  |  |  |         webfingerHandle(session, followUrlHandle, httpPrefix, | 
					
						
							|  |  |  |                         cachedWebfingers, | 
					
						
							| 
									
										
										
										
											2021-03-14 19:22:58 +00:00
										 |  |  |                         domain, __version__, debug) | 
					
						
							| 
									
										
										
										
											2021-01-12 10:18:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     (inboxUrl, pubKeyId, pubKey, | 
					
						
							|  |  |  |      fromPersonId, sharedInbox, | 
					
						
							|  |  |  |      avatarUrl2, displayName) = getPersonBox(baseDir, session, | 
					
						
							|  |  |  |                                              followUrlWf, | 
					
						
							|  |  |  |                                              personCache, projectVersion, | 
					
						
							|  |  |  |                                              httpPrefix, followUrlNickname, | 
					
						
							|  |  |  |                                              domain, 'outbox', 43036) | 
					
						
							|  |  |  |     if avatarUrl2: | 
					
						
							|  |  |  |         avatarUrl = avatarUrl2 | 
					
						
							|  |  |  |     if displayName: | 
					
						
							| 
									
										
										
										
											2021-02-12 17:08:48 +00:00
										 |  |  |         displayName = \ | 
					
						
							|  |  |  |             addEmojiToDisplayName(baseDir, httpPrefix, | 
					
						
							|  |  |  |                                   actorNickname, domain, | 
					
						
							|  |  |  |                                   displayName, False) | 
					
						
							| 
									
										
										
										
											2021-01-12 10:23:25 +00:00
										 |  |  |         titleStr = displayName | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if dormant: | 
					
						
							|  |  |  |         titleStr += ' 💤' | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     buttonsStr = '' | 
					
						
							|  |  |  |     if authorized: | 
					
						
							|  |  |  |         for b in buttons: | 
					
						
							|  |  |  |             if b == 'block': | 
					
						
							|  |  |  |                 buttonsStr += \ | 
					
						
							|  |  |  |                     '<a href="/users/' + actorNickname + \ | 
					
						
							|  |  |  |                     '?options=' + followUrl + \ | 
					
						
							|  |  |  |                     ';1;' + avatarUrl + '"><button class="buttonunfollow">' + \ | 
					
						
							|  |  |  |                     translate['Block'] + '</button></a>\n' | 
					
						
							|  |  |  |             if b == 'unfollow': | 
					
						
							|  |  |  |                 buttonsStr += \ | 
					
						
							|  |  |  |                     '<a href="/users/' + actorNickname + \ | 
					
						
							|  |  |  |                     '?options=' + followUrl + \ | 
					
						
							|  |  |  |                     ';1;' + avatarUrl + '"><button class="buttonunfollow">' + \ | 
					
						
							|  |  |  |                     translate['Unfollow'] + '</button></a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resultStr = '<div class="container">\n' | 
					
						
							|  |  |  |     resultStr += \ | 
					
						
							|  |  |  |         '<a href="/users/' + actorNickname + '?options=' + \ | 
					
						
							|  |  |  |         followUrl + ';1;' + avatarUrl + '">\n' | 
					
						
							|  |  |  |     resultStr += '<p><img loading="lazy" src="' + avatarUrl + '" alt=" ">' | 
					
						
							|  |  |  |     resultStr += titleStr + '</a>' + buttonsStr + '</p>\n' | 
					
						
							|  |  |  |     resultStr += '</div>\n' | 
					
						
							|  |  |  |     return resultStr |