diff --git a/daemon.py b/daemon.py
index 4da348bde..77642227b 100644
--- a/daemon.py
+++ b/daemon.py
@@ -134,10 +134,10 @@ from webapp_timeline import htmlInboxBlogs
from webapp_timeline import htmlInboxNews
from webapp_timeline import htmlOutbox
from webapp_timeline import htmlModeration
+from webapp_create_post import htmlNewPost
from webapp import htmlLogin
from webapp import htmlSuspended
from webapp import htmlGetLoginCredentials
-from webapp import htmlNewPost
from webapp import htmlFollowConfirm
from webapp import htmlUnfollowConfirm
from webapp import htmlEditNewsPost
diff --git a/webapp.py b/webapp.py
index 01122e489..f51ff06ff 100644
--- a/webapp.py
+++ b/webapp.py
@@ -14,14 +14,12 @@ from utils import getNicknameFromActor
from utils import getDomainFromActor
from utils import locatePost
from utils import noOfAccounts
-from utils import isPublicPostFromUrl
from utils import loadJson
from utils import getConfigParam
from posts import isEditor
from shares import getValidSharedItemID
from webapp_utils import getAltPath
from webapp_utils import getIconsDir
-from webapp_utils import getBannerFile
from webapp_utils import htmlHeader
from webapp_utils import htmlFooter
from webapp_post import individualPostAsHtml
@@ -53,46 +51,6 @@ def htmlFollowingList(cssCache: {}, baseDir: str,
return ''
-def htmlFollowingDataList(baseDir: str, nickname: str,
- domain: str, domainFull: str) -> str:
- """Returns a datalist of handles being followed
- """
- listStr = '\n'
- followingFilename = \
- baseDir + '/accounts/' + nickname + '@' + domain + '/following.txt'
- if os.path.isfile(followingFilename):
- with open(followingFilename, 'r') as followingFile:
- msg = followingFile.read()
- # add your own handle, so that you can send DMs
- # to yourself as reminders
- msg += nickname + '@' + domainFull + '\n'
- # include petnames
- petnamesFilename = \
- baseDir + '/accounts/' + \
- nickname + '@' + domain + '/petnames.txt'
- if os.path.isfile(petnamesFilename):
- followingList = []
- with open(petnamesFilename, 'r') as petnamesFile:
- petStr = petnamesFile.read()
- # extract each petname and append it
- petnamesList = petStr.split('\n')
- for pet in petnamesList:
- followingList.append(pet.split(' ')[0])
- # add the following.txt entries
- followingList += msg.split('\n')
- else:
- # no petnames list exists - just use following.txt
- followingList = msg.split('\n')
- followingList.sort()
- if followingList:
- for followingAddress in followingList:
- if followingAddress:
- listStr += \
- '@' + followingAddress + ' \n'
- listStr += ' \n'
- return listStr
-
-
def htmlModerationInfo(cssCache: {}, translate: {},
baseDir: str, httpPrefix: str) -> str:
msgStr1 = \
@@ -524,684 +482,6 @@ def htmlSuspended(cssCache: {}, baseDir: str) -> str:
return suspendedForm
-def htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
- replyStr: str,
- translate: {},
- iconsDir: str,
- showPublicOnDropdown: bool,
- defaultTimeline: str,
- pathBase: str,
- dropdownNewPostSuffix: str,
- dropdownNewBlogSuffix: str,
- dropdownUnlistedSuffix: str,
- dropdownFollowersSuffix: str,
- dropdownDMSuffix: str,
- dropdownReminderSuffix: str,
- dropdownEventSuffix: str,
- dropdownReportSuffix: str) -> str:
- """Returns the html for a drop down list of new post types
- """
- dropDownContent = '
\n'
- dropDownContent += '
\n'
- dropDownContent += '
\n'
- dropDownContent += ' ' + \
- scopeDescription + ' \n'
- dropDownContent += '
\n'
- dropDownContent += '
\n'
- return dropDownContent
-
-
-def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
- baseDir: str, httpPrefix: str,
- path: str, inReplyTo: str,
- mentions: [],
- reportUrl: str, pageNumber: int,
- nickname: str, domain: str,
- domainFull: str,
- defaultTimeline: str, newswire: {}) -> str:
- """New post screen
- """
- iconsDir = getIconsDir(baseDir)
- replyStr = ''
-
- showPublicOnDropdown = True
- messageBoxHeight = 400
-
- # filename of the banner shown at the top
- bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain)
-
- if not path.endswith('/newshare'):
- if not path.endswith('/newreport'):
- if not inReplyTo or path.endswith('/newreminder'):
- newPostText = '' + \
- translate['Write your post text below.'] + '
\n'
- else:
- newPostText = \
- '' + \
- translate['Write your reply to'] + \
- ' ' + \
- translate['this post'] + '
\n'
- replyStr = ' \n'
-
- # if replying to a non-public post then also make
- # this post non-public
- if not isPublicPostFromUrl(baseDir, nickname, domain,
- inReplyTo):
- newPostPath = path
- if '?' in newPostPath:
- newPostPath = newPostPath.split('?')[0]
- if newPostPath.endswith('/newpost'):
- path = path.replace('/newpost', '/newfollowers')
- elif newPostPath.endswith('/newunlisted'):
- path = path.replace('/newunlisted', '/newfollowers')
- showPublicOnDropdown = False
- else:
- newPostText = \
- '' + \
- translate['Write your report below.'] + '
\n'
-
- # custom report header with any additional instructions
- if os.path.isfile(baseDir + '/accounts/report.txt'):
- with open(baseDir + '/accounts/report.txt', 'r') as file:
- customReportText = file.read()
- if '' not in customReportText:
- customReportText = \
- '' + \
- customReportText + '
\n'
- repStr = ''
- customReportText = \
- customReportText.replace('
', repStr)
- newPostText += customReportText
-
- idx = 'This message only goes to moderators, even if it ' + \
- 'mentions other fediverse addresses.'
- newPostText += \
- '
' + translate[idx] + '
\n' + \
- '' + translate['Also see'] + \
- ' ' + \
- translate['Terms of Service'] + '
\n'
- else:
- newPostText = \
- '' + \
- translate['Enter the details for your shared item below.'] + \
- '
\n'
-
- if path.endswith('/newquestion'):
- newPostText = \
- '' + \
- translate['Enter the choices for your question below.'] + \
- '
\n'
-
- if os.path.isfile(baseDir + '/accounts/newpost.txt'):
- with open(baseDir + '/accounts/newpost.txt', 'r') as file:
- newPostText = \
- '' + file.read() + '
\n'
-
- cssFilename = baseDir + '/epicyon-profile.css'
- if os.path.isfile(baseDir + '/epicyon.css'):
- cssFilename = baseDir + '/epicyon.css'
-
- newPostCSS = getCSS(baseDir, cssFilename, cssCache)
- if newPostCSS:
- if httpPrefix != 'https':
- newPostCSS = newPostCSS.replace('https://',
- httpPrefix + '://')
-
- if '?' in path:
- path = path.split('?')[0]
- pathBase = path.replace('/newreport', '').replace('/newpost', '')
- pathBase = pathBase.replace('/newblog', '').replace('/newshare', '')
- pathBase = pathBase.replace('/newunlisted', '')
- pathBase = pathBase.replace('/newevent', '')
- pathBase = pathBase.replace('/newreminder', '')
- pathBase = pathBase.replace('/newfollowers', '').replace('/newdm', '')
-
- newPostImageSection = ' '
- if not path.endswith('/newevent'):
- newPostImageSection += \
- ' ' + \
- translate['Image description'] + ' \n'
- else:
- newPostImageSection += \
- ' ' + \
- translate['Event banner image description'] + ' \n'
- newPostImageSection += \
- ' \n'
-
- if path.endswith('/newevent'):
- newPostImageSection += \
- ' ' + \
- translate['Banner image'] + ' \n'
- newPostImageSection += \
- ' \n'
- else:
- newPostImageSection += \
- ' \n'
- newPostImageSection += '
\n'
-
- scopeIcon = 'scope_public.png'
- scopeDescription = translate['Public']
- placeholderSubject = \
- translate['Subject or Content Warning (optional)'] + '...'
- placeholderMentions = ''
- if inReplyTo:
- # mentionsAndContent = getMentionsString(content)
- placeholderMentions = \
- translate['Replying to'] + '...'
- placeholderMessage = translate['Write something'] + '...'
- extraFields = ''
- endpoint = 'newpost'
- if path.endswith('/newblog'):
- placeholderSubject = translate['Title']
- scopeIcon = 'scope_blog.png'
- if defaultTimeline != 'tlnews':
- scopeDescription = translate['Blog']
- else:
- scopeDescription = translate['Article']
- endpoint = 'newblog'
- elif path.endswith('/newunlisted'):
- scopeIcon = 'scope_unlisted.png'
- scopeDescription = translate['Unlisted']
- endpoint = 'newunlisted'
- elif path.endswith('/newfollowers'):
- scopeIcon = 'scope_followers.png'
- scopeDescription = translate['Followers']
- endpoint = 'newfollowers'
- elif path.endswith('/newdm'):
- scopeIcon = 'scope_dm.png'
- scopeDescription = translate['DM']
- endpoint = 'newdm'
- elif path.endswith('/newreminder'):
- scopeIcon = 'scope_reminder.png'
- scopeDescription = translate['Reminder']
- endpoint = 'newreminder'
- elif path.endswith('/newevent'):
- scopeIcon = 'scope_event.png'
- scopeDescription = translate['Event']
- endpoint = 'newevent'
- placeholderSubject = translate['Event name']
- placeholderMessage = translate['Describe the event'] + '...'
- elif path.endswith('/newreport'):
- scopeIcon = 'scope_report.png'
- scopeDescription = translate['Report']
- endpoint = 'newreport'
- elif path.endswith('/newquestion'):
- scopeIcon = 'scope_question.png'
- scopeDescription = translate['Question']
- placeholderMessage = translate['Enter your question'] + '...'
- endpoint = 'newquestion'
- extraFields = '\n'
- extraFields += ' ' + \
- translate['Possible answers'] + ': \n'
- for questionCtr in range(8):
- extraFields += \
- ' \n'
- extraFields += \
- ' ' + \
- translate['Duration of listing in days'] + \
- ': \n'
- extraFields += '
'
- elif path.endswith('/newshare'):
- scopeIcon = 'scope_share.png'
- scopeDescription = translate['Shared Item']
- placeholderSubject = translate['Name of the shared item'] + '...'
- placeholderMessage = \
- translate['Description of the item being shared'] + '...'
- endpoint = 'newshare'
- extraFields = '\n'
- extraFields += \
- ' ' + \
- translate['Type of shared item. eg. hat'] + ': \n'
- extraFields += \
- ' \n'
- extraFields += \
- ' ' + \
- translate['Category of shared item. eg. clothing'] + ': \n'
- extraFields += \
- ' \n'
- extraFields += \
- ' ' + \
- translate['Duration of listing in days'] + ': \n'
- extraFields += ' \n'
- extraFields += '
\n'
- extraFields += '\n'
- extraFields += \
- '' + \
- translate['City or location of the shared item'] + ': \n'
- extraFields += ' \n'
- extraFields += '
\n'
-
- citationsStr = ''
- if endpoint == 'newblog':
- citationsFilename = \
- baseDir + '/accounts/' + \
- nickname + '@' + domain + '/.citations.txt'
- if os.path.isfile(citationsFilename):
- citationsStr = '\n'
- citationsStr += '
' + \
- translate['Citations'] + ':
\n'
- citationsStr += '
\n'
- citationsSeparator = '#####'
- with open(citationsFilename, "r") as f:
- citations = f.readlines()
- for line in citations:
- if citationsSeparator not in line:
- continue
- sections = line.strip().split(citationsSeparator)
- if len(sections) != 3:
- continue
- title = sections[1]
- link = sections[2]
- citationsStr += \
- ' ' + \
- title + ' '
- citationsStr += ' \n'
- citationsStr += '
\n'
-
- dateAndLocation = ''
- if endpoint != 'newshare' and \
- endpoint != 'newreport' and \
- endpoint != 'newquestion':
- dateAndLocation = '\n'
-
- if endpoint == 'newevent':
- # event status
- dateAndLocation += '' + \
- translate['Status of the event'] + ': \n'
- dateAndLocation += ' \n'
- dateAndLocation += '' + \
- translate['Tentative'] + ' \n'
- dateAndLocation += ' \n'
- dateAndLocation += '' + \
- translate['Confirmed'] + ' \n'
- dateAndLocation += ' \n'
- dateAndLocation += '' + \
- translate['Cancelled'] + ' \n'
- dateAndLocation += '
\n'
- dateAndLocation += '\n'
- # maximum attendees
- dateAndLocation += '' + \
- translate['Maximum attendees'] + ': \n'
- dateAndLocation += ' \n'
- dateAndLocation += '
\n'
- dateAndLocation += '\n'
- # event joining options
- dateAndLocation += '' + \
- translate['Joining'] + ': \n'
- dateAndLocation += ' \n'
- dateAndLocation += '' + \
- translate['Anyone can join'] + ' \n'
- dateAndLocation += ' \n'
- dateAndLocation += '' + \
- translate['Apply to join'] + ' \n'
- dateAndLocation += ' \n'
- dateAndLocation += '' + \
- translate['Invitation only'] + ' \n'
- dateAndLocation += '
\n'
- dateAndLocation += '\n'
- dateAndLocation += '\n'
- dateAndLocation += '\n'
- dateAndLocation += '' + \
- translate['Moderation policy or code of conduct'] + \
- ': \n'
- dateAndLocation += \
- ' \n'
- dateAndLocation += '
\n'
- dateAndLocation += '\n'
- dateAndLocation += '' + \
- translate['Location'] + ': \n'
- dateAndLocation += ' \n'
- if endpoint == 'newevent':
- dateAndLocation += '' + \
- translate['Ticket URL'] + ': \n'
- dateAndLocation += ' \n'
- dateAndLocation += '' + \
- translate['Categories'] + ': \n'
- dateAndLocation += ' \n'
- dateAndLocation += '
\n'
-
- newPostForm = htmlHeader(cssFilename, newPostCSS)
-
- newPostForm += \
- '\n'
- newPostForm += ' \n'
-
- mentionsStr = ''
- for m in mentions:
- mentionNickname = getNicknameFromActor(m)
- if not mentionNickname:
- continue
- mentionDomain, mentionPort = getDomainFromActor(m)
- if not mentionDomain:
- continue
- if mentionPort:
- mentionsHandle = \
- '@' + mentionNickname + '@' + \
- mentionDomain + ':' + str(mentionPort)
- else:
- mentionsHandle = '@' + mentionNickname + '@' + mentionDomain
- if mentionsHandle not in mentionsStr:
- mentionsStr += mentionsHandle + ' '
-
- # build suffixes so that any replies or mentions are
- # preserved when switching between scopes
- dropdownNewPostSuffix = '/newpost'
- dropdownNewBlogSuffix = '/newblog'
- dropdownUnlistedSuffix = '/newunlisted'
- dropdownFollowersSuffix = '/newfollowers'
- dropdownDMSuffix = '/newdm'
- dropdownEventSuffix = '/newevent'
- dropdownReminderSuffix = '/newreminder'
- dropdownReportSuffix = '/newreport'
- if inReplyTo or mentions:
- dropdownNewPostSuffix = ''
- dropdownNewBlogSuffix = ''
- dropdownUnlistedSuffix = ''
- dropdownFollowersSuffix = ''
- dropdownDMSuffix = ''
- dropdownEventSuffix = ''
- dropdownReminderSuffix = ''
- dropdownReportSuffix = ''
- if inReplyTo:
- dropdownNewPostSuffix += '?replyto=' + inReplyTo
- dropdownNewBlogSuffix += '?replyto=' + inReplyTo
- dropdownUnlistedSuffix += '?replyto=' + inReplyTo
- dropdownFollowersSuffix += '?replyfollowers=' + inReplyTo
- dropdownDMSuffix += '?replydm=' + inReplyTo
- for mentionedActor in mentions:
- dropdownNewPostSuffix += '?mention=' + mentionedActor
- dropdownNewBlogSuffix += '?mention=' + mentionedActor
- dropdownUnlistedSuffix += '?mention=' + mentionedActor
- dropdownFollowersSuffix += '?mention=' + mentionedActor
- dropdownDMSuffix += '?mention=' + mentionedActor
- dropdownReportSuffix += '?mention=' + mentionedActor
-
- dropDownContent = ''
- if not reportUrl:
- dropDownContent = \
- htmlNewPostDropDown(scopeIcon, scopeDescription,
- replyStr,
- translate,
- iconsDir,
- showPublicOnDropdown,
- defaultTimeline,
- pathBase,
- dropdownNewPostSuffix,
- dropdownNewBlogSuffix,
- dropdownUnlistedSuffix,
- dropdownFollowersSuffix,
- dropdownDMSuffix,
- dropdownReminderSuffix,
- dropdownEventSuffix,
- dropdownReportSuffix)
- else:
- mentionsStr = 'Re: ' + reportUrl + '\n\n' + mentionsStr
-
- newPostForm += \
- '\n'
-
- if not reportUrl:
- newPostForm = \
- newPostForm.replace('', '')
-
- newPostForm += htmlFooter()
- return newPostForm
-
-
def htmlRemoveSharedItem(cssCache: {}, translate: {}, baseDir: str,
actor: str, shareName: str,
callingDomain: str) -> str:
diff --git a/webapp_create_post.py b/webapp_create_post.py
new file mode 100644
index 000000000..b69edc7ee
--- /dev/null
+++ b/webapp_create_post.py
@@ -0,0 +1,735 @@
+__filename__ = "webapp_create_post.py"
+__author__ = "Bob Mottram"
+__license__ = "AGPL3+"
+__version__ = "1.1.0"
+__maintainer__ = "Bob Mottram"
+__email__ = "bob@freedombone.net"
+__status__ = "Production"
+
+import os
+from utils import isPublicPostFromUrl
+from utils import getCSS
+from utils import getNicknameFromActor
+from utils import getDomainFromActor
+from webapp_utils import getIconsDir
+from webapp_utils import getBannerFile
+from webapp_utils import htmlHeader
+from webapp_utils import htmlFooter
+
+
+def htmlFollowingDataList(baseDir: str, nickname: str,
+ domain: str, domainFull: str) -> str:
+ """Returns a datalist of handles being followed
+ """
+ listStr = '\n'
+ followingFilename = \
+ baseDir + '/accounts/' + nickname + '@' + domain + '/following.txt'
+ if os.path.isfile(followingFilename):
+ with open(followingFilename, 'r') as followingFile:
+ msg = followingFile.read()
+ # add your own handle, so that you can send DMs
+ # to yourself as reminders
+ msg += nickname + '@' + domainFull + '\n'
+ # include petnames
+ petnamesFilename = \
+ baseDir + '/accounts/' + \
+ nickname + '@' + domain + '/petnames.txt'
+ if os.path.isfile(petnamesFilename):
+ followingList = []
+ with open(petnamesFilename, 'r') as petnamesFile:
+ petStr = petnamesFile.read()
+ # extract each petname and append it
+ petnamesList = petStr.split('\n')
+ for pet in petnamesList:
+ followingList.append(pet.split(' ')[0])
+ # add the following.txt entries
+ followingList += msg.split('\n')
+ else:
+ # no petnames list exists - just use following.txt
+ followingList = msg.split('\n')
+ followingList.sort()
+ if followingList:
+ for followingAddress in followingList:
+ if followingAddress:
+ listStr += \
+ '@' + followingAddress + ' \n'
+ listStr += ' \n'
+ return listStr
+
+
+def htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
+ replyStr: str,
+ translate: {},
+ iconsDir: str,
+ showPublicOnDropdown: bool,
+ defaultTimeline: str,
+ pathBase: str,
+ dropdownNewPostSuffix: str,
+ dropdownNewBlogSuffix: str,
+ dropdownUnlistedSuffix: str,
+ dropdownFollowersSuffix: str,
+ dropdownDMSuffix: str,
+ dropdownReminderSuffix: str,
+ dropdownEventSuffix: str,
+ dropdownReportSuffix: str) -> str:
+ """Returns the html for a drop down list of new post types
+ """
+ dropDownContent = '\n'
+ dropDownContent += '
\n'
+ dropDownContent += '
\n'
+ dropDownContent += ' ' + \
+ scopeDescription + ' \n'
+ dropDownContent += '
\n'
+ dropDownContent += '
\n'
+ return dropDownContent
+
+
+def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
+ baseDir: str, httpPrefix: str,
+ path: str, inReplyTo: str,
+ mentions: [],
+ reportUrl: str, pageNumber: int,
+ nickname: str, domain: str,
+ domainFull: str,
+ defaultTimeline: str, newswire: {}) -> str:
+ """New post screen
+ """
+ iconsDir = getIconsDir(baseDir)
+ replyStr = ''
+
+ showPublicOnDropdown = True
+ messageBoxHeight = 400
+
+ # filename of the banner shown at the top
+ bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain)
+
+ if not path.endswith('/newshare'):
+ if not path.endswith('/newreport'):
+ if not inReplyTo or path.endswith('/newreminder'):
+ newPostText = '' + \
+ translate['Write your post text below.'] + '
\n'
+ else:
+ newPostText = \
+ '' + \
+ translate['Write your reply to'] + \
+ ' ' + \
+ translate['this post'] + '
\n'
+ replyStr = ' \n'
+
+ # if replying to a non-public post then also make
+ # this post non-public
+ if not isPublicPostFromUrl(baseDir, nickname, domain,
+ inReplyTo):
+ newPostPath = path
+ if '?' in newPostPath:
+ newPostPath = newPostPath.split('?')[0]
+ if newPostPath.endswith('/newpost'):
+ path = path.replace('/newpost', '/newfollowers')
+ elif newPostPath.endswith('/newunlisted'):
+ path = path.replace('/newunlisted', '/newfollowers')
+ showPublicOnDropdown = False
+ else:
+ newPostText = \
+ '' + \
+ translate['Write your report below.'] + '
\n'
+
+ # custom report header with any additional instructions
+ if os.path.isfile(baseDir + '/accounts/report.txt'):
+ with open(baseDir + '/accounts/report.txt', 'r') as file:
+ customReportText = file.read()
+ if '' not in customReportText:
+ customReportText = \
+ '' + \
+ customReportText + '
\n'
+ repStr = ''
+ customReportText = \
+ customReportText.replace('
', repStr)
+ newPostText += customReportText
+
+ idx = 'This message only goes to moderators, even if it ' + \
+ 'mentions other fediverse addresses.'
+ newPostText += \
+ '
' + translate[idx] + '
\n' + \
+ '' + translate['Also see'] + \
+ ' ' + \
+ translate['Terms of Service'] + '
\n'
+ else:
+ newPostText = \
+ '' + \
+ translate['Enter the details for your shared item below.'] + \
+ '
\n'
+
+ if path.endswith('/newquestion'):
+ newPostText = \
+ '' + \
+ translate['Enter the choices for your question below.'] + \
+ '
\n'
+
+ if os.path.isfile(baseDir + '/accounts/newpost.txt'):
+ with open(baseDir + '/accounts/newpost.txt', 'r') as file:
+ newPostText = \
+ '' + file.read() + '
\n'
+
+ cssFilename = baseDir + '/epicyon-profile.css'
+ if os.path.isfile(baseDir + '/epicyon.css'):
+ cssFilename = baseDir + '/epicyon.css'
+
+ newPostCSS = getCSS(baseDir, cssFilename, cssCache)
+ if newPostCSS:
+ if httpPrefix != 'https':
+ newPostCSS = newPostCSS.replace('https://',
+ httpPrefix + '://')
+
+ if '?' in path:
+ path = path.split('?')[0]
+ pathBase = path.replace('/newreport', '').replace('/newpost', '')
+ pathBase = pathBase.replace('/newblog', '').replace('/newshare', '')
+ pathBase = pathBase.replace('/newunlisted', '')
+ pathBase = pathBase.replace('/newevent', '')
+ pathBase = pathBase.replace('/newreminder', '')
+ pathBase = pathBase.replace('/newfollowers', '').replace('/newdm', '')
+
+ newPostImageSection = ' '
+ if not path.endswith('/newevent'):
+ newPostImageSection += \
+ ' ' + \
+ translate['Image description'] + ' \n'
+ else:
+ newPostImageSection += \
+ ' ' + \
+ translate['Event banner image description'] + ' \n'
+ newPostImageSection += \
+ ' \n'
+
+ if path.endswith('/newevent'):
+ newPostImageSection += \
+ ' ' + \
+ translate['Banner image'] + ' \n'
+ newPostImageSection += \
+ ' \n'
+ else:
+ newPostImageSection += \
+ ' \n'
+ newPostImageSection += '
\n'
+
+ scopeIcon = 'scope_public.png'
+ scopeDescription = translate['Public']
+ placeholderSubject = \
+ translate['Subject or Content Warning (optional)'] + '...'
+ placeholderMentions = ''
+ if inReplyTo:
+ # mentionsAndContent = getMentionsString(content)
+ placeholderMentions = \
+ translate['Replying to'] + '...'
+ placeholderMessage = translate['Write something'] + '...'
+ extraFields = ''
+ endpoint = 'newpost'
+ if path.endswith('/newblog'):
+ placeholderSubject = translate['Title']
+ scopeIcon = 'scope_blog.png'
+ if defaultTimeline != 'tlnews':
+ scopeDescription = translate['Blog']
+ else:
+ scopeDescription = translate['Article']
+ endpoint = 'newblog'
+ elif path.endswith('/newunlisted'):
+ scopeIcon = 'scope_unlisted.png'
+ scopeDescription = translate['Unlisted']
+ endpoint = 'newunlisted'
+ elif path.endswith('/newfollowers'):
+ scopeIcon = 'scope_followers.png'
+ scopeDescription = translate['Followers']
+ endpoint = 'newfollowers'
+ elif path.endswith('/newdm'):
+ scopeIcon = 'scope_dm.png'
+ scopeDescription = translate['DM']
+ endpoint = 'newdm'
+ elif path.endswith('/newreminder'):
+ scopeIcon = 'scope_reminder.png'
+ scopeDescription = translate['Reminder']
+ endpoint = 'newreminder'
+ elif path.endswith('/newevent'):
+ scopeIcon = 'scope_event.png'
+ scopeDescription = translate['Event']
+ endpoint = 'newevent'
+ placeholderSubject = translate['Event name']
+ placeholderMessage = translate['Describe the event'] + '...'
+ elif path.endswith('/newreport'):
+ scopeIcon = 'scope_report.png'
+ scopeDescription = translate['Report']
+ endpoint = 'newreport'
+ elif path.endswith('/newquestion'):
+ scopeIcon = 'scope_question.png'
+ scopeDescription = translate['Question']
+ placeholderMessage = translate['Enter your question'] + '...'
+ endpoint = 'newquestion'
+ extraFields = '\n'
+ extraFields += ' ' + \
+ translate['Possible answers'] + ': \n'
+ for questionCtr in range(8):
+ extraFields += \
+ ' \n'
+ extraFields += \
+ ' ' + \
+ translate['Duration of listing in days'] + \
+ ': \n'
+ extraFields += '
'
+ elif path.endswith('/newshare'):
+ scopeIcon = 'scope_share.png'
+ scopeDescription = translate['Shared Item']
+ placeholderSubject = translate['Name of the shared item'] + '...'
+ placeholderMessage = \
+ translate['Description of the item being shared'] + '...'
+ endpoint = 'newshare'
+ extraFields = '\n'
+ extraFields += \
+ ' ' + \
+ translate['Type of shared item. eg. hat'] + ': \n'
+ extraFields += \
+ ' \n'
+ extraFields += \
+ ' ' + \
+ translate['Category of shared item. eg. clothing'] + ': \n'
+ extraFields += \
+ ' \n'
+ extraFields += \
+ ' ' + \
+ translate['Duration of listing in days'] + ': \n'
+ extraFields += ' \n'
+ extraFields += '
\n'
+ extraFields += '\n'
+ extraFields += \
+ '' + \
+ translate['City or location of the shared item'] + ': \n'
+ extraFields += ' \n'
+ extraFields += '
\n'
+
+ citationsStr = ''
+ if endpoint == 'newblog':
+ citationsFilename = \
+ baseDir + '/accounts/' + \
+ nickname + '@' + domain + '/.citations.txt'
+ if os.path.isfile(citationsFilename):
+ citationsStr = '\n'
+ citationsStr += '
' + \
+ translate['Citations'] + ':
\n'
+ citationsStr += '
\n'
+ citationsSeparator = '#####'
+ with open(citationsFilename, "r") as f:
+ citations = f.readlines()
+ for line in citations:
+ if citationsSeparator not in line:
+ continue
+ sections = line.strip().split(citationsSeparator)
+ if len(sections) != 3:
+ continue
+ title = sections[1]
+ link = sections[2]
+ citationsStr += \
+ ' ' + \
+ title + ' '
+ citationsStr += ' \n'
+ citationsStr += '
\n'
+
+ dateAndLocation = ''
+ if endpoint != 'newshare' and \
+ endpoint != 'newreport' and \
+ endpoint != 'newquestion':
+ dateAndLocation = '\n'
+
+ if endpoint == 'newevent':
+ # event status
+ dateAndLocation += '' + \
+ translate['Status of the event'] + ': \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '' + \
+ translate['Tentative'] + ' \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '' + \
+ translate['Confirmed'] + ' \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '' + \
+ translate['Cancelled'] + ' \n'
+ dateAndLocation += '
\n'
+ dateAndLocation += '\n'
+ # maximum attendees
+ dateAndLocation += '' + \
+ translate['Maximum attendees'] + ': \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '
\n'
+ dateAndLocation += '\n'
+ # event joining options
+ dateAndLocation += '' + \
+ translate['Joining'] + ': \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '' + \
+ translate['Anyone can join'] + ' \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '' + \
+ translate['Apply to join'] + ' \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '' + \
+ translate['Invitation only'] + ' \n'
+ dateAndLocation += '
\n'
+ dateAndLocation += '\n'
+ dateAndLocation += '\n'
+ dateAndLocation += '\n'
+ dateAndLocation += '' + \
+ translate['Moderation policy or code of conduct'] + \
+ ': \n'
+ dateAndLocation += \
+ ' \n'
+ dateAndLocation += '
\n'
+ dateAndLocation += '\n'
+ dateAndLocation += '' + \
+ translate['Location'] + ': \n'
+ dateAndLocation += ' \n'
+ if endpoint == 'newevent':
+ dateAndLocation += '' + \
+ translate['Ticket URL'] + ': \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '' + \
+ translate['Categories'] + ': \n'
+ dateAndLocation += ' \n'
+ dateAndLocation += '
\n'
+
+ newPostForm = htmlHeader(cssFilename, newPostCSS)
+
+ newPostForm += \
+ '\n'
+ newPostForm += ' \n'
+
+ mentionsStr = ''
+ for m in mentions:
+ mentionNickname = getNicknameFromActor(m)
+ if not mentionNickname:
+ continue
+ mentionDomain, mentionPort = getDomainFromActor(m)
+ if not mentionDomain:
+ continue
+ if mentionPort:
+ mentionsHandle = \
+ '@' + mentionNickname + '@' + \
+ mentionDomain + ':' + str(mentionPort)
+ else:
+ mentionsHandle = '@' + mentionNickname + '@' + mentionDomain
+ if mentionsHandle not in mentionsStr:
+ mentionsStr += mentionsHandle + ' '
+
+ # build suffixes so that any replies or mentions are
+ # preserved when switching between scopes
+ dropdownNewPostSuffix = '/newpost'
+ dropdownNewBlogSuffix = '/newblog'
+ dropdownUnlistedSuffix = '/newunlisted'
+ dropdownFollowersSuffix = '/newfollowers'
+ dropdownDMSuffix = '/newdm'
+ dropdownEventSuffix = '/newevent'
+ dropdownReminderSuffix = '/newreminder'
+ dropdownReportSuffix = '/newreport'
+ if inReplyTo or mentions:
+ dropdownNewPostSuffix = ''
+ dropdownNewBlogSuffix = ''
+ dropdownUnlistedSuffix = ''
+ dropdownFollowersSuffix = ''
+ dropdownDMSuffix = ''
+ dropdownEventSuffix = ''
+ dropdownReminderSuffix = ''
+ dropdownReportSuffix = ''
+ if inReplyTo:
+ dropdownNewPostSuffix += '?replyto=' + inReplyTo
+ dropdownNewBlogSuffix += '?replyto=' + inReplyTo
+ dropdownUnlistedSuffix += '?replyto=' + inReplyTo
+ dropdownFollowersSuffix += '?replyfollowers=' + inReplyTo
+ dropdownDMSuffix += '?replydm=' + inReplyTo
+ for mentionedActor in mentions:
+ dropdownNewPostSuffix += '?mention=' + mentionedActor
+ dropdownNewBlogSuffix += '?mention=' + mentionedActor
+ dropdownUnlistedSuffix += '?mention=' + mentionedActor
+ dropdownFollowersSuffix += '?mention=' + mentionedActor
+ dropdownDMSuffix += '?mention=' + mentionedActor
+ dropdownReportSuffix += '?mention=' + mentionedActor
+
+ dropDownContent = ''
+ if not reportUrl:
+ dropDownContent = \
+ htmlNewPostDropDown(scopeIcon, scopeDescription,
+ replyStr,
+ translate,
+ iconsDir,
+ showPublicOnDropdown,
+ defaultTimeline,
+ pathBase,
+ dropdownNewPostSuffix,
+ dropdownNewBlogSuffix,
+ dropdownUnlistedSuffix,
+ dropdownFollowersSuffix,
+ dropdownDMSuffix,
+ dropdownReminderSuffix,
+ dropdownEventSuffix,
+ dropdownReportSuffix)
+ else:
+ mentionsStr = 'Re: ' + reportUrl + '\n\n' + mentionsStr
+
+ newPostForm += \
+ '\n'
+ newPostForm += ' \n'
+ newPostForm += \
+ '
' + newPostText + ' \n'
+ newPostForm += '
\n'
+ newPostForm += '
\n'
+ newPostForm += '' + dropDownContent + ' \n'
+
+ newPostForm += \
+ ' \n'
+ newPostForm += ' \n'
+ newPostForm += '
\n'
+ newPostForm += '
\n'
+
+ newPostForm += '
\n'
+
+ newPostForm += replyStr
+ if mediaInstance and not replyStr:
+ newPostForm += newPostImageSection
+
+ newPostForm += \
+ '
' + placeholderSubject + ' '
+ newPostForm += '
'
+ newPostForm += ''
+
+ selectedStr = ' selected'
+ if inReplyTo or endpoint == 'newdm':
+ if inReplyTo:
+ newPostForm += \
+ '
' + placeholderMentions + \
+ ' \n'
+ else:
+ newPostForm += \
+ '
' \
+ '' + \
+ translate['Send to'] + ':' + ' 📄 \n'
+ newPostForm += \
+ '
\n'
+ newPostForm += \
+ htmlFollowingDataList(baseDir, nickname, domain, domainFull)
+ newPostForm += ''
+ selectedStr = ''
+
+ newPostForm += \
+ '
' + placeholderMessage + ' '
+ if mediaInstance:
+ messageBoxHeight = 200
+
+ if endpoint == 'newquestion':
+ messageBoxHeight = 100
+ elif endpoint == 'newblog':
+ messageBoxHeight = 800
+
+ newPostForm += \
+ '
\n'
+ newPostForm += extraFields + citationsStr + dateAndLocation
+ if not mediaInstance or replyStr:
+ newPostForm += newPostImageSection
+ newPostForm += '
\n'
+ newPostForm += ' \n'
+
+ if not reportUrl:
+ newPostForm = \
+ newPostForm.replace('', '')
+
+ newPostForm += htmlFooter()
+ return newPostForm