Start of translations

master
Bob Mottram 2019-09-07 09:57:52 +01:00
parent ea20ba6583
commit 5c44b93fb0
4 changed files with 498 additions and 212 deletions

110
daemon.py
View File

@ -12,6 +12,7 @@ import commentjson
import json
import time
import base64
import locale
# used for mime decoding of message POST
import email.parser
# for saving images
@ -604,7 +605,8 @@ class PubServer(BaseHTTPRequestHandler):
optionsLink=None
if len(optionsList)>3:
optionsLink=optionsList[3]
msg=htmlPersonOptions(self.server.baseDir, \
msg=htmlPersonOptions(self.server.translate, \
self.server.baseDir, \
self.server.domain, \
originPathStr, \
optionsActor, \
@ -623,7 +625,7 @@ class PubServer(BaseHTTPRequestHandler):
if htmlGET and '?rmshare=' in self.path:
shareName=self.path.split('?rmshare=')[1]
actor=self.server.httpPrefix+'://'+self.server.domainFull+self.path.split('?rmshare=')[0]
msg=htmlRemoveSharedItem(self.server.baseDir,actor,shareName).encode()
msg=htmlRemoveSharedItem(self.server.translate,self.server.baseDir,actor,shareName).encode()
if not msg:
self._redirect_headers(actor+'/inbox',cookie)
self.server.GETbusy=False
@ -919,7 +921,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.GETbusy=False
return
hashtagStr= \
htmlHashtagSearch(self.server.baseDir,hashtag,pageNumber, \
htmlHashtagSearch(self.server.translate, \
self.server.baseDir,hashtag,pageNumber, \
maxPostsInFeed,self.server.session, \
self.server.cachedWebfingers, \
self.server.personCache, \
@ -939,7 +942,8 @@ class PubServer(BaseHTTPRequestHandler):
if htmlGET and '/users/' in self.path:
if self.path.endswith('/search'):
# show the search screen
msg=htmlSearch(self.server.baseDir,self.path).encode()
msg=htmlSearch(self.server.translate, \
self.server.baseDir,self.path).encode()
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
self.server.GETbusy=False
@ -949,7 +953,9 @@ class PubServer(BaseHTTPRequestHandler):
if htmlGET and '/users/' in self.path:
if self.path.endswith('/searchemoji'):
# show the search screen
msg=htmlSearchEmojiTextEntry(self.server.baseDir,self.path).encode()
msg=htmlSearchEmojiTextEntry(self.server.translate, \
self.server.baseDir, \
self.path).encode()
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
self.server.GETbusy=False
@ -1189,7 +1195,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.useTor)
deleteStr= \
htmlDeletePost(pageNumber, \
htmlDeletePost(self.server.translate,pageNumber, \
self.server.session,self.server.baseDir, \
deleteUrl,self.server.httpPrefix, \
__version__,self.server.cachedWebfingers, \
@ -1279,7 +1285,12 @@ class PubServer(BaseHTTPRequestHandler):
self.path.endswith('/newdm') or \
self.path.endswith('/newreport') or \
self.path.endswith('/newshare')):
msg=htmlNewPost(self.server.baseDir,self.path,inReplyToUrl,replyToList,shareDescription,replyPageNumber).encode()
msg=htmlNewPost(self.server.translate, \
self.server.baseDir, \
self.path,inReplyToUrl, \
replyToList, \
shareDescription, \
replyPageNumber).encode()
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
self.server.GETbusy=False
@ -1311,7 +1322,8 @@ class PubServer(BaseHTTPRequestHandler):
postJsonObject['likes']={'items': []}
if self._requestHTTP():
msg= \
htmlIndividualPost(self.server.session, \
htmlIndividualPost(self.server.translate, \
self.server.session, \
self.server.cachedWebfingers,self.server.personCache, \
nickname,self.server.domain,self.server.port, \
authorized,postJsonObject, \
@ -1361,7 +1373,8 @@ class PubServer(BaseHTTPRequestHandler):
print('DEBUG: creating new session')
self.server.session= \
createSession(self.server.domain,self.server.port,self.server.useTor)
msg=htmlPostReplies(self.server.baseDir, \
msg=htmlPostReplies(self.server.translate, \
self.server.baseDir, \
self.server.session, \
self.server.cachedWebfingers, \
self.server.personCache, \
@ -1406,7 +1419,8 @@ class PubServer(BaseHTTPRequestHandler):
print('DEBUG: creating new session')
self.server.session= \
createSession(self.server.domain,self.server.port,self.server.useTor)
msg=htmlPostReplies(self.server.baseDir, \
msg=htmlPostReplies(self.server.translate, \
self.server.baseDir, \
self.server.session, \
self.server.cachedWebfingers, \
self.server.personCache, \
@ -1440,7 +1454,8 @@ class PubServer(BaseHTTPRequestHandler):
personLookup(self.server.domain,self.path.replace('/roles',''), \
self.server.baseDir)
if getPerson:
msg=htmlProfile(self.server.projectVersion, \
msg=htmlProfile(self.server.translate, \
self.server.projectVersion, \
self.server.baseDir, \
self.server.httpPrefix, \
True, \
@ -1476,7 +1491,8 @@ class PubServer(BaseHTTPRequestHandler):
personLookup(self.server.domain,self.path.replace('/skills',''), \
self.server.baseDir)
if getPerson:
msg=htmlProfile(self.server.projectVersion, \
msg=htmlProfile(self.server.translate, \
self.server.projectVersion, \
self.server.baseDir, \
self.server.httpPrefix, \
True, \
@ -1533,7 +1549,8 @@ class PubServer(BaseHTTPRequestHandler):
if postJsonObject.get('likes'):
postJsonObject['likes']={'items': []}
if self._requestHTTP():
msg=htmlIndividualPost(self.server.baseDir, \
msg=htmlIndividualPost(self.server.translate, \
self.server.baseDir, \
self.server.session, \
self.server.cachedWebfingers,self.server.personCache, \
nickname,self.server.domain,self.server.port, \
@ -1823,7 +1840,8 @@ class PubServer(BaseHTTPRequestHandler):
print('DEBUG: creating new session')
self.server.session= \
createSession(self.server.domain,self.server.port,self.server.useTor)
msg=htmlProfile(self.server.projectVersion, \
msg=htmlProfile(self.server.translate, \
self.server.projectVersion, \
self.server.baseDir, \
self.server.httpPrefix, \
authorized, \
@ -1873,7 +1891,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session= \
createSession(self.server.domain,self.server.port,self.server.useTor)
msg=htmlProfile(self.server.projectVersion, \
msg=htmlProfile(self.server.translate, \
self.server.projectVersion, \
self.server.baseDir, \
self.server.httpPrefix, \
authorized, \
@ -1921,7 +1940,8 @@ class PubServer(BaseHTTPRequestHandler):
print('DEBUG: creating new session')
self.server.session= \
createSession(self.server.domain,self.server.port,self.server.useTor)
msg=htmlProfile(self.server.projectVersion, \
msg=htmlProfile(self.server.translate, \
self.server.projectVersion, \
self.server.baseDir, \
self.server.httpPrefix, \
authorized, \
@ -1952,7 +1972,8 @@ class PubServer(BaseHTTPRequestHandler):
print('DEBUG: creating new session')
self.server.session= \
createSession(self.server.domain,self.server.port,self.server.useTor)
msg=htmlProfile(self.server.projectVersion, \
msg=htmlProfile(self.server.translate, \
self.server.projectVersion, \
self.server.baseDir, \
self.server.httpPrefix, \
authorized, \
@ -2755,7 +2776,8 @@ class PubServer(BaseHTTPRequestHandler):
if searchStr.startswith('#'):
# hashtag search
hashtagStr= \
htmlHashtagSearch(self.server.baseDir,searchStr[1:],1, \
htmlHashtagSearch(self.server.translate, \
self.server.baseDir,searchStr[1:],1, \
maxPostsInFeed,self.server.session, \
self.server.cachedWebfingers, \
self.server.personCache, \
@ -2789,7 +2811,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.port, \
self.server.useTor)
profileStr= \
htmlProfileAfterSearch(self.server.baseDir, \
htmlProfileAfterSearch(self.server.translate, \
self.server.baseDir, \
self.path.replace('/searchhandle',''), \
self.server.httpPrefix, \
nickname, \
@ -3134,7 +3157,11 @@ class PubServer(BaseHTTPRequestHandler):
if '&submitUnblock=' in optionsConfirmParams:
if self.server.debug:
print('Unblocking '+optionsActor)
msg=htmlUnblockConfirm(self.server.baseDir,originPathStr,optionsActor,optionsAvatarUrl).encode()
msg=htmlUnblockConfirm(self.server.translate, \
self.server.baseDir, \
originPathStr, \
optionsActor, \
optionsAvatarUrl).encode()
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
self.server.POSTbusy=False
@ -3142,7 +3169,11 @@ class PubServer(BaseHTTPRequestHandler):
if '&submitFollow=' in optionsConfirmParams:
if self.server.debug:
print('Following '+optionsActor)
msg=htmlFollowConfirm(self.server.baseDir,originPathStr,optionsActor,optionsAvatarUrl).encode()
msg=htmlFollowConfirm(self.server.translate, \
self.server.baseDir, \
originPathStr, \
optionsActor, \
optionsAvatarUrl).encode()
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
self.server.POSTbusy=False
@ -3150,7 +3181,11 @@ class PubServer(BaseHTTPRequestHandler):
if '&submitUnfollow=' in optionsConfirmParams:
if self.server.debug:
print('Unfollowing '+optionsActor)
msg=htmlUnfollowConfirm(self.server.baseDir,originPathStr,optionsActor,optionsAvatarUrl).encode()
msg=htmlUnfollowConfirm(self.server.translate, \
self.server.baseDir, \
originPathStr, \
optionsActor, \
optionsAvatarUrl).encode()
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
self.server.POSTbusy=False
@ -3159,7 +3194,11 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.debug:
print('Sending DM to '+optionsActor)
reportPath=self.path.replace('/personoptions','')+'/newdm'
msg=htmlNewPost(self.server.baseDir,reportPath,None,[optionsActor],None,pageNumber).encode()
msg=htmlNewPost(self.server.translate, \
self.server.baseDir, \
reportPath,None, \
[optionsActor],None, \
pageNumber).encode()
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
self.server.POSTbusy=False
@ -3168,7 +3207,10 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.debug:
print('Reporting '+optionsActor)
reportPath=self.path.replace('/personoptions','')+'/newreport'
msg=htmlNewPost(self.server.baseDir,reportPath,None,[],postUrl,pageNumber).encode()
msg=htmlNewPost(self.server.translate, \
self.server.baseDir, \
reportPath,None,[], \
postUrl,pageNumber).encode()
self._set_headers('text/html',len(msg),cookie)
self.wfile.write(msg)
self.server.POSTbusy=False
@ -3462,6 +3504,26 @@ def runDaemon(projectVersion, \
httpd = ThreadingHTTPServer(serverAddress, PubServerUnitTest)
else:
httpd = ThreadingHTTPServer(serverAddress, PubServer)
# load translations dictionary
httpd.translate={}
if not unitTest:
if not os.path.isdir(baseDir+'/translations'):
print('ERROR: translations directory not found')
return
systemLanguage=locale.getdefaultlocale()[0]
if '_' in systemLanguage:
systemLanguage=systemLanguage.split('_')[0]
if '.' in systemLanguage:
systemLanguage=systemLanguage.split('.')[0]
translationsFile=baseDir+'/translations/'+systemLanguage+'.json'
if not os.path.isfile(translationsFile):
systemLanguage='en'
translationsFile=baseDir+'/translations/'+systemLanguage+'.json'
print('System language: '+systemLanguage)
with open(translationsFile, 'r') as fp:
httpd.translate=commentjson.load(fp)
httpd.outboxThread={}
httpd.projectVersion=projectVersion
# max POST size of 30M

View File

@ -0,0 +1,94 @@
{
"SHOW MORE": "SHOW MORE",
"Your browser does not support the video tag.": "Your browser does not support the video tag.",
"Your browser does not support the audio tag.": "Your browser does not support the audio tag.",
"Show profile": "Show profile",
"Show options for this person": "Show options for this person",
"Repeat this post": "Repeat this post",
"Undo the repeat": "Undo the repeat",
"Like this post": "Like this post",
"Undo the like": "Undo the like",
"Delete this post": "Delete this post",
"Reply to this post": "Reply to this post",
"Write your post text below.": "Write your post text below.",
"Write your reply to": "Write your reply to",
"this post": "this post",
"Write your report below.": "Write your report below.",
"This message only goes to moderators, even if it mentions other fediverse addresses.": "This message only goes to moderators, even if it mentions other fediverse addresses.",
"Also see": "Also see",
"Terms of Service": "Terms of Service",
"Enter the details for your shared item below.": "Enter the details for your shared item below.",
"Subject or Content Warning (optional)": "Subject or Content Warning (optional)",
"Write something": "Write something",
"Name of the shared item": "Name of the shared item",
"Description of the item being shared": "Description of the item being shared",
"Type of shared item. eg. hat": "Type of shared item. eg. hat",
"Category of shared item. eg. clothing": "Category of shared item. eg. clothing",
"Duration of listing in days": "Duration of listing in days",
"City or location of the shared item": "City or location of the shared item",
"Describe a shared item": "Describe a shared item",
"Public": "Public",
"Visible to anyone": "Visible to anyone",
"Unlisted": "Unlisted",
"Not on public timeline": "Not on public timeline",
"Followers": "Followers",
"Only to followers": "Only to followers",
"DM": "DM",
"Only to mentioned people": "Only to mentioned people",
"Report": "Report",
"Send to moderators": "Send to moderators",
"Search for emoji": "Search for emoji",
"Cancel": "Cancel",
"Submit": "Submit",
"Image description": "Image description",
"Item image": "Item image",
"Type": "Type",
"Category": "Category",
"Location": "Location",
"Login": "Login",
"Edit": "Edit",
"Switch to timeline view": "Switch to timeline view",
"Approve": "Approve",
"Deny": "Deny",
"Posts": "Posts",
"Following": "Following",
"Followers": "Followers",
"Roles": "Roles",
"Skills": "Skills",
"Shares": "Shares",
"Block": "Block",
"Unfollow": "Unfollow",
"Your browser does not support the audio element.": "Your browser does not support the audio element.",
"Your browser does not support the video element.": "Your browser does not support the video element.",
"Create a new post": "Create a new post",
"Create a new DM": "Create a new DM",
"Switch to profile view": "Switch to profile view",
"Inbox": "Inbox",
"Outbox": "Outbox",
"Search and follow": "Search and follow",
"Refresh": "Refresh",
"Nickname or URL. Block using *@domain or nickname@domain": "Nickname or URL. Block using *@domain or nickname@domain",
"Remove the above item": "Remove the above item",
"Remove": "Remove",
"Suspend the above account nickname": "Suspend the above account nickname",
"Suspend": "Suspend",
"Remove a suspension for an account nickname": "Remove a suspension for an account nickname",
"Unsuspend": "Unsuspend",
"Block an account on another instance": "Block an account on another instance",
"Unblock": "Unblock",
"Unblock an account on another instance": "Unblock an account on another instance",
"Information about current blocks/suspensions": "Information about current blocks/suspensions",
"Info": "Info",
"Remove": "Remove",
"Yes": "Yes",
"No": "No",
"Delete this post?": "Delete this post?",
"Follow": "Follow",
"Stop following": "Stop following",
"Options for": "Options for",
"View": "View",
"Stop blocking": "Stop blocking",
"Enter an emoji name to search for": "Enter an emoji name to search for",
"Enter an address, shared item, #hashtag, *skill or :emoji: to search for": "Enter an address, shared item, #hashtag, *skill or :emoji: to search for",
"Go Back": "Go Back"
}

View File

@ -0,0 +1,94 @@
{
"SHOW MORE": "MONTRE PLUS",
"Your browser does not support the video tag.": "Votre navigateur ne supporte pas le tag vidéo.",
"Your browser does not support the audio tag.": "Votre navigateur ne supporte pas la balise audio.",
"Show profile": "Montre le profile",
"Show options for this person": "Afficher les options pour cette personne",
"Repeat this post": "Répétez ce post",
"Undo the repeat": "Annuler la répétition",
"Like this post": "Comme ce poste",
"Undo the like": "Annuler le même",
"Delete this post": "Supprimer ce post",
"Reply to this post": "Répondre à ce post",
"Write your post text below.": "Entrez votre message ci-dessous.",
"Write your reply to": "Écrivez votre réponse à",
"this post": "ce post",
"Write your report below.": "Écrivez votre rapport ci-dessous.",
"This message only goes to moderators, even if it mentions other fediverse addresses.": "Ce message nadresse que les modérateurs, même sil mentionne dautres adresses fedivers.",
"Also see": "Regarde aussi",
"Terms of Service": "Conditions d'utilisation",
"Enter the details for your shared item below.": "Entrez les détails de votre article partagé ci-dessous.",
"Subject or Content Warning (optional)": "Avertissement de sujet ou de contenu (facultatif)",
"Write something": "Écris quelque chose",
"Name of the shared item": "Nom de l'élément partagé",
"Description of the item being shared": "Description de l'élément en cours de partage",
"Type of shared item. eg. hat": "Type d'élément partagé. par exemple. chapeau",
"Category of shared item. eg. clothing": "Catégorie d'élément partagé. par exemple. Vêtements",
"Duration of listing in days": "Durée de la cotation en jours",
"City or location of the shared item": "Ville ou lieu de l'élément partagé",
"Describe a shared item": "Décrire un élément partagé",
"Public": "Publique",
"Visible to anyone": "Visible par n'importe qui",
"Unlisted": "Non répertorié",
"Not on public timeline": "Pas sur la chronologie publique",
"Followers": "Suiveuses",
"Only to followers": "Seulement aux adeptes",
"DM": "MD",
"Only to mentioned people": "Seulement aux personnes mentionnées",
"Report": "Rapport",
"Send to moderators": "Envoyer aux modérateurs",
"Search for emoji": "Recherche emoji",
"Cancel": "Annuler",
"Submit": "Soumettre",
"Image description": "Description de l'image",
"Item image": "Image de l'article",
"Type": "Type",
"Category": "Catégorie",
"Location": "Emplacement",
"Login": "S'identifier",
"Edit": "Modifier",
"Switch to timeline view": "Passer en vue chronologique",
"Approve": "Approuver",
"Deny": "Nier",
"Posts": "Des postes",
"Following": "Suivante",
"Followers": "Suiveuses",
"Roles": "Rôles",
"Skills": "Compétences",
"Shares": "Actions",
"Block": "Bloc",
"Unfollow": "Se désabonner",
"Your browser does not support the audio element.": "Votre navigateur ne supporte pas l'élément audio.",
"Your browser does not support the video element.": "Votre application ne supporte pas le format de l'élément vidéo.",
"Create a new post": "Créer un nouveau post",
"Create a new DM": "Créer un nouveau message direct",
"Switch to profile view": "Passer en vue de profil",
"Inbox": "Réception",
"Outbox": "Envoi",
"Search and follow": "Rechercher et suivre",
"Refresh": "Rafraîchir",
"Nickname or URL. Block using *@domain or nickname@domain": "Surnom ou URL. Bloquer en utilisant *@domain ou pseudo@domain",
"Remove the above item": "Supprimer l'élément ci-dessus",
"Remove": "Retirer",
"Suspend the above account nickname": "Suspendre le pseudo du compte ci-dessus",
"Suspend": "Suspendre",
"Remove a suspension for an account nickname": "Supprimer une suspension pour un pseudo de compte",
"Unsuspend": "Insuffler",
"Block an account on another instance": "Bloquer un compte sur une autre instance",
"Unblock": "Débloquer",
"Unblock an account on another instance": "Débloquer un compte sur une autre instance",
"Information about current blocks/suspensions": "Informations sur les blocs / suspensions en cours",
"Info": "Info",
"Remove": "Retirer",
"Yes": "Oui",
"No": "Non",
"Delete this post?": "Supprimer ce post?",
"Follow": "Suivre",
"Stop following": "Arrête de suivre",
"Options for": "Options pour",
"View": "Vue",
"Stop blocking": "Arrêtez le blocage",
"Enter an emoji name to search for": "Entrez un nom emoji à rechercher",
"Enter an address, shared item, #hashtag, *skill or :emoji: to search for": "Entrez une adresse, un objet partagé, #hashtag, * skill ou: emoji: à rechercher",
"Go Back": "Retourner"
}

View File

@ -221,7 +221,8 @@ def htmlModerationInfo(baseDir: str) -> str:
infoForm+=htmlFooter()
return infoForm
def htmlHashtagSearch(baseDir: str,hashtag: str,pageNumber: int,postsPerPage: int,
def htmlHashtagSearch(translate: {}, \
baseDir: str,hashtag: str,pageNumber: int,postsPerPage: int, \
session,wfRequest: {},personCache: {}, \
httpPrefix: str,projectVersion: str) -> str:
"""Show a page containing search results for a hashtag
@ -272,7 +273,8 @@ def htmlHashtagSearch(baseDir: str,hashtag: str,pageNumber: int,postsPerPage: in
index-=1
continue
hashtagSearchForm+= \
individualPostAsHtml(None,baseDir,session,wfRequest,personCache, \
individualPostAsHtml(translate,None, \
baseDir,session,wfRequest,personCache, \
nickname,domain,port,postJsonObject, \
None,True,False, \
httpPrefix,projectVersion, \
@ -680,20 +682,23 @@ def htmlSuspended(baseDir: str) -> str:
suspendedForm+=htmlFooter()
return suspendedForm
def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: str,pageNumber: int) -> str:
def htmlNewPost(translate: {},baseDir: str, \
path: str,inReplyTo: str, \
mentions: [], \
reportUrl: str,pageNumber: int) -> str:
"""New post screen
"""
replyStr=''
if not path.endswith('/newshare'):
if not path.endswith('/newreport'):
if not inReplyTo:
newPostText='<p class="new-post-text">Enter your post text below.</p>'
newPostText='<p class="new-post-text">'+translate['Write your post text below.']+'</p>'
else:
newPostText='<p class="new-post-text">Enter your reply to <a href="'+inReplyTo+'">this post</a> below.</p>'
newPostText='<p class="new-post-text">'+translate['Write your reply to']+' <a href="'+inReplyTo+'">'+translate['this post']+'</a></p>'
replyStr='<input type="hidden" name="replyTo" value="'+inReplyTo+'">'
else:
newPostText= \
'<p class="new-post-text">Enter your report below.</p>'
'<p class="new-post-text">'+translate['Write your report below.']+'</p>'
# custom report header with any additional instructions
if os.path.isfile(baseDir+'/accounts/report.txt'):
@ -704,9 +709,9 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st
customReportText=customReportText.replace('<p>','<p class="login-subtext">')
newPostText+=customReportText
newPostText+='<p class="new-post-subtext">This message <i>only goes to moderators</i>, even if it mentions other fediverse addresses.</p><p class="new-post-subtext">You can also refer to points within the <a href="/terms">Terms of Service</a> if necessary.</p>'
newPostText+='<p class="new-post-subtext">'+translate['This message only goes to moderators, even if it mentions other fediverse addresses.']+'</p><p class="new-post-subtext">'+translate['Also see']+' <a href="/terms">'+translate['Terms of Service']+'</a></p>'
else:
newPostText='<p class="new-post-text">Enter the details for your shared item below.</p>'
newPostText='<p class="new-post-text">'+translate['Enter the details for your shared item below.']+'</p>'
if os.path.isfile(baseDir+'/accounts/newpost.txt'):
with open(baseDir+'/accounts/newpost.txt', 'r') as file:
@ -721,8 +726,8 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st
scopeIcon='scope_public.png'
scopeDescription='Public'
placeholderSubject='Subject or Content Warning (optional)...'
placeholderMessage='Write something...'
placeholderSubject=translate['Subject or Content Warning (optional)']+'...'
placeholderMessage=translate['Write something']+'...'
extraFields=''
endpoint='newpost'
if path.endswith('/newunlisted'):
@ -744,23 +749,23 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st
if path.endswith('/newshare'):
scopeIcon='scope_share.png'
scopeDescription='Shared Item'
placeholderSubject='Name of the shared item...'
placeholderMessage='Description of the item being shared...'
placeholderSubject=translate['Name of the shared item']+'...'
placeholderMessage=translate['Description of the item being shared']+'...'
endpoint='newshare'
extraFields= \
'<div class="container">' \
' <input type="text" class="itemType" placeholder="Type of shared item. eg. hat" name="itemType">' \
' <input type="text" class="category" placeholder="Category of shared item. eg. clothing" name="category">' \
' <label class="labels">Duration of listing in days:</label> <input type="number" name="duration" min="1" max="365" step="1" value="14">' \
' <input type="text" class="itemType" placeholder="'+translate['Type of shared item. eg. hat']+'" name="itemType">' \
' <input type="text" class="category" placeholder="'+translate['Category of shared item. eg. clothing']+'" name="category">' \
' <label class="labels">'+translate['Duration of listing in days']+':</label> <input type="number" name="duration" min="1" max="365" step="1" value="14">' \
'</div>' \
'<input type="text" placeholder="City or location of the shared item" name="location">'
'<input type="text" placeholder="'+translate['City or location of the shared item']+'" name="location">'
newPostForm=htmlHeader(newPostCSS)
# only show the share option if this is not a reply
shareOptionOnDropdown=''
if not replyStr:
shareOptionOnDropdown='<a href="'+pathBase+'/newshare"><img src="/icons/scope_share.png"/><b>Share</b><br>Describe a shared item</a>'
shareOptionOnDropdown='<a href="'+pathBase+'/newshare"><img src="/icons/scope_share.png"/><b>Share</b><br>'+translate['Describe a shared item']+'</a>'
mentionsStr=''
for m in mentions:
@ -803,11 +808,11 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st
if not reportUrl:
dropDownContent= \
' <div id="myDropdown" class="dropdown-content">' \
' <a href="'+pathBase+dropdownNewPostSuffix+'"><img src="/icons/scope_public.png"/><b>Public</b><br>Visible to anyone</a>' \
' <a href="'+pathBase+dropdownUnlistedSuffix+'"><img src="/icons/scope_unlisted.png"/><b>Unlisted</b><br>Not on public timeline</a>' \
' <a href="'+pathBase+dropdownFollowersSuffix+'"><img src="/icons/scope_followers.png"/><b>Followers</b><br>Only to followers</a>' \
' <a href="'+pathBase+dropdownDMSuffix+'"><img src="/icons/scope_dm.png"/><b>DM</b><br>Only to mentioned people</a>' \
' <a href="'+pathBase+dropdownReportSuffix+'"><img src="/icons/scope_report.png"/><b>Report</b><br>Send to moderators</a>'+ \
' <a href="'+pathBase+dropdownNewPostSuffix+'"><img src="/icons/scope_public.png"/><b>'+translate['Public']+'</b><br>'+translate['Visible to anyone']+'</a>' \
' <a href="'+pathBase+dropdownUnlistedSuffix+'"><img src="/icons/scope_unlisted.png"/><b>'+translate['Unlisted']+'</b><br>'+translate['Not on public timeline']+'</a>' \
' <a href="'+pathBase+dropdownFollowersSuffix+'"><img src="/icons/scope_followers.png"/><b>'+translate['Followers']+'</b><br>'+translate['Only to followers']+'</a>' \
' <a href="'+pathBase+dropdownDMSuffix+'"><img src="/icons/scope_dm.png"/><b>'+translate['DM']+'</b><br>'+translate['Only to mentioned people']+'</a>' \
' <a href="'+pathBase+dropdownReportSuffix+'"><img src="/icons/scope_report.png"/><b>'+translate['Report']+'</b><br>'+translate['Send to moderators']+'</a>'+ \
shareOptionOnDropdown+ \
' </div>'
else:
@ -822,9 +827,9 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st
' <img src="/icons/'+scopeIcon+'"/><b class="scope-desc">'+scopeDescription+'</b>'+ \
dropDownContent+ \
' </div>' \
' <input type="submit" name="submitPost" value="Submit">' \
' <a href="'+pathBase+'/inbox"><button class="cancelbtn">Cancel</button></a>' \
' <a href="'+pathBase+'/searchemoji"><img class="emojisearch" src="/emoji/1F601.png" title="Search for emoji" alt="Search for emoji"/></a>'+ \
' <input type="submit" name="submitPost" value="'+translate['Submit']+'">' \
' <a href="'+pathBase+'/inbox"><button class="cancelbtn">'+translate['Cancel']+'</button></a>' \
' <a href="'+pathBase+'/searchemoji"><img class="emojisearch" src="/emoji/1F601.png" title="'+translate['Search for emoji']+'" alt="'+translate['Search for emoji']+'"/></a>'+ \
' </div>'+ \
replyStr+ \
' <input type="text" placeholder="'+placeholderSubject+'" name="subject">' \
@ -832,7 +837,7 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st
' <textarea id="message" name="message" placeholder="'+placeholderMessage+'" style="height:400px" autofocus>'+mentionsStr+'</textarea>' \
''+extraFields+ \
' <div class="container">' \
' <input type="text" placeholder="Image description" name="imageDescription">' \
' <input type="text" placeholder="'+translate['Image description']+'" name="imageDescription">' \
' <input type="file" id="attachpic" name="attachpic"' \
' accept=".png, .jpg, .jpeg, .gif, .mp4, .webm, .ogv, .mp3, .ogg">' \
' </div>' \
@ -876,7 +881,8 @@ def htmlFooter() -> str:
'</html>\n'
return htmlStr
def htmlProfilePosts(baseDir: str,httpPrefix: str, \
def htmlProfilePosts(translate: {}, \
baseDir: str,httpPrefix: str, \
authorized: bool,ocapAlways: bool, \
nickname: str,domain: str,port: int, \
session,wfRequest: {},personCache: {}, \
@ -903,7 +909,8 @@ def htmlProfilePosts(baseDir: str,httpPrefix: str, \
break
for item in outboxFeed['orderedItems']:
if item['type']=='Create':
postStr=individualPostAsHtml(None,baseDir,session,wfRequest,personCache, \
postStr=individualPostAsHtml(translate,None, \
baseDir,session,wfRequest,personCache, \
nickname,domain,port,item,None,True,False, \
httpPrefix,projectVersion, \
False,False,False,True)
@ -915,7 +922,7 @@ def htmlProfilePosts(baseDir: str,httpPrefix: str, \
currPage+=1
return profileStr
def htmlProfileFollowing(baseDir: str,httpPrefix: str, \
def htmlProfileFollowing(translate: {},baseDir: str,httpPrefix: str, \
authorized: bool,ocapAlways: bool, \
nickname: str,domain: str,port: int, \
session,wfRequest: {},personCache: {}, \
@ -948,7 +955,7 @@ def htmlProfileFollowing(baseDir: str,httpPrefix: str, \
'<center><a href="'+actor+'/'+feedName+'?page='+str(pageNumber+1)+'"><img class="pageicon" src="/icons/pagedown.png" title="Page down" alt="Page down"></a></center>'
return profileStr
def htmlProfileRoles(nickname: str,domain: str,rolesJson: {}) -> str:
def htmlProfileRoles(translate: {},nickname: str,domain: str,rolesJson: {}) -> str:
"""Shows roles on the profile screen
"""
profileStr=''
@ -963,19 +970,17 @@ def htmlProfileRoles(nickname: str,domain: str,rolesJson: {}) -> str:
profileStr='<div>'+profileStr+'</div>'
return profileStr
def htmlProfileSkills(nickname: str,domain: str,skillsJson: {}) -> str:
def htmlProfileSkills(translate: {},nickname: str,domain: str,skillsJson: {}) -> str:
"""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><br>'
if len(profileStr)==0:
profileStr+='<p>@'+nickname+'@'+domain+' has no skills assigned</p>'
else:
if len(profileStr)>0:
profileStr='<center><div class="skill-title">'+profileStr+'</div></center>'
return profileStr
def htmlProfileShares(nickname: str,domain: str,sharesJson: {}) -> str:
def htmlProfileShares(translate: {},nickname: str,domain: str,sharesJson: {}) -> str:
"""Shows shares on the profile screen
"""
profileStr=''
@ -984,19 +989,17 @@ def htmlProfileShares(nickname: str,domain: str,sharesJson: {}) -> str:
profileStr+='<p class="share-title">'+item['displayName']+'</p>'
if item.get('imageUrl'):
profileStr+='<a href="'+item['imageUrl']+'">'
profileStr+='<img src="'+item['imageUrl']+'" alt="Item image"></a>'
profileStr+='<img src="'+item['imageUrl']+'" alt="'+translate['Item image']+'"></a>'
profileStr+='<p>'+item['summary']+'</p>'
profileStr+='<p><b>Type:</b> '+item['itemType']+' '
profileStr+='<b>Category:</b> '+item['category']+' '
profileStr+='<b>Location:</b> '+item['location']+'</p>'
profileStr+='<p><b>'+translate['Type']+':</b> '+item['itemType']+' '
profileStr+='<b>'+translate['Category']+':</b> '+item['category']+' '
profileStr+='<b>'+translate['Location']+':</b> '+item['location']+'</p>'
profileStr+='</div>'
if len(profileStr)==0:
profileStr+='<p>@'+nickname+'@'+domain+' is not sharing any items</p>'
else:
if len(profileStr)>0:
profileStr='<div class="share-title">'+profileStr+'</div>'
return profileStr
def htmlProfile(projectVersion: str, \
def htmlProfile(translate: {},projectVersion: str, \
baseDir: str,httpPrefix: str,authorized: bool, \
ocapAlways: bool,profileJson: {},selected: str, \
session,wfRequest: {},personCache: {}, \
@ -1043,10 +1046,10 @@ def htmlProfile(projectVersion: str, \
actor=profileJson['id']
if not authorized:
loginButton='<br><a href="/login"><button class="loginButton">Login</button></a>'
loginButton='<br><a href="/login"><button class="loginButton">'+translate['Login']+'</button></a>'
else:
editProfileStr='<a href="'+actor+'/editprofile"><button class="button"><span>Edit </span></button></a>'
linkToTimelineStart='<a href="/users/'+nickname+'/inbox" title="Switch to timeline view" alt="Switch to timeline view">'
editProfileStr='<a href="'+actor+'/editprofile"><button class="button"><span>'+translate['Edit']+' </span></button></a>'
linkToTimelineStart='<a href="/users/'+nickname+'/inbox" title="'+translate['Switch to timeline view']+'" alt="'+translate['Switch to timeline view']+'">'
linkToTimelineEnd='</a>'
# are there any follow requests?
followRequestsFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/followrequests.txt'
@ -1073,9 +1076,9 @@ def htmlProfile(projectVersion: str, \
followApprovalsSection+='<a href="'+followerActor+'">'
followApprovalsSection+='<span class="followRequestHandle">'+followerHandle+'</span></a>'
followApprovalsSection+='<a href="'+basePath+'/followapprove='+followerHandle+'">'
followApprovalsSection+='<button class="followApprove">Approve</button></a>'
followApprovalsSection+='<button class="followApprove">'+translate['Approve']+'</button></a>'
followApprovalsSection+='<a href="'+basePath+'/followdeny='+followerHandle+'">'
followApprovalsSection+='<button class="followDeny">Deny</button></a>'
followApprovalsSection+='<button class="followDeny">'+translate['Deny']+'</button></a>'
followApprovalsSection+='</div>'
profileStr= \
@ -1092,12 +1095,12 @@ def htmlProfile(projectVersion: str, \
linkToTimelineEnd+ \
'<div class="container">\n' \
' <center>' \
' <a href="'+actor+'"><button class="'+postsButton+'"><span>Posts </span></button></a>' \
' <a href="'+actor+'/following"><button class="'+followingButton+'"><span>Following </span></button></a>' \
' <a href="'+actor+'/followers"><button class="'+followersButton+'"><span>Followers </span></button></a>' \
' <a href="'+actor+'/roles"><button class="'+rolesButton+'"><span>Roles </span></button></a>' \
' <a href="'+actor+'/skills"><button class="'+skillsButton+'"><span>Skills </span></button></a>' \
' <a href="'+actor+'/shares"><button class="'+sharesButton+'"><span>Shares </span></button></a>'+ \
' <a href="'+actor+'"><button class="'+postsButton+'"><span>'+translate['Posts']+' </span></button></a>' \
' <a href="'+actor+'/following"><button class="'+followingButton+'"><span>'+translate['Following']+' </span></button></a>' \
' <a href="'+actor+'/followers"><button class="'+followersButton+'"><span>'+translate['Followers']+' </span></button></a>' \
' <a href="'+actor+'/roles"><button class="'+rolesButton+'"><span>'+translate['Roles']+' </span></button></a>' \
' <a href="'+actor+'/skills"><button class="'+skillsButton+'"><span>'+translate['Skills']+' </span></button></a>' \
' <a href="'+actor+'/shares"><button class="'+sharesButton+'"><span>'+translate['Shares']+' </span></button></a>'+ \
editProfileStr+ \
' </center>' \
'</div>'
@ -1109,13 +1112,14 @@ def htmlProfile(projectVersion: str, \
if selected=='posts':
profileStr+= \
htmlProfilePosts(baseDir,httpPrefix,authorized, \
htmlProfilePosts(translate, \
baseDir,httpPrefix,authorized, \
ocapAlways,nickname,domain,port, \
session,wfRequest,personCache, \
projectVersion)
if selected=='following':
profileStr+= \
htmlProfileFollowing(baseDir,httpPrefix, \
htmlProfileFollowing(translate,baseDir,httpPrefix, \
authorized,ocapAlways,nickname, \
domain,port,session, \
wfRequest,personCache,extraJson, \
@ -1125,7 +1129,7 @@ def htmlProfile(projectVersion: str, \
pageNumber,maxItemsPerPage)
if selected=='followers':
profileStr+= \
htmlProfileFollowing(baseDir,httpPrefix, \
htmlProfileFollowing(translate,baseDir,httpPrefix, \
authorized,ocapAlways,nickname, \
domain,port,session, \
wfRequest,personCache,extraJson, \
@ -1135,13 +1139,13 @@ def htmlProfile(projectVersion: str, \
pageNumber,maxItemsPerPage)
if selected=='roles':
profileStr+= \
htmlProfileRoles(nickname,domainFull,extraJson)
htmlProfileRoles(translate,nickname,domainFull,extraJson)
if selected=='skills':
profileStr+= \
htmlProfileSkills(nickname,domainFull,extraJson)
htmlProfileSkills(translate,nickname,domainFull,extraJson)
if selected=='shares':
profileStr+= \
htmlProfileShares(nickname,domainFull,extraJson)
htmlProfileShares(translate,nickname,domainFull,extraJson)
profileStr=htmlHeader(profileStyle)+profileStr+htmlFooter()
return profileStr
@ -1172,9 +1176,9 @@ def individualFollowAsHtml(baseDir: str,session,wfRequest: {}, \
if authorized:
for b in buttons:
if b=='block':
buttonsStr+='<a href="/users/'+actorNickname+'?block='+followUrl+';'+avatarUrl+'"><button class="buttonunfollow">Block</button></a>'
buttonsStr+='<a href="/users/'+actorNickname+'?block='+followUrl+';'+avatarUrl+'"><button class="buttonunfollow">'+translate['Block']+'</button></a>'
if b=='unfollow':
buttonsStr+='<a href="/users/'+actorNickname+'?unfollow='+followUrl+';'+avatarUrl+'"><button class="buttonunfollow">Unfollow</button></a>'
buttonsStr+='<a href="/users/'+actorNickname+'?unfollow='+followUrl+';'+avatarUrl+'"><button class="buttonunfollow">'+translate['Unfollow']+'</button></a>'
return \
'<div class="container">\n' \
@ -1238,7 +1242,7 @@ def htmlRemplaceEmojiFromTags(content: str,tag: {}) -> str:
content=content.replace(tagItem['name'],emojiHtml)
return content
def addEmbeddedAudio(content: str) -> str:
def addEmbeddedAudio(translate: {},content: str) -> str:
"""Adds embedded audio for mp3/ogg
"""
if not ('.mp3' in content or '.ogg' in content):
@ -1272,11 +1276,11 @@ def addEmbeddedAudio(content: str) -> str:
url=w
content+='<center><audio controls>'
content+='<source src="'+url+'" type="audio/'+extension.replace('.','')+'">'
content+='Your browser does not support the audio element.'
content+=translate['Your browser does not support the audio element.']
content+='</audio></center>'
return content
def addEmbeddedVideo(content: str,width=400,height=300) -> str:
def addEmbeddedVideo(translate: {},content: str,width=400,height=300) -> str:
"""Adds embedded video for mp4/webm/ogv
"""
if not ('.mp4' in content or '.webm' in content or '.ogv' in content):
@ -1311,11 +1315,11 @@ def addEmbeddedVideo(content: str,width=400,height=300) -> str:
url=w
content+='<center><video width="'+str(width)+'" height="'+str(height)+'" controls>'
content+='<source src="'+url+'" type="video/'+extension.replace('.','')+'">'
content+='Your browser does not support the video element.'
content+=translate['Your browser does not support the video element.']
content+='</video></center>'
return content
def addEmbeddedVideoFromSites(content: str,width=400,height=300) -> str:
def addEmbeddedVideoFromSites(translate: {},content: str,width=400,height=300) -> str:
"""Adds embedded videos
"""
if '>vimeo.com/' in content:
@ -1355,12 +1359,12 @@ def addEmbeddedVideoFromSites(content: str,width=400,height=300) -> str:
return content
return content
def addEmbeddedElements(content: str) -> str:
def addEmbeddedElements(translate: {},content: str) -> str:
"""Adds embedded elements for various media types
"""
content=addEmbeddedVideoFromSites(content)
content=addEmbeddedAudio(content)
return addEmbeddedVideo(content)
content=addEmbeddedVideoFromSites(translate,content)
content=addEmbeddedAudio(translate,content)
return addEmbeddedVideo(translate,content)
def followerApprovalActive(baseDir: str,nickname: str,domain: str) -> bool:
"""Returns true if the given account requires follower approval
@ -1374,7 +1378,9 @@ def followerApprovalActive(baseDir: str,nickname: str,domain: str) -> bool:
manuallyApprovesFollowers=actorJson['manuallyApprovesFollowers']
return manuallyApprovesFollowers
def insertQuestion(nickname: str,content: str,postJsonObject: {},pageNumber: int) -> str:
def insertQuestion(translate: {}, \
nickname: str,content: str, \
postJsonObject: {},pageNumber: int) -> str:
""" Inserts question selection into a post
"""
if not isQuestion(postJsonObject):
@ -1393,11 +1399,12 @@ def insertQuestion(nickname: str,content: str,postJsonObject: {},pageNumber: int
if not choice.get('name'):
continue
content+='<input type="radio" name="answer" value="'+choice['name']+'"> '+choice['name']+'<br>'
content+='<input type="submit" value="Submit">'
content+='<input type="submit" value="'+translate['Submit']+'">'
content+='</form></div>'
return content
def individualPostAsHtml(pageNumber: int,baseDir: str, \
def individualPostAsHtml(translate: {}, \
pageNumber: int,baseDir: str, \
session,wfRequest: {},personCache: {}, \
nickname: str,domain: str,port: int, \
postJsonObject: {}, \
@ -1584,8 +1591,8 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
attachmentStr+='<br>'
attachmentStr+= \
'<center><video width="400" height="300" controls>' \
'<source src="'+attach['url']+'" alt="'+imageDescription+'" title="'+imageDescription+'" class="attachment" type="video/'+extension.replace('.','')+'">' \
'Your browser does not support the video tag.' \
'<source src="'+attach['url']+'" alt="'+imageDescription+'" title="'+imageDescription+'" class="attachment" type="video/'+extension.replace('.','')+'">'+ \
translate['Your browser does not support the video tag.']+ \
'</video></center>'
attachmentCtr+=1
elif mediaType=='audio/mpeg' or \
@ -1598,8 +1605,8 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
attachmentStr+='<br>'
attachmentStr+= \
'<center><audio controls>' \
'<source src="'+attach['url']+'" alt="'+imageDescription+'" title="'+imageDescription+'" class="attachment" type="audio/'+extension.replace('.','')+'">' \
'Your browser does not support the audio tag.' \
'<source src="'+attach['url']+'" alt="'+imageDescription+'" title="'+imageDescription+'" class="attachment" type="audio/'+extension.replace('.','')+'">'+ \
translate['Your browser does not support the audio tag.']+ \
'</audio></center>'
attachmentCtr+=1
attachmentStr+='</div>'
@ -1627,7 +1634,7 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
avatarImageInPost= \
' <div class="timeline-avatar">' \
' <a href="'+postJsonObject['actor']+'">' \
' <img src="'+avatarUrl+'" title="Show profile" alt="Avatar"'+avatarPosition+'/></a>' \
' <img src="'+avatarUrl+'" title="'+translate['Show profile']+'" alt="Avatar"'+avatarPosition+'/></a>' \
' </div>'
messageIdStr=''
@ -1638,7 +1645,7 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
avatarImageInPost= \
' <div class="timeline-avatar">' \
' <a href="/users/'+nickname+'?options='+postJsonObject['actor']+';'+str(pageNumber)+';'+avatarUrl+messageIdStr+'">' \
' <img title="Show options for this person" src="'+avatarUrl+'" '+avatarPosition+'/></a>' \
' <img title="'+translate['Show options for this person']+'" src="'+avatarUrl+'" '+avatarPosition+'/></a>' \
' </div>'
publishedStr=postJsonObject['object']['published']
@ -1662,11 +1669,11 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
# don't allow announce/repeat of your own posts
announceIcon='repeat_inactive.png'
announceLink='repeat'
announceTitle='Repeat this post'
announceTitle=translate['Repeat this post']
if announcedByPerson(postJsonObject,nickname,fullDomain):
announceIcon='repeat.png'
announceLink='unrepeat'
announceTitle='Undo the repeat this post'
announceTitle=translate['Undo the repeat']
announceStr= \
'<a href="/users/'+nickname+'?'+announceLink+'='+postJsonObject['object']['id']+pageNumberParam+'" title="'+announceTitle+'">' \
'<img src="/icons/'+announceIcon+'"/></a>'
@ -1675,11 +1682,11 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
if not isModerationPost:
likeIcon='like_inactive.png'
likeLink='like'
likeTitle='Like this post'
likeTitle=translate['Like this post']
if noOfLikes(postJsonObject)>0:
likeIcon='like.png'
likeLink='unlike'
likeTitle='Undo the like of this post'
likeTitle=translate['Undo the like']
likeStr= \
'<a href="/users/'+nickname+'?'+likeLink+'='+postJsonObject['object']['id']+pageNumberParam+'" title="'+likeTitle+'">' \
'<img src="/icons/'+likeIcon+'"/></a>'
@ -1690,7 +1697,7 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
postJsonObject['object']['id'].startswith(postJsonObject['actor'])):
if '/users/'+nickname+'/' in postJsonObject['object']['id']:
deleteStr= \
'<a href="/users/'+nickname+'?delete='+postJsonObject['object']['id']+pageNumberParam+'" title="Delete this post">' \
'<a href="/users/'+nickname+'?delete='+postJsonObject['object']['id']+pageNumberParam+'" title="'+translate['Delete this post']+'">' \
'<img src="/icons/delete.png"/></a>'
# change the background color for DMs in inbox timeline
@ -1715,11 +1722,11 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
footerStr='<div class="'+containerClassIcons+'">'
if not isModerationPost and showRepeatIcon:
if not manuallyApprovesFollowers:
footerStr+='<a href="/users/'+nickname+'?replyto='+replyToLink+'" title="Reply to this post">'
footerStr+='<a href="/users/'+nickname+'?replyto='+replyToLink+'" title="'+translate['Reply to this post']+'">'
else:
footerStr+='<a href="/users/'+nickname+'?replyfollowers='+replyToLink+'" title="Reply to this post">'
footerStr+='<a href="/users/'+nickname+'?replyfollowers='+replyToLink+'" title="'+translate['Reply to this post']+'">'
else:
footerStr+='<a href="/users/'+nickname+'?replydm='+replyToLink+'" title="Reply to this post">'
footerStr+='<a href="/users/'+nickname+'?replydm='+replyToLink+'" title="'+translate['Reply to this post']+'">'
footerStr+='<img src="/icons/reply.png"/></a>'
footerStr+=announceStr+likeStr+deleteStr
footerStr+='<span class="'+timeClass+'">'+publishedStr+'</span>'
@ -1727,8 +1734,8 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
if not postJsonObject['object']['sensitive']:
contentStr=postJsonObject['object']['content']+attachmentStr
contentStr=addEmbeddedElements(contentStr)
contentStr=insertQuestion(nickname,contentStr,postJsonObject,pageNumber)
contentStr=addEmbeddedElements(translate,contentStr)
contentStr=insertQuestion(translate,nickname,contentStr,postJsonObject,pageNumber)
else:
postID='post'+str(createPassword(8))
contentStr=''
@ -1738,11 +1745,11 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \
containerClass='container report'
else:
contentStr+='<b>Sensitive</b> '
contentStr+='<button class="cwButton" onclick="showContentWarning('+"'"+postID+"'"+')">SHOW MORE</button>'
contentStr+='<button class="cwButton" onclick="showContentWarning('+"'"+postID+"'"+')">'+translate['SHOW MORE']+'</button>'
contentStr+='<div class="cwText" id="'+postID+'">'
contentStr+=postJsonObject['object']['content']+attachmentStr
contentStr=addEmbeddedElements(contentStr)
contentStr=insertQuestion(nickname,contentStr,postJsonObject,pageNumber)
contentStr=addEmbeddedElements(translate,contentStr)
contentStr=insertQuestion(translate,nickname,contentStr,postJsonObject,pageNumber)
contentStr+='</div>'
if postJsonObject['object'].get('tag'):
@ -1769,7 +1776,8 @@ def isQuestion(postObjectJson: {}) -> bool:
return True
return False
def htmlTimeline(pageNumber: int,itemsPerPage: int,session,baseDir: str, \
def htmlTimeline(translate: {},pageNumber: int, \
itemsPerPage: int,session,baseDir: str, \
wfRequest: {},personCache: {}, \
nickname: str,domain: str,port: int,timelineJson: {}, \
boxName: str,allowDeletion: bool, \
@ -1823,24 +1831,24 @@ def htmlTimeline(pageNumber: int,itemsPerPage: int,session,baseDir: str, \
if boxName!='dm':
if not manuallyApproveFollowers:
newPostButtonStr='<a href="'+actor+'/newpost"><img src="/icons/newpost.png" title="Create a new post" alt="Create a new post" class="right"/></a>'
newPostButtonStr='<a href="'+actor+'/newpost"><img src="/icons/newpost.png" title="'+translate['Create a new post']+'" alt="'+translate['Create a new post']+'" class="right"/></a>'
else:
newPostButtonStr='<a href="'+actor+'/newfollowers"><img src="/icons/newpost.png" title="Create a new post" alt="Create a new post" class="right"/></a>'
newPostButtonStr='<a href="'+actor+'/newfollowers"><img src="/icons/newpost.png" title="'+translate['Create a new post']+'" alt="'+translate['Create a new post']+'" class="right"/></a>'
else:
newPostButtonStr='<a href="'+actor+'/newdm"><img src="/icons/newpost.png" title="Create a new DM" alt="Create a new DM" class="right"/></a>'
newPostButtonStr='<a href="'+actor+'/newdm"><img src="/icons/newpost.png" title="'+translate['Create a new DM']+'" alt="'+translate['Create a new DM']+'" class="right"/></a>'
# banner and row of buttons
tlStr+= \
'<a href="/users/'+nickname+'" title="Switch to profile view" alt="Switch to profile view">' \
'<a href="/users/'+nickname+'" title="'+translate['Switch to profile view']+'" alt="'+translate['Switch to profile view']+'">' \
'<div class="timeline-banner">' \
'</div></a>' \
'<div class="container">\n'+ \
' <a href="'+actor+'/inbox"><button class="'+inboxButton+'"><span>Inbox</span></button></a>' \
' <a href="'+actor+'/dm"><button class="'+dmButton+'"><span>DM</span></button></a>' \
' <a href="'+actor+'/outbox"><button class="'+sentButton+'"><span>Outbox</span></button></a>'+ \
' <a href="'+actor+'/inbox"><button class="'+inboxButton+'"><span>'+translate['Inbox']+'</span></button></a>' \
' <a href="'+actor+'/dm"><button class="'+dmButton+'"><span>'+translate['DM']+'</span></button></a>' \
' <a href="'+actor+'/outbox"><button class="'+sentButton+'"><span>'+translate['Outbox']+'</span></button></a>'+ \
moderationButtonStr+newPostButtonStr+ \
' <a href="'+actor+'/search"><img src="/icons/search.png" title="Search and follow" alt="Search and follow" class="right"/></a>'+ \
' <a href="'+actor+'/'+boxName+'"><img src="/icons/refresh.png" title="Refresh" alt="Refresh" class="right"/></a>'+ \
' <a href="'+actor+'/search"><img src="/icons/search.png" title="'+translate['Search and follow']+'" alt="'+translate['Search and follow']+'" class="right"/></a>'+ \
' <a href="'+actor+'/'+boxName+'"><img src="/icons/refresh.png" title="'+translate['Refresh']+'" alt="'+translate['Refresh']+'" class="right"/></a>'+ \
followApprovals+ \
'</div>'
@ -1849,13 +1857,13 @@ def htmlTimeline(pageNumber: int,itemsPerPage: int,session,baseDir: str, \
tlStr+= \
'<form method="POST" action="/users/'+nickname+'/moderationaction">' \
'<div class="container">\n'+ \
' <input type="text" placeholder="Nickname or URL. Block using *@domain or nickname@domain" name="moderationAction" value="">' \
' <input type="submit" title="Remove the above item" name="submitRemove" value="Remove">' \
' <input type="submit" title="Suspend the above account nickname" name="submitSuspend" value="Suspend">' \
' <input type="submit" title="Remove a suspension for an account nickname" name="submitUnsuspend" value="Unsuspend">' \
' <input type="submit" title="Block an account on another instance" name="submitBlock" value="Block">' \
' <input type="submit" title="Unblock an account on another instance" name="submitUnblock" value="Unblock">' \
' <input type="submit" title="Information about current blocks/suspensions" name="submitInfo" value="Info">' \
' <input type="text" placeholder="'+translate['Nickname or URL. Block using *@domain or nickname@domain']+'" name="moderationAction" value="">' \
' <input type="submit" title="'+translate['Remove the above item']+'" name="submitRemove" value="'+translate['Remove']+'">' \
' <input type="submit" title="'+translate['Suspend the above account nickname']+'" name="submitSuspend" value="'+translate['Suspend']+'">' \
' <input type="submit" title="'+translate['Remove a suspension for an account nickname']+'" name="submitUnsuspend" value="'+translate['Unsuspend']+'">' \
' <input type="submit" title="'+translate['Block an account on another instance']+'" name="submitBlock" value="'+translate['Block']+'">' \
' <input type="submit" title="'+translate['Unblock an account on another instance']+'" name="submitUnblock" value="'+translate['Unblock']+'">' \
' <input type="submit" title="'+translate['Information about current blocks/suspensions']+'" name="submitInfo" value="'+translate['Info']+'">' \
'</div></form>'
# add the javascript for content warnings
@ -1872,7 +1880,7 @@ def htmlTimeline(pageNumber: int,itemsPerPage: int,session,baseDir: str, \
itemCtr+=1
avatarUrl=getPersonAvatarUrl(baseDir,item['actor'],personCache)
tlStr+= \
individualPostAsHtml(pageNumber, \
individualPostAsHtml(translate,pageNumber, \
baseDir,session,wfRequest,personCache, \
nickname,domain,port,item,avatarUrl,True, \
allowDeletion, \
@ -1936,14 +1944,15 @@ def htmlOutbox(pageNumber: int,itemsPerPage: int, \
nickname,domain,port,outboxJson,'outbox',allowDeletion, \
httpPrefix,projectVersion,manuallyApproveFollowers)
def htmlIndividualPost(baseDir: str,session,wfRequest: {},personCache: {}, \
def htmlIndividualPost(translate: {}, \
baseDir: str,session,wfRequest: {},personCache: {}, \
nickname: str,domain: str,port: int,authorized: bool, \
postJsonObject: {},httpPrefix: str,projectVersion: str) -> str:
"""Show an individual post as html
"""
postStr='<script>'+contentWarningScript()+'</script>'
postStr+= \
individualPostAsHtml(None,baseDir,session,wfRequest,personCache, \
individualPostAsHtml(translate,None,baseDir,session,wfRequest,personCache, \
nickname,domain,port,postJsonObject,None,True,False, \
httpPrefix,projectVersion,False,authorized,False,False)
messageId=postJsonObject['id'].replace('/activity','')
@ -1956,7 +1965,7 @@ def htmlIndividualPost(baseDir: str,session,wfRequest: {},personCache: {}, \
with open(postFilename, 'r') as fp:
postJsonObject=commentjson.load(fp)
postStr= \
individualPostAsHtml(None, \
individualPostAsHtml(translate,None, \
baseDir,session,wfRequest,personCache, \
nickname,domain,port,postJsonObject, \
None,True,False, \
@ -1975,14 +1984,15 @@ def htmlIndividualPost(baseDir: str,session,wfRequest: {},personCache: {}, \
# add items to the html output
for item in repliesJson['orderedItems']:
postStr+= \
individualPostAsHtml(None, \
individualPostAsHtml(translate,None, \
baseDir,session,wfRequest,personCache, \
nickname,domain,port,item,None,True,False, \
httpPrefix,projectVersion, \
False,authorized,False,False)
return htmlHeader()+postStr+htmlFooter()
def htmlPostReplies(baseDir: str,session,wfRequest: {},personCache: {}, \
def htmlPostReplies(translate: {},baseDir: str, \
session,wfRequest: {},personCache: {}, \
nickname: str,domain: str,port: int,repliesJson: {}, \
httpPrefix: str,projectVersion: str) -> str:
"""Show the replies to an individual post as html
@ -1990,13 +2000,16 @@ def htmlPostReplies(baseDir: str,session,wfRequest: {},personCache: {}, \
repliesStr=''
if repliesJson.get('orderedItems'):
for item in repliesJson['orderedItems']:
repliesStr+=individualPostAsHtml(None,baseDir,session,wfRequest,personCache, \
nickname,domain,port,item,None,True,False, \
httpPrefix,projectVersion,False,False,False,False)
repliesStr+= \
individualPostAsHtml(translate,None, \
baseDir,session,wfRequest,personCache, \
nickname,domain,port,item,None,True,False, \
httpPrefix,projectVersion, \
False,False,False,False)
return htmlHeader()+repliesStr+htmlFooter()
def htmlRemoveSharedItem(baseDir: str,actor: str,shareName: str) -> str:
def htmlRemoveSharedItem(translate: {},baseDir: str,actor: str,shareName: str) -> str:
"""Shows a screen asking to confirm the removal of a shared item
"""
nickname=getNicknameFromActor(actor)
@ -2028,13 +2041,13 @@ def htmlRemoveSharedItem(baseDir: str,actor: str,shareName: str) -> str:
sharesStr+=' <center>'
if sharedItemImageUrl:
sharesStr+=' <img src="'+sharedItemImageUrl+'"/>'
sharesStr+=' <p class="followText">Remove '+sharedItemDisplayName+' ?</p>'
sharesStr+=' <p class="followText">'+translate['Remove']+' '+sharedItemDisplayName+' ?</p>'
sharesStr+= \
' <form method="POST" action="'+actor+'/rmshare">' \
' <input type="hidden" name="actor" value="'+actor+'">' \
' <input type="hidden" name="shareName" value="'+shareName+'">' \
' <button type="submit" class="button" name="submitYes">Yes</button>' \
' <a href="'+actor+'/inbox'+'"><button class="button">No</button></a>' \
' <button type="submit" class="button" name="submitYes">'+translate['Yes']+'</button>' \
' <a href="'+actor+'/inbox'+'"><button class="button">'+translate['No']+'</button></a>' \
' </form>'
sharesStr+=' </center>'
sharesStr+=' </div>'
@ -2042,7 +2055,7 @@ def htmlRemoveSharedItem(baseDir: str,actor: str,shareName: str) -> str:
sharesStr+=htmlFooter()
return sharesStr
def htmlDeletePost(pageNumber: int, \
def htmlDeletePost(translate,pageNumber: int, \
session,baseDir: str,messageId: str, \
httpPrefix: str,projectVersion: str, \
wfRequest: {},personCache: {}) -> str:
@ -2072,23 +2085,29 @@ def htmlDeletePost(pageNumber: int, \
deletePostStr=htmlHeader(profileStyle)
deletePostStr+='<script>'+contentWarningScript()+'</script>'
deletePostStr+= \
individualPostAsHtml(pageNumber,baseDir,session,wfRequest,personCache, \
nickname,domain,port,postJsonObject,None,True,False, \
httpPrefix,projectVersion,False,False,False,False)
individualPostAsHtml(translate,pageNumber, \
baseDir,session,wfRequest,personCache, \
nickname,domain,port,postJsonObject, \
None,True,False, \
httpPrefix,projectVersion, \
False,False,False,False)
deletePostStr+='<center>'
deletePostStr+=' <p class="followText">Delete this post?</p>'
deletePostStr+=' <p class="followText">'+translate['Delete this post?']+'</p>'
deletePostStr+= \
' <form method="POST" action="'+actor+'/rmpost">' \
' <input type="hidden" name="pageNumber" value="'+str(pageNumber)+'">' \
' <input type="hidden" name="messageId" value="'+messageId+'">' \
' <button type="submit" class="button" name="submitYes">Yes</button>' \
' <a href="'+actor+'/inbox'+'"><button class="button">No</button></a>' \
' <button type="submit" class="button" name="submitYes">'+translate['Yes']+'</button>' \
' <a href="'+actor+'/inbox'+'"><button class="button">'+translate['No']+'</button></a>' \
' </form>'
deletePostStr+='</center>'
deletePostStr+=htmlFooter()
return deletePostStr
def htmlFollowConfirm(baseDir: str,originPathStr: str,followActor: str,followProfileUrl: str) -> str:
def htmlFollowConfirm(translate: {},baseDir: str, \
originPathStr: str, \
followActor: str, \
followProfileUrl: str) -> str:
"""Asks to confirm a follow
"""
followDomain,port=getDomainFromActor(followActor)
@ -2105,12 +2124,12 @@ def htmlFollowConfirm(baseDir: str,originPathStr: str,followActor: str,followPro
followStr+=' <center>'
followStr+=' <a href="'+followActor+'">'
followStr+=' <img src="'+followProfileUrl+'"/></a>'
followStr+=' <p class="followText">Follow '+getNicknameFromActor(followActor)+'@'+followDomain+' ?</p>'
followStr+=' <p class="followText">'+translate['Follow']+' '+getNicknameFromActor(followActor)+'@'+followDomain+' ?</p>'
followStr+= \
' <form method="POST" action="'+originPathStr+'/followconfirm">' \
' <input type="hidden" name="actor" value="'+followActor+'">' \
' <button type="submit" class="button" name="submitYes">Yes</button>' \
' <a href="'+originPathStr+'"><button class="button">No</button></a>' \
' <button type="submit" class="button" name="submitYes">'+translate['Yes']+'</button>' \
' <a href="'+originPathStr+'"><button class="button">'+translate['No']+'</button></a>' \
' </form>'
followStr+='</center>'
followStr+='</div>'
@ -2118,7 +2137,10 @@ def htmlFollowConfirm(baseDir: str,originPathStr: str,followActor: str,followPro
followStr+=htmlFooter()
return followStr
def htmlUnfollowConfirm(baseDir: str,originPathStr: str,followActor: str,followProfileUrl: str) -> str:
def htmlUnfollowConfirm(translate: {},baseDir: str, \
originPathStr: str, \
followActor: str, \
followProfileUrl: str) -> str:
"""Asks to confirm unfollowing an actor
"""
followDomain,port=getDomainFromActor(followActor)
@ -2135,12 +2157,12 @@ def htmlUnfollowConfirm(baseDir: str,originPathStr: str,followActor: str,followP
followStr+=' <center>'
followStr+=' <a href="'+followActor+'">'
followStr+=' <img src="'+followProfileUrl+'"/></a>'
followStr+=' <p class="followText">Stop following '+getNicknameFromActor(followActor)+'@'+followDomain+' ?</p>'
followStr+=' <p class="followText">'+translate['Stop following']+' '+getNicknameFromActor(followActor)+'@'+followDomain+' ?</p>'
followStr+= \
' <form method="POST" action="'+originPathStr+'/unfollowconfirm">' \
' <input type="hidden" name="actor" value="'+followActor+'">' \
' <button type="submit" class="button" name="submitYes">Yes</button>' \
' <a href="'+originPathStr+'"><button class="button">No</button></a>' \
' <button type="submit" class="button" name="submitYes">'+translate['Yes']+'</button>' \
' <a href="'+originPathStr+'"><button class="button">'+translate['No']+'</button></a>' \
' </form>'
followStr+='</center>'
followStr+='</div>'
@ -2148,7 +2170,12 @@ def htmlUnfollowConfirm(baseDir: str,originPathStr: str,followActor: str,followP
followStr+=htmlFooter()
return followStr
def htmlPersonOptions(baseDir: str,domain: str,originPathStr: str,optionsActor: str,optionsProfileUrl: str,optionsLink: str,pageNumber: int) -> str:
def htmlPersonOptions(translate: {},baseDir: str, \
domain: str,originPathStr: str, \
optionsActor: str, \
optionsProfileUrl: str, \
optionsLink: str, \
pageNumber: int) -> str:
"""Show options for a person: view/follow/block/report
"""
optionsDomain,optionsPort=getDomainFromActor(optionsActor)
@ -2188,18 +2215,18 @@ def htmlPersonOptions(baseDir: str,domain: str,originPathStr: str,optionsActor:
optionsStr+=' <center>'
optionsStr+=' <a href="'+optionsActor+'">'
optionsStr+=' <img src="'+optionsProfileUrl+'"/></a>'
optionsStr+=' <p class="optionsText">Options for @'+getNicknameFromActor(optionsActor)+'@'+optionsDomain+'</p>'
optionsStr+=' <p class="optionsText">'+translate['Options for']+' @'+getNicknameFromActor(optionsActor)+'@'+optionsDomain+'</p>'
optionsStr+= \
' <form method="POST" action="'+originPathStr+'/personoptions">' \
' <input type="hidden" name="pageNumber" value="'+str(pageNumber)+'">' \
' <input type="hidden" name="actor" value="'+optionsActor+'">' \
' <input type="hidden" name="avatarUrl" value="'+optionsProfileUrl+'">'+ \
optionsLinkStr+ \
' <button type="submit" class="button" name="submitView">View</button>' \
' <button type="submit" class="button" name="submit'+followStr+'">'+followStr+'</button>' \
' <button type="submit" class="button" name="submit'+blockStr+'">'+blockStr+'</button>' \
' <button type="submit" class="button" name="submitDM">DM</button>' \
' <button type="submit" class="button" name="submitReport">Report</button>' \
' <button type="submit" class="button" name="submitView">'+translate['View']+'</button>' \
' <button type="submit" class="button" name="submit'+followStr+'">'+translate[followStr]+'</button>' \
' <button type="submit" class="button" name="submit'+blockStr+'">'+translate[blockStr]+'</button>' \
' <button type="submit" class="button" name="submitDM">'+translate['DM']+'</button>' \
' <button type="submit" class="button" name="submitReport">'+translate['Report']+'</button>' \
' </form>'
optionsStr+='</center>'
optionsStr+='</div>'
@ -2207,37 +2234,43 @@ def htmlPersonOptions(baseDir: str,domain: str,originPathStr: str,optionsActor:
optionsStr+=htmlFooter()
return optionsStr
def htmlBlockConfirm(baseDir: str,originPathStr: str,blockActor: str,blockProfileUrl: str) -> str:
"""Asks to confirm a block
"""
blockDomain,port=getDomainFromActor(blockActor)
if os.path.isfile(baseDir+'/img/block-background.png'):
if not os.path.isfile(baseDir+'/accounts/block-background.png'):
copyfile(baseDir+'/img/block-background.png',baseDir+'/accounts/block-background.png')
#def htmlBlockConfirm(translate: {},baseDir: str, \
# originPathStr: str, \
# blockActor: str, \
# blockProfileUrl: str) -> str:
# """Asks to confirm a block
# """
# blockDomain,port=getDomainFromActor(blockActor)
#
# if os.path.isfile(baseDir+'/img/block-background.png'):
# if not os.path.isfile(baseDir+'/accounts/block-background.png'):
# copyfile(baseDir+'/img/block-background.png',baseDir+'/accounts/block-background.png')
#
# with open(baseDir+'/epicyon-follow.css', 'r') as cssFile:
# profileStyle = cssFile.read()
# blockStr=htmlHeader(profileStyle)
# blockStr+='<div class="block">'
# blockStr+=' <div class="blockAvatar">'
# blockStr+=' <center>'
# blockStr+=' <a href="'+blockActor+'">'
# blockStr+=' <img src="'+blockProfileUrl+'"/></a>'
# blockStr+=' <p class="blockText">'+translate['Block']+' '+getNicknameFromActor(blockActor)+'@'+blockDomain+' ?</p>'
# blockStr+= \
# ' <form method="POST" action="'+originPathStr+'/blockconfirm">' \
# ' <input type="hidden" name="actor" value="'+blockActor+'">' \
# ' <button type="submit" class="button" name="submitYes">'+translate['Yes']+'</button>' \
# ' <a href="'+originPathStr+'"><button class="button">'+translate['No']+'</button></a>' \
# ' </form>'
# blockStr+='</center>'
# blockStr+='</div>'
# blockStr+='</div>'
# blockStr+=htmlFooter()
# return blockStr
with open(baseDir+'/epicyon-follow.css', 'r') as cssFile:
profileStyle = cssFile.read()
blockStr=htmlHeader(profileStyle)
blockStr+='<div class="block">'
blockStr+=' <div class="blockAvatar">'
blockStr+=' <center>'
blockStr+=' <a href="'+blockActor+'">'
blockStr+=' <img src="'+blockProfileUrl+'"/></a>'
blockStr+=' <p class="blockText">Block '+getNicknameFromActor(blockActor)+'@'+blockDomain+' ?</p>'
blockStr+= \
' <form method="POST" action="'+originPathStr+'/blockconfirm">' \
' <input type="hidden" name="actor" value="'+blockActor+'">' \
' <button type="submit" class="button" name="submitYes">Yes</button>' \
' <a href="'+originPathStr+'"><button class="button">No</button></a>' \
' </form>'
blockStr+='</center>'
blockStr+='</div>'
blockStr+='</div>'
blockStr+=htmlFooter()
return blockStr
def htmlUnblockConfirm(baseDir: str,originPathStr: str,blockActor: str,blockProfileUrl: str) -> str:
def htmlUnblockConfirm(translate: {},baseDir: str, \
originPathStr: str, \
blockActor: str, \
blockProfileUrl: str) -> str:
"""Asks to confirm unblocking an actor
"""
blockDomain,port=getDomainFromActor(blockActor)
@ -2254,12 +2287,12 @@ def htmlUnblockConfirm(baseDir: str,originPathStr: str,blockActor: str,blockProf
blockStr+=' <center>'
blockStr+=' <a href="'+blockActor+'">'
blockStr+=' <img src="'+blockProfileUrl+'"/></a>'
blockStr+=' <p class="blockText">Stop blocking '+getNicknameFromActor(blockActor)+'@'+blockDomain+' ?</p>'
blockStr+=' <p class="blockText">'+translate['Stop blocking']+' '+getNicknameFromActor(blockActor)+'@'+blockDomain+' ?</p>'
blockStr+= \
' <form method="POST" action="'+originPathStr+'/unblockconfirm">' \
' <input type="hidden" name="actor" value="'+blockActor+'">' \
' <button type="submit" class="button" name="submitYes">Yes</button>' \
' <a href="'+originPathStr+'"><button class="button">No</button></a>' \
' <button type="submit" class="button" name="submitYes">'+translate['Yes']+'</button>' \
' <a href="'+originPathStr+'"><button class="button">'+translate['No']+'</button></a>' \
' </form>'
blockStr+='</center>'
blockStr+='</div>'
@ -2267,7 +2300,8 @@ def htmlUnblockConfirm(baseDir: str,originPathStr: str,blockActor: str,blockProf
blockStr+=htmlFooter()
return blockStr
def htmlSearchEmojiTextEntry(baseDir: str,path: str) -> str:
def htmlSearchEmojiTextEntry(translate: {}, \
baseDir: str,path: str) -> str:
"""Search for an emoji by name
"""
if not os.path.isfile(baseDir+'/emoji/emoji.json'):
@ -2287,12 +2321,12 @@ def htmlSearchEmojiTextEntry(baseDir: str,path: str) -> str:
emojiStr+='<div class="follow">'
emojiStr+=' <div class="followAvatar">'
emojiStr+=' <center>'
emojiStr+=' <p class="followText">Enter an emoji name to search for</p>'
emojiStr+=' <p class="followText">'+translate['Enter an emoji name to search for']+'</p>'
emojiStr+= \
' <form method="POST" action="'+actor+'/searchhandleemoji">' \
' <input type="hidden" name="actor" value="'+actor+'">' \
' <input type="text" name="searchtext" autofocus><br>' \
' <button type="submit" class="button" name="submitSearch">Submit</button>' \
' <button type="submit" class="button" name="submitSearch">'+translate['Submit']+'</button>' \
' </form>'
emojiStr+=' </center>'
emojiStr+=' </div>'
@ -2300,7 +2334,8 @@ def htmlSearchEmojiTextEntry(baseDir: str,path: str) -> str:
emojiStr+=htmlFooter()
return emojiStr
def htmlSearch(baseDir: str,path: str) -> str:
def htmlSearch(translate: {}, \
baseDir: str,path: str) -> str:
"""Search called from the timeline icon
"""
actor=path.replace('/search','')
@ -2317,12 +2352,12 @@ def htmlSearch(baseDir: str,path: str) -> str:
followStr+='<div class="follow">'
followStr+=' <div class="followAvatar">'
followStr+=' <center>'
followStr+=' <p class="followText">Enter an address, shared item, #hashtag, *skill or :emoji: to search for</p>'
followStr+=' <p class="followText">'+translate['Enter an address, shared item, #hashtag, *skill or :emoji: to search for']+'</p>'
followStr+= \
' <form method="POST" action="'+actor+'/searchhandle">' \
' <input type="hidden" name="actor" value="'+actor+'">' \
' <input type="text" name="searchtext" autofocus><br>' \
' <button type="submit" class="button" name="submitSearch">Submit</button>' \
' <button type="submit" class="button" name="submitSearch">'+translate['Submit']+'</button>' \
' </form>'
followStr+=' </center>'
followStr+=' </div>'
@ -2330,7 +2365,8 @@ def htmlSearch(baseDir: str,path: str) -> str:
followStr+=htmlFooter()
return followStr
def htmlProfileAfterSearch(baseDir: str,path: str,httpPrefix: str, \
def htmlProfileAfterSearch(translate: {}, \
baseDir: str,path: str,httpPrefix: str, \
nickname: str,domain: str,port: int, \
profileHandle: str, \
session,wfRequest: {},personCache: {},
@ -2434,8 +2470,8 @@ def htmlProfileAfterSearch(baseDir: str,path: str,httpPrefix: str, \
' <form method="POST" action="'+backUrl+'/followconfirm">' \
' <center>' \
' <input type="hidden" name="actor" value="'+personUrl+'">' \
' <button type="submit" class="button" name="submitYes">Follow</button>' \
' <a href="'+backUrl+'"><button class="button">Go Back</button></a>' \
' <button type="submit" class="button" name="submitYes">'+translate['Follow']+'</button>' \
' <a href="'+backUrl+'"><button class="button">'+translate['Go Back']+'</button></a>' \
' </center>' \
' </form>' \
'</div>'
@ -2453,7 +2489,7 @@ def htmlProfileAfterSearch(baseDir: str,path: str,httpPrefix: str, \
if not item.get('object'):
continue
profileStr+= \
individualPostAsHtml(None,baseDir, \
individualPostAsHtml(translate,None,baseDir, \
session,wfRequest,personCache, \
nickname,domain,port, \
item,avatarUrl,False,False, \