mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon
commit
29613d4732
340
daemon.py
340
daemon.py
|
|
@ -81,7 +81,6 @@ from posts import createBlogPost
|
|||
from posts import createReportPost
|
||||
from posts import createUnlistedPost
|
||||
from posts import createFollowersOnlyPost
|
||||
from posts import createEventPost
|
||||
from posts import createDirectMessagePost
|
||||
from posts import populateRepliesJson
|
||||
from posts import addToField
|
||||
|
|
@ -114,7 +113,6 @@ from threads import threadWithTrace
|
|||
from threads import removeDormantThreads
|
||||
from media import replaceYouTube
|
||||
from media import attachMedia
|
||||
from media import pathIsImage
|
||||
from media import pathIsVideo
|
||||
from media import pathIsAudio
|
||||
from blocking import updateBlockedCache
|
||||
|
|
@ -161,7 +159,6 @@ from webapp_person_options import htmlPersonOptions
|
|||
from webapp_timeline import htmlShares
|
||||
from webapp_timeline import htmlInbox
|
||||
from webapp_timeline import htmlBookmarks
|
||||
from webapp_timeline import htmlEvents
|
||||
from webapp_timeline import htmlInboxDMs
|
||||
from webapp_timeline import htmlInboxReplies
|
||||
from webapp_timeline import htmlInboxMedia
|
||||
|
|
@ -256,6 +253,7 @@ from utils import saveJson
|
|||
from utils import isSuspended
|
||||
from utils import dangerousMarkup
|
||||
from utils import refreshNewswire
|
||||
from utils import isImageFile
|
||||
from manualapprove import manualDenyFollowRequest
|
||||
from manualapprove import manualApproveFollowRequest
|
||||
from announce import createAnnounce
|
||||
|
|
@ -1724,7 +1722,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
print('moderationText: ' + moderationText)
|
||||
nickname = moderationText
|
||||
if nickname.startswith('http') or \
|
||||
nickname.startswith('dat'):
|
||||
nickname.startswith('hyper'):
|
||||
nickname = getNicknameFromActor(nickname)
|
||||
if '@' in nickname:
|
||||
nickname = nickname.split('@')[0]
|
||||
|
|
@ -1739,7 +1737,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
if moderationButton == 'block':
|
||||
fullBlockDomain = None
|
||||
if moderationText.startswith('http') or \
|
||||
moderationText.startswith('dat'):
|
||||
moderationText.startswith('hyper'):
|
||||
# https://domain
|
||||
blockDomain, blockPort = \
|
||||
getDomainFromActor(moderationText)
|
||||
|
|
@ -1757,7 +1755,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
if moderationButton == 'unblock':
|
||||
fullBlockDomain = None
|
||||
if moderationText.startswith('http') or \
|
||||
moderationText.startswith('dat'):
|
||||
moderationText.startswith('hyper'):
|
||||
# https://domain
|
||||
blockDomain, blockPort = \
|
||||
getDomainFromActor(moderationText)
|
||||
|
|
@ -5926,7 +5924,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
GETstartTime, GETtimings: {}) -> None:
|
||||
"""Returns a media file
|
||||
"""
|
||||
if pathIsImage(path) or \
|
||||
if isImageFile(path) or \
|
||||
pathIsVideo(path) or \
|
||||
pathIsAudio(path):
|
||||
mediaStr = path.split('/media/')[1]
|
||||
|
|
@ -5956,7 +5954,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
GETstartTime, GETtimings: {}) -> None:
|
||||
"""Returns an emoji image
|
||||
"""
|
||||
if pathIsImage(path):
|
||||
if isImageFile(path):
|
||||
emojiStr = path.split('/emoji/')[1]
|
||||
emojiFilename = baseDir + '/emoji/' + emojiStr
|
||||
if os.path.isfile(emojiFilename):
|
||||
|
|
@ -9043,138 +9041,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.GETbusy = False
|
||||
return True
|
||||
|
||||
def _showEventsTimeline(self, authorized: bool,
|
||||
callingDomain: str, path: str,
|
||||
baseDir: str, httpPrefix: str,
|
||||
domain: str, domainFull: str, port: int,
|
||||
onionDomain: str, i2pDomain: str,
|
||||
GETstartTime, GETtimings: {},
|
||||
proxyType: str, cookie: str,
|
||||
debug: str) -> bool:
|
||||
"""Shows the events timeline
|
||||
"""
|
||||
if '/users/' in path:
|
||||
if authorized:
|
||||
# convert /events to /tlevents
|
||||
if path.endswith('/events') or \
|
||||
'/events?page=' in path:
|
||||
path = path.replace('/events', '/tlevents')
|
||||
eventsFeed = \
|
||||
personBoxJson(self.server.recentPostsCache,
|
||||
self.server.session,
|
||||
baseDir,
|
||||
domain,
|
||||
port,
|
||||
path,
|
||||
httpPrefix,
|
||||
maxPostsInFeed, 'tlevents',
|
||||
authorized,
|
||||
0, self.server.positiveVoting,
|
||||
self.server.votingTimeMins)
|
||||
print('eventsFeed: ' + str(eventsFeed))
|
||||
if eventsFeed:
|
||||
if self._requestHTTP():
|
||||
nickname = path.replace('/users/', '')
|
||||
nickname = nickname.replace('/tlevents', '')
|
||||
pageNumber = 1
|
||||
if '?page=' in nickname:
|
||||
pageNumber = nickname.split('?page=')[1]
|
||||
nickname = nickname.split('?page=')[0]
|
||||
if pageNumber.isdigit():
|
||||
pageNumber = int(pageNumber)
|
||||
else:
|
||||
pageNumber = 1
|
||||
if 'page=' not in path:
|
||||
# if no page was specified then show the first
|
||||
eventsFeed = \
|
||||
personBoxJson(self.server.recentPostsCache,
|
||||
self.server.session,
|
||||
baseDir,
|
||||
domain,
|
||||
port,
|
||||
path + '?page=1',
|
||||
httpPrefix,
|
||||
maxPostsInFeed,
|
||||
'tlevents',
|
||||
authorized,
|
||||
0, self.server.positiveVoting,
|
||||
self.server.votingTimeMins)
|
||||
fullWidthTimelineButtonHeader = \
|
||||
self.server.fullWidthTimelineButtonHeader
|
||||
minimalNick = isMinimal(baseDir, domain, nickname)
|
||||
|
||||
accessKeys = self.server.accessKeys
|
||||
if self.server.keyShortcuts.get(nickname):
|
||||
accessKeys = \
|
||||
self.server.keyShortcuts[nickname]
|
||||
|
||||
msg = \
|
||||
htmlEvents(self.server.cssCache,
|
||||
self.server.defaultTimeline,
|
||||
self.server.recentPostsCache,
|
||||
self.server.maxRecentPosts,
|
||||
self.server.translate,
|
||||
pageNumber, maxPostsInFeed,
|
||||
self.server.session,
|
||||
baseDir,
|
||||
self.server.cachedWebfingers,
|
||||
self.server.personCache,
|
||||
nickname,
|
||||
domain,
|
||||
port,
|
||||
eventsFeed,
|
||||
self.server.allowDeletion,
|
||||
httpPrefix,
|
||||
self.server.projectVersion,
|
||||
minimalNick,
|
||||
self.server.YTReplacementDomain,
|
||||
self.server.showPublishedDateOnly,
|
||||
self.server.newswire,
|
||||
self.server.positiveVoting,
|
||||
self.server.showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
self.server.iconsAsButtons,
|
||||
self.server.rssIconAtTop,
|
||||
self.server.publishButtonAtTop,
|
||||
authorized,
|
||||
self.server.themeName,
|
||||
self.server.peertubeInstances,
|
||||
self.server.allowLocalNetworkAccess,
|
||||
self.server.textModeBanner,
|
||||
accessKeys)
|
||||
msg = msg.encode('utf-8')
|
||||
msglen = len(msg)
|
||||
self._set_headers('text/html', msglen,
|
||||
cookie, callingDomain)
|
||||
self._write(msg)
|
||||
self._benchmarkGETtimings(GETstartTime, GETtimings,
|
||||
'show bookmarks 2 done',
|
||||
'show events')
|
||||
else:
|
||||
# don't need authenticated fetch here because
|
||||
# there is already the authorization check
|
||||
msg = json.dumps(eventsFeed,
|
||||
ensure_ascii=False)
|
||||
msg = msg.encode('utf-8')
|
||||
msglen = len(msg)
|
||||
self._set_headers('application/json', msglen,
|
||||
None, callingDomain)
|
||||
self._write(msg)
|
||||
self.server.GETbusy = False
|
||||
return True
|
||||
else:
|
||||
if debug:
|
||||
nickname = path.replace('/users/', '')
|
||||
nickname = nickname.replace('/tlevents', '')
|
||||
print('DEBUG: ' + nickname +
|
||||
' was not authorized to access ' + path)
|
||||
if debug:
|
||||
print('DEBUG: GET access to events is unauthorized')
|
||||
self.send_response(405)
|
||||
self.end_headers()
|
||||
self.server.GETbusy = False
|
||||
return True
|
||||
|
||||
def _showOutboxTimeline(self, authorized: bool,
|
||||
callingDomain: str, path: str,
|
||||
baseDir: str, httpPrefix: str,
|
||||
|
|
@ -10202,7 +10068,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
GETstartTime, GETtimings: {}) -> bool:
|
||||
"""Show a shared item image
|
||||
"""
|
||||
if not pathIsImage(path):
|
||||
if not isImageFile(path):
|
||||
self._404()
|
||||
return True
|
||||
|
||||
|
|
@ -10252,7 +10118,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
if '/accounts/avatars/' not in path:
|
||||
if '/accounts/headers/' not in path:
|
||||
return False
|
||||
if not pathIsImage(path):
|
||||
if not isImageFile(path):
|
||||
return False
|
||||
if '/accounts/avatars/' in path:
|
||||
avatarStr = path.split('/accounts/avatars/')[1]
|
||||
|
|
@ -10385,7 +10251,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
# Various types of new post in the web interface
|
||||
newPostEnd = ('newpost', 'newblog', 'newunlisted',
|
||||
'newfollowers', 'newdm', 'newreminder',
|
||||
'newevent', 'newreport', 'newquestion',
|
||||
'newreport', 'newquestion',
|
||||
'newshare')
|
||||
for postType in newPostEnd:
|
||||
if path.endswith('/' + postType):
|
||||
|
|
@ -10578,44 +10444,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
return True
|
||||
return False
|
||||
|
||||
def _editEvent(self, callingDomain: str, path: str,
|
||||
httpPrefix: str, domain: str, domainFull: str,
|
||||
baseDir: str, translate: {},
|
||||
mediaInstance: bool,
|
||||
cookie: str) -> bool:
|
||||
"""Show edit event screen
|
||||
"""
|
||||
messageId = path.split('?editeventpost=')[1]
|
||||
if '?' in messageId:
|
||||
messageId = messageId.split('?')[0]
|
||||
actor = path.split('?actor=')[1]
|
||||
if '?' in actor:
|
||||
actor = actor.split('?')[0]
|
||||
nickname = getNicknameFromActor(path)
|
||||
if nickname == actor:
|
||||
# postUrl = \
|
||||
# httpPrefix + '://' + \
|
||||
# domainFull + '/users/' + nickname + \
|
||||
# '/statuses/' + messageId
|
||||
msg = None
|
||||
# TODO
|
||||
# htmlEditEvent(mediaInstance,
|
||||
# translate,
|
||||
# baseDir,
|
||||
# httpPrefix,
|
||||
# path,
|
||||
# nickname, domain,
|
||||
# postUrl)
|
||||
if msg:
|
||||
msg = msg.encode('utf-8')
|
||||
msglen = len(msg)
|
||||
self._set_headers('text/html', msglen,
|
||||
cookie, callingDomain)
|
||||
self._write(msg)
|
||||
self.server.GETbusy = False
|
||||
return True
|
||||
return False
|
||||
|
||||
def _getFollowingJson(self, baseDir: str, path: str,
|
||||
callingDomain: str,
|
||||
httpPrefix: str,
|
||||
|
|
@ -11474,7 +11302,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
|
||||
# if not authorized then show the login screen
|
||||
if htmlGET and self.path != '/login' and \
|
||||
not pathIsImage(self.path) and \
|
||||
not isImageFile(self.path) and \
|
||||
self.path != '/' and \
|
||||
self.path != '/users/news/linksmobile' and \
|
||||
self.path != '/users/news/newswiremobile':
|
||||
|
|
@ -12498,21 +12326,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.GETbusy = False
|
||||
return
|
||||
|
||||
# Edit an event
|
||||
if authorized and \
|
||||
'/tlevents' in self.path and \
|
||||
'?editeventpost=' in self.path and \
|
||||
'?actor=' in self.path:
|
||||
if self._editEvent(callingDomain, self.path,
|
||||
self.server.httpPrefix,
|
||||
self.server.domain,
|
||||
self.server.domainFull,
|
||||
self.server.baseDir,
|
||||
self.server.translate,
|
||||
self.server.mediaInstance,
|
||||
cookie):
|
||||
return
|
||||
|
||||
# edit profile in web interface
|
||||
if self._editProfile(callingDomain, self.path,
|
||||
self.server.translate,
|
||||
|
|
@ -12931,29 +12744,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
'show shares 2 done',
|
||||
'show bookmarks 2 done')
|
||||
|
||||
# get the events for a given person
|
||||
if self.path.endswith('/tlevents') or \
|
||||
'/tlevents?page=' in self.path or \
|
||||
self.path.endswith('/events') or \
|
||||
'/events?page=' in self.path:
|
||||
if self._showEventsTimeline(authorized,
|
||||
callingDomain, self.path,
|
||||
self.server.baseDir,
|
||||
self.server.httpPrefix,
|
||||
self.server.domain,
|
||||
self.server.domainFull,
|
||||
self.server.port,
|
||||
self.server.onionDomain,
|
||||
self.server.i2pDomain,
|
||||
GETstartTime, GETtimings,
|
||||
self.server.proxyType,
|
||||
cookie, self.server.debug):
|
||||
return
|
||||
|
||||
self._benchmarkGETtimings(GETstartTime, GETtimings,
|
||||
'show bookmarks 2 done',
|
||||
'show events done')
|
||||
|
||||
# outbox timeline
|
||||
if self._showOutboxTimeline(authorized,
|
||||
callingDomain, self.path,
|
||||
|
|
@ -13135,7 +12925,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
fileLength = -1
|
||||
|
||||
if '/media/' in self.path:
|
||||
if pathIsImage(self.path) or \
|
||||
if isImageFile(self.path) or \
|
||||
pathIsVideo(self.path) or \
|
||||
pathIsAudio(self.path):
|
||||
mediaStr = self.path.split('/media/')[1]
|
||||
|
|
@ -13235,12 +13025,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
print('DEBUG: no media filename in POST')
|
||||
|
||||
if filename:
|
||||
if filename.endswith('.png') or \
|
||||
filename.endswith('.jpg') or \
|
||||
filename.endswith('.webp') or \
|
||||
filename.endswith('.avif') or \
|
||||
filename.endswith('.svg') or \
|
||||
filename.endswith('.gif'):
|
||||
if isImageFile(filename):
|
||||
postImageFilename = filename.replace('.temp', '')
|
||||
print('Removing metadata from ' + postImageFilename)
|
||||
city = getSpoofedCity(self.server.city,
|
||||
|
|
@ -13338,11 +13123,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
else:
|
||||
commentsEnabled = True
|
||||
|
||||
if not fields.get('privateEvent'):
|
||||
privateEvent = False
|
||||
else:
|
||||
privateEvent = True
|
||||
|
||||
if postType == 'newpost':
|
||||
if not fields.get('pinToProfile'):
|
||||
pinToProfile = False
|
||||
|
|
@ -13425,14 +13205,20 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
print('WARN: blog posts must have content')
|
||||
return -1
|
||||
# submit button on newblog screen
|
||||
followersOnly = False
|
||||
saveToFile = False
|
||||
clientToServer = False
|
||||
city = None
|
||||
messageJson = \
|
||||
createBlogPost(self.server.baseDir, nickname,
|
||||
self.server.domain, self.server.port,
|
||||
self.server.httpPrefix,
|
||||
fields['message'],
|
||||
False, False, False, commentsEnabled,
|
||||
followersOnly, saveToFile,
|
||||
clientToServer, commentsEnabled,
|
||||
filename, attachmentMediaType,
|
||||
fields['imageDescription'],
|
||||
city,
|
||||
fields['replyTo'], fields['replyTo'],
|
||||
fields['subject'],
|
||||
fields['schedulePost'],
|
||||
|
|
@ -13545,13 +13331,17 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.baseDir,
|
||||
nickname,
|
||||
self.server.domain)
|
||||
followersOnly = False
|
||||
saveToFile = False
|
||||
clientToServer = False
|
||||
messageJson = \
|
||||
createUnlistedPost(self.server.baseDir,
|
||||
nickname,
|
||||
self.server.domain, self.server.port,
|
||||
self.server.httpPrefix,
|
||||
mentionsStr + fields['message'],
|
||||
False, False, False, commentsEnabled,
|
||||
followersOnly, saveToFile,
|
||||
clientToServer, commentsEnabled,
|
||||
filename, attachmentMediaType,
|
||||
fields['imageDescription'],
|
||||
city,
|
||||
|
|
@ -13580,6 +13370,9 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.baseDir,
|
||||
nickname,
|
||||
self.server.domain)
|
||||
followersOnly = True
|
||||
saveToFile = False
|
||||
clientToServer = False
|
||||
messageJson = \
|
||||
createFollowersOnlyPost(self.server.baseDir,
|
||||
nickname,
|
||||
|
|
@ -13587,7 +13380,8 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.port,
|
||||
self.server.httpPrefix,
|
||||
mentionsStr + fields['message'],
|
||||
True, False, False,
|
||||
followersOnly, saveToFile,
|
||||
clientToServer,
|
||||
commentsEnabled,
|
||||
filename, attachmentMediaType,
|
||||
fields['imageDescription'],
|
||||
|
|
@ -13612,64 +13406,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
return 1
|
||||
else:
|
||||
return -1
|
||||
elif postType == 'newevent':
|
||||
# A Mobilizon-type event is posted
|
||||
|
||||
# if there is no image dscription then make it the same
|
||||
# as the event title
|
||||
if not fields.get('imageDescription'):
|
||||
fields['imageDescription'] = fields['subject']
|
||||
# Events are public by default, with opt-in
|
||||
# followers only status
|
||||
if not fields.get('followersOnlyEvent'):
|
||||
fields['followersOnlyEvent'] = False
|
||||
|
||||
if not fields.get('anonymousParticipationEnabled'):
|
||||
anonymousParticipationEnabled = False
|
||||
else:
|
||||
anonymousParticipationEnabled = True
|
||||
maximumAttendeeCapacity = 999999
|
||||
if fields.get('maximumAttendeeCapacity'):
|
||||
maximumAttendeeCapacity = \
|
||||
int(fields['maximumAttendeeCapacity'])
|
||||
|
||||
city = getSpoofedCity(self.server.city,
|
||||
self.server.baseDir,
|
||||
nickname,
|
||||
self.server.domain)
|
||||
messageJson = \
|
||||
createEventPost(self.server.baseDir,
|
||||
nickname,
|
||||
self.server.domain,
|
||||
self.server.port,
|
||||
self.server.httpPrefix,
|
||||
mentionsStr + fields['message'],
|
||||
privateEvent,
|
||||
False, False, commentsEnabled,
|
||||
filename, attachmentMediaType,
|
||||
fields['imageDescription'],
|
||||
city,
|
||||
fields['subject'],
|
||||
fields['schedulePost'],
|
||||
fields['eventDate'],
|
||||
fields['eventTime'],
|
||||
fields['location'],
|
||||
fields['category'],
|
||||
fields['joinMode'],
|
||||
fields['endDate'],
|
||||
fields['endTime'],
|
||||
maximumAttendeeCapacity,
|
||||
fields['repliesModerationOption'],
|
||||
anonymousParticipationEnabled,
|
||||
fields['eventStatus'],
|
||||
fields['ticketUrl'])
|
||||
if messageJson:
|
||||
if fields['schedulePost']:
|
||||
return 1
|
||||
if self._postToOutbox(messageJson, __version__, nickname):
|
||||
return 1
|
||||
else:
|
||||
return -1
|
||||
elif postType == 'newdm':
|
||||
messageJson = None
|
||||
print('A DM was posted')
|
||||
|
|
@ -13678,6 +13414,9 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.baseDir,
|
||||
nickname,
|
||||
self.server.domain)
|
||||
followersOnly = True
|
||||
saveToFile = False
|
||||
clientToServer = False
|
||||
messageJson = \
|
||||
createDirectMessagePost(self.server.baseDir,
|
||||
nickname,
|
||||
|
|
@ -13686,7 +13425,8 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.httpPrefix,
|
||||
mentionsStr +
|
||||
fields['message'],
|
||||
True, False, False,
|
||||
followersOnly, saveToFile,
|
||||
clientToServer,
|
||||
commentsEnabled,
|
||||
filename, attachmentMediaType,
|
||||
fields['imageDescription'],
|
||||
|
|
@ -13723,6 +13463,10 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.baseDir,
|
||||
nickname,
|
||||
self.server.domain)
|
||||
followersOnly = True
|
||||
saveToFile = False
|
||||
clientToServer = False
|
||||
commentsEnabled = False
|
||||
messageJson = \
|
||||
createDirectMessagePost(self.server.baseDir,
|
||||
nickname,
|
||||
|
|
@ -13730,7 +13474,8 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.port,
|
||||
self.server.httpPrefix,
|
||||
mentionsStr + fields['message'],
|
||||
True, False, False, False,
|
||||
followersOnly, saveToFile,
|
||||
clientToServer, commentsEnabled,
|
||||
filename, attachmentMediaType,
|
||||
fields['imageDescription'],
|
||||
city,
|
||||
|
|
@ -14172,7 +13917,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
if not self.path.endswith('confirm'):
|
||||
self.path = self.path.replace('/outbox/', '/outbox')
|
||||
self.path = self.path.replace('/tlblogs/', '/tlblogs')
|
||||
self.path = self.path.replace('/tlevents/', '/tlevents')
|
||||
self.path = self.path.replace('/inbox/', '/inbox')
|
||||
self.path = self.path.replace('/shares/', '/shares')
|
||||
self.path = self.path.replace('/sharedInbox/', '/sharedInbox')
|
||||
|
|
@ -14510,7 +14254,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
# receive different types of post created by htmlNewPost
|
||||
postTypes = ("newpost", "newblog", "newunlisted", "newfollowers",
|
||||
"newdm", "newreport", "newshare", "newquestion",
|
||||
"editblogpost", "newreminder", "newevent")
|
||||
"editblogpost", "newreminder")
|
||||
for currPostType in postTypes:
|
||||
if not authorized:
|
||||
if self.server.debug:
|
||||
|
|
@ -14520,8 +14264,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
postRedirect = self.server.defaultTimeline
|
||||
if currPostType == 'newshare':
|
||||
postRedirect = 'shares'
|
||||
elif currPostType == 'newevent':
|
||||
postRedirect = 'tlevents'
|
||||
|
||||
pageNumber = \
|
||||
self._receiveNewPost(currPostType, self.path,
|
||||
|
|
|
|||
62
epicyon.py
62
epicyon.py
|
|
@ -1602,9 +1602,7 @@ if args.proxyPort:
|
|||
setConfigParam(baseDir, 'proxyPort', proxyPort)
|
||||
if args.gnunet:
|
||||
httpPrefix = 'gnunet'
|
||||
if args.dat:
|
||||
httpPrefix = 'dat'
|
||||
if args.hyper:
|
||||
if args.dat or args.hyper:
|
||||
httpPrefix = 'hyper'
|
||||
if args.i2p:
|
||||
httpPrefix = 'http'
|
||||
|
|
@ -1645,7 +1643,7 @@ if args.followers:
|
|||
if '/@' in args.followers or \
|
||||
'/users/' in args.followers or \
|
||||
args.followers.startswith('http') or \
|
||||
args.followers.startswith('dat'):
|
||||
args.followers.startswith('hyper'):
|
||||
# format: https://domain/@nick
|
||||
prefixes = getProtocolPrefixes()
|
||||
for prefix in prefixes:
|
||||
|
|
@ -2312,6 +2310,14 @@ if args.testdata:
|
|||
testMediaType = None
|
||||
testImageDescription = None
|
||||
testCity = 'London, England'
|
||||
testInReplyTo = None
|
||||
testInReplyToAtomUri = None
|
||||
testSubject = None
|
||||
testSchedulePost = False
|
||||
testEventDate = None
|
||||
testEventTime = None
|
||||
testLocation = None
|
||||
testIsArticle = False
|
||||
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"like this is totally just a #test man",
|
||||
|
|
@ -2320,7 +2326,11 @@ if args.testdata:
|
|||
testC2S,
|
||||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType, testImageDescription, testCity)
|
||||
testMediaType, testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"Zoiks!!!",
|
||||
testFollowersOnly,
|
||||
|
|
@ -2328,7 +2338,11 @@ if args.testdata:
|
|||
testC2S,
|
||||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType, testImageDescription, testCity)
|
||||
testMediaType, testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"Hey scoob we need like a hundred more #milkshakes",
|
||||
testFollowersOnly,
|
||||
|
|
@ -2336,7 +2350,11 @@ if args.testdata:
|
|||
testC2S,
|
||||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType, testImageDescription, testCity)
|
||||
testMediaType, testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"Getting kinda spooky around here",
|
||||
testFollowersOnly,
|
||||
|
|
@ -2345,7 +2363,10 @@ if args.testdata:
|
|||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType, testImageDescription, testCity,
|
||||
'someone')
|
||||
'someone', testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"And they would have gotten away with it too" +
|
||||
"if it wasn't for those pesky hackers",
|
||||
|
|
@ -2354,7 +2375,11 @@ if args.testdata:
|
|||
testC2S,
|
||||
testCommentsEnabled,
|
||||
'img/logo.png', 'image/png',
|
||||
'Description of image', testCity)
|
||||
'Description of image', testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"man these centralized sites are like the worst!",
|
||||
testFollowersOnly,
|
||||
|
|
@ -2362,7 +2387,11 @@ if args.testdata:
|
|||
testC2S,
|
||||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType, testImageDescription, testCity)
|
||||
testMediaType, testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"another mystery solved #test",
|
||||
testFollowersOnly,
|
||||
|
|
@ -2370,7 +2399,11 @@ if args.testdata:
|
|||
testC2S,
|
||||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType, testImageDescription, testCity)
|
||||
testMediaType, testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"let's go bowling",
|
||||
testFollowersOnly,
|
||||
|
|
@ -2378,8 +2411,11 @@ if args.testdata:
|
|||
testC2S,
|
||||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType, testImageDescription, testCity)
|
||||
|
||||
testMediaType, testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
domainFull = domain + ':' + str(port)
|
||||
clearFollows(baseDir, nickname, domain)
|
||||
followPerson(baseDir, nickname, domain, 'maxboardroom', domainFull,
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ def _getNoOfFollows(baseDir: str, nickname: str, domain: str,
|
|||
not line.startswith('http'):
|
||||
ctr += 1
|
||||
elif ((line.startswith('http') or
|
||||
line.startswith('dat')) and
|
||||
line.startswith('hyper')) and
|
||||
hasUsersPath(line)):
|
||||
ctr += 1
|
||||
return ctr
|
||||
|
|
@ -456,7 +456,7 @@ def getFollowingFeed(baseDir: str, domain: str, port: int, path: str,
|
|||
line2.split('@')[0]
|
||||
following['orderedItems'].append(url)
|
||||
elif ((line.startswith('http') or
|
||||
line.startswith('dat')) and
|
||||
line.startswith('hyper')) and
|
||||
hasUsersPath(line)):
|
||||
# https://domain/users/nickname
|
||||
pageCtr += 1
|
||||
|
|
|
|||
5
inbox.py
5
inbox.py
|
|
@ -168,7 +168,7 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
|
|||
"""
|
||||
pageNumber = -999
|
||||
avatarUrl = None
|
||||
if boxname != 'tlevents' and boxname != 'outbox':
|
||||
if boxname != 'outbox':
|
||||
boxname = 'inbox'
|
||||
|
||||
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
|
||||
|
|
@ -2504,9 +2504,6 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
|
|||
if isBlogPost(postJsonObject):
|
||||
# blogs index will be updated
|
||||
updateIndexList.append('tlblogs')
|
||||
elif isEventPost(postJsonObject):
|
||||
# events index will be updated
|
||||
updateIndexList.append('tlevents')
|
||||
|
||||
# get the avatar for a reply/announce
|
||||
_obtainAvatarForReplyPost(session, baseDir,
|
||||
|
|
|
|||
41
media.py
41
media.py
|
|
@ -9,6 +9,7 @@ __module_group__ = "Timeline"
|
|||
|
||||
import os
|
||||
import datetime
|
||||
import subprocess
|
||||
from random import randint
|
||||
from hashlib import sha1
|
||||
from auth import createPassword
|
||||
|
|
@ -245,6 +246,13 @@ def attachMedia(baseDir: str, httpPrefix: str,
|
|||
}
|
||||
if mediaType.startswith('image/'):
|
||||
attachmentJson['focialPoint'] = [0.0, 0.0]
|
||||
# find the dimensions of the image and add them as metadata
|
||||
attachImageWidth, attachImageHeight = \
|
||||
getImageDimensions(imageFilename)
|
||||
if attachImageWidth and attachImageHeight:
|
||||
attachmentJson['width'] = attachImageWidth
|
||||
attachmentJson['height'] = attachImageHeight
|
||||
|
||||
postJson['attachment'] = [attachmentJson]
|
||||
|
||||
if baseDir:
|
||||
|
|
@ -286,17 +294,6 @@ def archiveMedia(baseDir: str, archiveDirectory: str, maxWeeks=4) -> None:
|
|||
break
|
||||
|
||||
|
||||
def pathIsImage(path: str) -> bool:
|
||||
if path.endswith('.png') or \
|
||||
path.endswith('.jpg') or \
|
||||
path.endswith('.gif') or \
|
||||
path.endswith('.svg') or \
|
||||
path.endswith('.avif') or \
|
||||
path.endswith('.webp'):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def pathIsVideo(path: str) -> bool:
|
||||
if path.endswith('.ogv') or \
|
||||
path.endswith('.mp4'):
|
||||
|
|
@ -309,3 +306,25 @@ def pathIsAudio(path: str) -> bool:
|
|||
path.endswith('.mp3'):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def getImageDimensions(imageFilename: str) -> (int, int):
|
||||
"""Returns the dimensions of an image file
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(['identify', '-format', '"%wx%h"',
|
||||
imageFilename], stdout=subprocess.PIPE)
|
||||
except BaseException:
|
||||
return None, None
|
||||
if not result:
|
||||
return None, None
|
||||
dimensionsStr = result.stdout.decode('utf-8').replace('"', '')
|
||||
if 'x' not in dimensionsStr:
|
||||
return None, None
|
||||
widthStr = dimensionsStr.split('x')[0]
|
||||
if not widthStr.isdigit():
|
||||
return None, None
|
||||
heightStr = dimensionsStr.split('x')[1]
|
||||
if not heightStr.isdigit():
|
||||
return None, None
|
||||
return int(widthStr), int(heightStr)
|
||||
|
|
|
|||
|
|
@ -337,8 +337,6 @@ def postMessageToOutbox(session, translate: {},
|
|||
if messageJson['object'].get('type'):
|
||||
if messageJson['object']['type'] == 'Article':
|
||||
outboxName = 'tlblogs'
|
||||
elif messageJson['object']['type'] == 'Event':
|
||||
outboxName = 'tlevents'
|
||||
|
||||
savedFilename = \
|
||||
savePostToBox(baseDir,
|
||||
|
|
|
|||
12
person.py
12
person.py
|
|
@ -28,7 +28,6 @@ from posts import createNewsTimeline
|
|||
from posts import createBlogsTimeline
|
||||
from posts import createFeaturesTimeline
|
||||
from posts import createBookmarksTimeline
|
||||
from posts import createEventsTimeline
|
||||
from posts import createInbox
|
||||
from posts import createOutbox
|
||||
from posts import createModeration
|
||||
|
|
@ -746,8 +745,7 @@ def personBoxJson(recentPostsCache: {},
|
|||
boxname != 'tlblogs' and boxname != 'tlnews' and \
|
||||
boxname != 'tlfeatures' and \
|
||||
boxname != 'outbox' and boxname != 'moderation' and \
|
||||
boxname != 'tlbookmarks' and boxname != 'bookmarks' and \
|
||||
boxname != 'tlevents':
|
||||
boxname != 'tlbookmarks' and boxname != 'bookmarks':
|
||||
return None
|
||||
|
||||
if not '/' + boxname in path:
|
||||
|
|
@ -796,12 +794,6 @@ def personBoxJson(recentPostsCache: {},
|
|||
port, httpPrefix,
|
||||
noOfItems, headerOnly,
|
||||
pageNumber)
|
||||
elif boxname == 'tlevents':
|
||||
return createEventsTimeline(recentPostsCache,
|
||||
session, baseDir, nickname, domain,
|
||||
port, httpPrefix,
|
||||
noOfItems, headerOnly,
|
||||
pageNumber)
|
||||
elif boxname == 'tlreplies':
|
||||
return createRepliesTimeline(recentPostsCache,
|
||||
session, baseDir, nickname, domain,
|
||||
|
|
@ -1208,7 +1200,7 @@ def getActorJson(hostDomain: str, handle: str, http: bool, gnunet: bool,
|
|||
if '/@' in handle or \
|
||||
'/users/' in handle or \
|
||||
handle.startswith('http') or \
|
||||
handle.startswith('dat'):
|
||||
handle.startswith('hyper'):
|
||||
# format: https://domain/@nick
|
||||
originalHandle = handle
|
||||
if not hasUsersPath(originalHandle):
|
||||
|
|
|
|||
148
posts.py
148
posts.py
|
|
@ -14,7 +14,6 @@ import os
|
|||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
import random
|
||||
from socket import error as SocketError
|
||||
from time import gmtime, strftime
|
||||
|
|
@ -657,8 +656,7 @@ def deleteAllPosts(baseDir: str,
|
|||
"""Deletes all posts for a person from inbox or outbox
|
||||
"""
|
||||
if boxname != 'inbox' and boxname != 'outbox' and \
|
||||
boxname != 'tlblogs' and boxname != 'tlnews' and \
|
||||
boxname != 'tlevents':
|
||||
boxname != 'tlblogs' and boxname != 'tlnews':
|
||||
return
|
||||
boxDir = createPersonDir(nickname, domain, baseDir, boxname)
|
||||
for deleteFilename in os.scandir(boxDir):
|
||||
|
|
@ -681,7 +679,6 @@ def savePostToBox(baseDir: str, httpPrefix: str, postId: str,
|
|||
"""
|
||||
if boxname != 'inbox' and boxname != 'outbox' and \
|
||||
boxname != 'tlblogs' and boxname != 'tlnews' and \
|
||||
boxname != 'tlevents' and \
|
||||
boxname != 'scheduled':
|
||||
return None
|
||||
originalDomain = domain
|
||||
|
|
@ -1066,18 +1063,18 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
|
|||
mediaType: str, imageDescription: str, city: str,
|
||||
isModerationReport: bool,
|
||||
isArticle: bool,
|
||||
inReplyTo: str = None,
|
||||
inReplyToAtomUri: str = None,
|
||||
subject: str = None, schedulePost: bool = False,
|
||||
eventDate: str = None, eventTime: str = None,
|
||||
location: str = None,
|
||||
eventUUID: str = None, category: str = None,
|
||||
joinMode: str = None,
|
||||
endDate: str = None, endTime: str = None,
|
||||
maximumAttendeeCapacity: int = None,
|
||||
repliesModerationOption: str = None,
|
||||
anonymousParticipationEnabled: bool = None,
|
||||
eventStatus: str = None, ticketUrl: str = None) -> {}:
|
||||
inReplyTo: str,
|
||||
inReplyToAtomUri: str,
|
||||
subject: str, schedulePost: bool,
|
||||
eventDate: str, eventTime: str,
|
||||
location: str,
|
||||
eventUUID: str, category: str,
|
||||
joinMode: str,
|
||||
endDate: str, endTime: str,
|
||||
maximumAttendeeCapacity: int,
|
||||
repliesModerationOption: str,
|
||||
anonymousParticipationEnabled: bool,
|
||||
eventStatus: str, ticketUrl: str) -> {}:
|
||||
"""Creates a message
|
||||
"""
|
||||
content = removeInvalidChars(content)
|
||||
|
|
@ -1244,9 +1241,6 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
|
|||
if isArticle:
|
||||
savePostToBox(baseDir, httpPrefix, newPostId,
|
||||
nickname, domain, newPost, 'tlblogs')
|
||||
elif eventUUID:
|
||||
savePostToBox(baseDir, httpPrefix, newPostId,
|
||||
nickname, domain, newPost, 'tlevents')
|
||||
else:
|
||||
savePostToBox(baseDir, httpPrefix, newPostId,
|
||||
nickname, domain, newPost, 'outbox')
|
||||
|
|
@ -1426,12 +1420,12 @@ def createPublicPost(baseDir: str,
|
|||
clientToServer: bool, commentsEnabled: bool,
|
||||
attachImageFilename: str, mediaType: str,
|
||||
imageDescription: str, city: str,
|
||||
inReplyTo: str = None,
|
||||
inReplyToAtomUri: str = None, subject: str = None,
|
||||
schedulePost: bool = False,
|
||||
eventDate: str = None, eventTime: str = None,
|
||||
location: str = None,
|
||||
isArticle: bool = False) -> {}:
|
||||
inReplyTo: str,
|
||||
inReplyToAtomUri: str, subject: str,
|
||||
schedulePost: bool,
|
||||
eventDate: str, eventTime: str,
|
||||
location: str,
|
||||
isArticle: bool) -> {}:
|
||||
"""Public post
|
||||
"""
|
||||
domainFull = getFullDomain(domain, port)
|
||||
|
|
@ -1501,10 +1495,10 @@ def createBlogPost(baseDir: str,
|
|||
clientToServer: bool, commentsEnabled: bool,
|
||||
attachImageFilename: str, mediaType: str,
|
||||
imageDescription: str, city: str,
|
||||
inReplyTo: str = None, inReplyToAtomUri: str = None,
|
||||
subject: str = None, schedulePost: bool = False,
|
||||
eventDate: str = None, eventTime: str = None,
|
||||
location: str = None) -> {}:
|
||||
inReplyTo: str, inReplyToAtomUri: str,
|
||||
subject: str, schedulePost: bool,
|
||||
eventDate: str, eventTime: str,
|
||||
location: str) -> {}:
|
||||
blogJson = \
|
||||
createPublicPost(baseDir,
|
||||
nickname, domain, port, httpPrefix,
|
||||
|
|
@ -1600,10 +1594,10 @@ def createUnlistedPost(baseDir: str,
|
|||
clientToServer: bool, commentsEnabled: bool,
|
||||
attachImageFilename: str, mediaType: str,
|
||||
imageDescription: str, city: str,
|
||||
inReplyTo: str = None, inReplyToAtomUri: str = None,
|
||||
subject: str = None, schedulePost: bool = False,
|
||||
eventDate: str = None, eventTime: str = None,
|
||||
location: str = None) -> {}:
|
||||
inReplyTo: str, inReplyToAtomUri: str,
|
||||
subject: str, schedulePost: bool,
|
||||
eventDate: str, eventTime: str,
|
||||
location: str) -> {}:
|
||||
"""Unlisted post. This has the #Public and followers links inverted.
|
||||
"""
|
||||
domainFull = getFullDomain(domain, port)
|
||||
|
|
@ -1630,11 +1624,11 @@ def createFollowersOnlyPost(baseDir: str,
|
|||
clientToServer: bool, commentsEnabled: bool,
|
||||
attachImageFilename: str, mediaType: str,
|
||||
imageDescription: str, city: str,
|
||||
inReplyTo: str = None,
|
||||
inReplyToAtomUri: str = None,
|
||||
subject: str = None, schedulePost: bool = False,
|
||||
eventDate: str = None, eventTime: str = None,
|
||||
location: str = None) -> {}:
|
||||
inReplyTo: str,
|
||||
inReplyToAtomUri: str,
|
||||
subject: str, schedulePost: bool,
|
||||
eventDate: str, eventTime: str,
|
||||
location: str) -> {}:
|
||||
"""Followers only post
|
||||
"""
|
||||
domainFull = getFullDomain(domain, port)
|
||||
|
|
@ -1653,57 +1647,6 @@ def createFollowersOnlyPost(baseDir: str,
|
|||
None, None, None, None, None)
|
||||
|
||||
|
||||
def createEventPost(baseDir: str,
|
||||
nickname: str, domain: str, port: int,
|
||||
httpPrefix: str,
|
||||
content: str, followersOnly: bool,
|
||||
saveToFile: bool,
|
||||
clientToServer: bool, commentsEnabled: bool,
|
||||
attachImageFilename: str, mediaType: str,
|
||||
imageDescription: str, city: str,
|
||||
subject: str = None, schedulePost: str = False,
|
||||
eventDate: str = None, eventTime: str = None,
|
||||
location: str = None, category: str = None,
|
||||
joinMode: str = None,
|
||||
endDate: str = None, endTime: str = None,
|
||||
maximumAttendeeCapacity: int = None,
|
||||
repliesModerationOption: str = None,
|
||||
anonymousParticipationEnabled: bool = None,
|
||||
eventStatus: str = None, ticketUrl: str = None) -> {}:
|
||||
"""Mobilizon-type Event post
|
||||
"""
|
||||
if not attachImageFilename:
|
||||
print('Event has no attached image')
|
||||
return None
|
||||
if not category:
|
||||
print('Event has no category')
|
||||
return None
|
||||
domainFull = getFullDomain(domain, port)
|
||||
|
||||
# create event uuid
|
||||
eventUUID = str(uuid.uuid1())
|
||||
|
||||
toStr1 = 'https://www.w3.org/ns/activitystreams#Public'
|
||||
toStr2 = httpPrefix + '://' + domainFull + '/users/' + \
|
||||
nickname + '/followers',
|
||||
if followersOnly:
|
||||
toStr1 = toStr2
|
||||
toStr2 = None
|
||||
return _createPostBase(baseDir, nickname, domain, port,
|
||||
toStr1, toStr2,
|
||||
httpPrefix, content, followersOnly, saveToFile,
|
||||
clientToServer, commentsEnabled,
|
||||
attachImageFilename, mediaType,
|
||||
imageDescription, city,
|
||||
False, False, None, None, subject,
|
||||
schedulePost, eventDate, eventTime, location,
|
||||
eventUUID, category, joinMode,
|
||||
endDate, endTime, maximumAttendeeCapacity,
|
||||
repliesModerationOption,
|
||||
anonymousParticipationEnabled,
|
||||
eventStatus, ticketUrl)
|
||||
|
||||
|
||||
def getMentionedPeople(baseDir: str, httpPrefix: str,
|
||||
content: str, domain: str, debug: bool) -> []:
|
||||
"""Extracts a list of mentioned actors from the given message content
|
||||
|
|
@ -1747,12 +1690,12 @@ def createDirectMessagePost(baseDir: str,
|
|||
commentsEnabled: bool,
|
||||
attachImageFilename: str, mediaType: str,
|
||||
imageDescription: str, city: str,
|
||||
inReplyTo: str = None,
|
||||
inReplyToAtomUri: str = None,
|
||||
subject: str = None, debug: bool = False,
|
||||
schedulePost: bool = False,
|
||||
eventDate: str = None, eventTime: str = None,
|
||||
location: str = None) -> {}:
|
||||
inReplyTo: str,
|
||||
inReplyToAtomUri: str,
|
||||
subject: str, debug: bool,
|
||||
schedulePost: bool,
|
||||
eventDate: str, eventTime: str,
|
||||
location: str) -> {}:
|
||||
"""Direct Message post
|
||||
"""
|
||||
content = resolvePetnames(baseDir, nickname, domain, content)
|
||||
|
|
@ -1825,7 +1768,7 @@ def createReportPost(baseDir: str,
|
|||
if moderatorActor not in moderatorsList:
|
||||
moderatorsList.append(moderatorActor)
|
||||
continue
|
||||
if line.startswith('http') or line.startswith('dat'):
|
||||
if line.startswith('http') or line.startswith('hyper'):
|
||||
# must be a local address - no remote moderators
|
||||
if '://' + domainFull + '/' in line:
|
||||
if line not in moderatorsList:
|
||||
|
|
@ -2835,16 +2778,6 @@ def createBookmarksTimeline(session, baseDir: str, nickname: str, domain: str,
|
|||
True, 0, False, 0, pageNumber)
|
||||
|
||||
|
||||
def createEventsTimeline(recentPostsCache: {},
|
||||
session, baseDir: str, nickname: str, domain: str,
|
||||
port: int, httpPrefix: str, itemsPerPage: int,
|
||||
headerOnly: bool, pageNumber: int = None) -> {}:
|
||||
return _createBoxIndexed(recentPostsCache, session, baseDir, 'tlevents',
|
||||
nickname, domain,
|
||||
port, httpPrefix, itemsPerPage, headerOnly,
|
||||
True, 0, False, 0, pageNumber)
|
||||
|
||||
|
||||
def createDMTimeline(recentPostsCache: {},
|
||||
session, baseDir: str, nickname: str, domain: str,
|
||||
port: int, httpPrefix: str, itemsPerPage: int,
|
||||
|
|
@ -3179,8 +3112,7 @@ def _createBoxIndexed(recentPostsCache: {},
|
|||
boxname != 'tlblogs' and boxname != 'tlnews' and \
|
||||
boxname != 'tlfeatures' and \
|
||||
boxname != 'outbox' and boxname != 'tlbookmarks' and \
|
||||
boxname != 'bookmarks' and \
|
||||
boxname != 'tlevents':
|
||||
boxname != 'bookmarks':
|
||||
return None
|
||||
|
||||
# bookmarks and events timelines are like the inbox
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ def load_document(url):
|
|||
# validate URL
|
||||
pieces = urllib_parse.urlparse(url)
|
||||
if (not all([pieces.scheme, pieces.netloc]) or
|
||||
pieces.scheme not in ['http', 'https', 'dat'] or
|
||||
pieces.scheme not in ['http', 'https', 'hyper'] or
|
||||
set(pieces.netloc) > set(
|
||||
string.ascii_letters + string.digits + '-.:')):
|
||||
raise JsonLdError(
|
||||
|
|
|
|||
136
tests.py
136
tests.py
|
|
@ -86,6 +86,7 @@ from announce import sendAnnounceViaServer
|
|||
from city import parseNogoString
|
||||
from city import spoofGeolocation
|
||||
from city import pointInNogo
|
||||
from media import getImageDimensions
|
||||
from media import getMediaPath
|
||||
from media import getAttachmentMediaType
|
||||
from delete import sendDeleteViaServer
|
||||
|
|
@ -476,6 +477,14 @@ def createServerAlice(path: str, domain: str, port: int,
|
|||
testMediaType = None
|
||||
testImageDescription = None
|
||||
testCity = 'London, England'
|
||||
testInReplyTo = None
|
||||
testInReplyToAtomUri = None
|
||||
testSubject = None
|
||||
testSchedulePost = False
|
||||
testEventDate = None
|
||||
testEventTime = None
|
||||
testLocation = None
|
||||
testIsArticle = False
|
||||
createPublicPost(path, nickname, domain, port, httpPrefix,
|
||||
"No wise fish would go anywhere without a porpoise",
|
||||
testFollowersOnly,
|
||||
|
|
@ -484,7 +493,11 @@ def createServerAlice(path: str, domain: str, port: int,
|
|||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType,
|
||||
testImageDescription, testCity)
|
||||
testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(path, nickname, domain, port, httpPrefix,
|
||||
"Curiouser and curiouser!",
|
||||
testFollowersOnly,
|
||||
|
|
@ -493,7 +506,11 @@ def createServerAlice(path: str, domain: str, port: int,
|
|||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType,
|
||||
testImageDescription, testCity)
|
||||
testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(path, nickname, domain, port, httpPrefix,
|
||||
"In the gardens of memory, in the palace " +
|
||||
"of dreams, that is where you and I shall meet",
|
||||
|
|
@ -503,7 +520,11 @@ def createServerAlice(path: str, domain: str, port: int,
|
|||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType,
|
||||
testImageDescription, testCity)
|
||||
testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
global testServerAliceRunning
|
||||
testServerAliceRunning = True
|
||||
maxMentions = 10
|
||||
|
|
@ -581,6 +602,14 @@ def createServerBob(path: str, domain: str, port: int,
|
|||
testImageDescription = None
|
||||
testMediaType = None
|
||||
testCity = 'London, England'
|
||||
testInReplyTo = None
|
||||
testInReplyToAtomUri = None
|
||||
testSubject = None
|
||||
testSchedulePost = False
|
||||
testEventDate = None
|
||||
testEventTime = None
|
||||
testLocation = None
|
||||
testIsArticle = False
|
||||
createPublicPost(path, nickname, domain, port, httpPrefix,
|
||||
"It's your life, live it your way.",
|
||||
testFollowersOnly,
|
||||
|
|
@ -589,7 +618,11 @@ def createServerBob(path: str, domain: str, port: int,
|
|||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType,
|
||||
testImageDescription, testCity)
|
||||
testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(path, nickname, domain, port, httpPrefix,
|
||||
"One of the things I've realised is that " +
|
||||
"I am very simple",
|
||||
|
|
@ -599,7 +632,11 @@ def createServerBob(path: str, domain: str, port: int,
|
|||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType,
|
||||
testImageDescription, testCity)
|
||||
testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
createPublicPost(path, nickname, domain, port, httpPrefix,
|
||||
"Quantum physics is a bit of a passion of mine",
|
||||
testFollowersOnly,
|
||||
|
|
@ -608,7 +645,11 @@ def createServerBob(path: str, domain: str, port: int,
|
|||
testCommentsEnabled,
|
||||
testAttachImageFilename,
|
||||
testMediaType,
|
||||
testImageDescription, testCity)
|
||||
testImageDescription, testCity,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
global testServerBobRunning
|
||||
testServerBobRunning = True
|
||||
maxMentions = 10
|
||||
|
|
@ -792,6 +833,10 @@ def testPostMessageBetweenServers():
|
|||
alicePersonCache = {}
|
||||
aliceCachedWebfingers = {}
|
||||
attachedImageFilename = baseDir + '/img/logo.png'
|
||||
testImageWidth, testImageHeight = \
|
||||
getImageDimensions(attachedImageFilename)
|
||||
assert testImageWidth
|
||||
assert testImageHeight
|
||||
mediaType = getAttachmentMediaType(attachedImageFilename)
|
||||
attachedImageDescription = 'Logo'
|
||||
isArticle = False
|
||||
|
|
@ -875,6 +920,20 @@ def testPostMessageBetweenServers():
|
|||
assert 'Why is a mouse when it spins?' in \
|
||||
receivedJson['object']['content']
|
||||
assert 'यह एक परीक्षण है' in receivedJson['object']['content']
|
||||
print('Check that message received from Alice contains an attachment')
|
||||
assert receivedJson['object']['attachment']
|
||||
assert len(receivedJson['object']['attachment']) == 1
|
||||
attached = receivedJson['object']['attachment'][0]
|
||||
pprint(attached)
|
||||
assert attached.get('type')
|
||||
assert attached.get('url')
|
||||
assert attached['mediaType'] == 'image/png'
|
||||
assert '/media/' in attached['url']
|
||||
assert attached['url'].endswith('.png')
|
||||
assert attached.get('width')
|
||||
assert attached.get('height')
|
||||
assert attached['width'] > 0
|
||||
assert attached['height'] > 0
|
||||
|
||||
print('\n\n*******************************************************')
|
||||
print("Bob likes Alice's post")
|
||||
|
|
@ -1416,10 +1475,28 @@ def _testCreatePerson():
|
|||
setBio(baseDir, nickname, domain, 'Randomly roaming in your backyard')
|
||||
archivePostsForPerson(nickname, domain, baseDir, 'inbox', None, {}, 4)
|
||||
archivePostsForPerson(nickname, domain, baseDir, 'outbox', None, {}, 4)
|
||||
testInReplyTo = None
|
||||
testInReplyToAtomUri = None
|
||||
testSubject = None
|
||||
testSchedulePost = False
|
||||
testEventDate = None
|
||||
testEventTime = None
|
||||
testLocation = None
|
||||
testIsArticle = False
|
||||
content = "G'day world!"
|
||||
followersOnly = False
|
||||
saveToFile = True
|
||||
commentsEnabled = True
|
||||
attachImageFilename = None
|
||||
mediaType = None
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
"G'day world!", False, True, clientToServer,
|
||||
True, None, None, None, None,
|
||||
'Not suitable for Vogons', 'London, England')
|
||||
content, followersOnly, saveToFile, clientToServer,
|
||||
commentsEnabled, attachImageFilename, mediaType,
|
||||
'Not suitable for Vogons', 'London, England',
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
|
||||
os.chdir(currDir)
|
||||
shutil.rmtree(baseDir)
|
||||
|
|
@ -2802,12 +2879,23 @@ def _testReplyToPublicPost() -> None:
|
|||
mediaType = None
|
||||
imageDescription = 'Some description'
|
||||
city = 'London, England'
|
||||
testInReplyToAtomUri = None
|
||||
testSubject = None
|
||||
testSchedulePost = False
|
||||
testEventDate = None
|
||||
testEventTime = None
|
||||
testLocation = None
|
||||
testIsArticle = False
|
||||
reply = \
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
content, followersOnly, saveToFile,
|
||||
clientToServer, commentsEnabled,
|
||||
attachImageFilename, mediaType,
|
||||
imageDescription, city, postId)
|
||||
imageDescription, city, postId,
|
||||
testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
# print(str(reply))
|
||||
assert reply['object']['content'] == \
|
||||
'<p><span class=\"h-card\">' + \
|
||||
|
|
@ -3365,16 +3453,30 @@ def _testLinksWithinPost() -> None:
|
|||
saveToFile = False
|
||||
clientToServer = False
|
||||
commentsEnabled = True
|
||||
attachImageFilename = None
|
||||
mediaType = None
|
||||
imageDescription = None
|
||||
city = 'London, England'
|
||||
testInReplyTo = None
|
||||
testInReplyToAtomUri = None
|
||||
testSubject = None
|
||||
testSchedulePost = False
|
||||
testEventDate = None
|
||||
testEventTime = None
|
||||
testLocation = None
|
||||
testIsArticle = False
|
||||
|
||||
postJsonObject = \
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
content, followersOnly, saveToFile,
|
||||
clientToServer, commentsEnabled,
|
||||
mediaType, imageDescription, city,
|
||||
False, None)
|
||||
attachImageFilename, mediaType,
|
||||
imageDescription, city,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
|
||||
assert postJsonObject['object']['content'] == \
|
||||
'<p>This is a test post with links.<br><br>' + \
|
||||
'<a href="ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/" ' + \
|
||||
|
|
@ -3400,8 +3502,14 @@ def _testLinksWithinPost() -> None:
|
|||
postJsonObject = \
|
||||
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
|
||||
content,
|
||||
False, False, False, True,
|
||||
None, None, False, None)
|
||||
False, False,
|
||||
False, True,
|
||||
None, None,
|
||||
False, None,
|
||||
testInReplyTo, testInReplyToAtomUri,
|
||||
testSubject, testSchedulePost,
|
||||
testEventDate, testEventTime, testLocation,
|
||||
testIsArticle)
|
||||
assert postJsonObject['object']['content'] == content
|
||||
|
||||
|
||||
|
|
|
|||
13
utils.py
13
utils.py
|
|
@ -270,6 +270,15 @@ def getImageFormats() -> str:
|
|||
return imageFormats
|
||||
|
||||
|
||||
def isImageFile(filename: str) -> bool:
|
||||
"""Is the given filename an image?
|
||||
"""
|
||||
for ext in getImageExtensions():
|
||||
if filename.endswith('.' + ext):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def getMediaFormats() -> str:
|
||||
"""Returns a string of permissable media formats
|
||||
used when selecting an attachment for a new post
|
||||
|
|
@ -1130,7 +1139,7 @@ def locatePost(baseDir: str, nickname: str, domain: str,
|
|||
postUrl = postUrl + '.' + extension
|
||||
|
||||
# search boxes
|
||||
boxes = ('inbox', 'outbox', 'tlblogs', 'tlevents')
|
||||
boxes = ('inbox', 'outbox', 'tlblogs')
|
||||
accountDir = baseDir + '/accounts/' + nickname + '@' + domain + '/'
|
||||
for boxName in boxes:
|
||||
postFilename = accountDir + boxName + '/' + postUrl
|
||||
|
|
@ -1392,7 +1401,7 @@ def _isReservedName(nickname: str) -> bool:
|
|||
'public', 'followers', 'category',
|
||||
'channel', 'calendar',
|
||||
'tlreplies', 'tlmedia', 'tlblogs',
|
||||
'tlevents', 'tlblogs', 'tlfeatures',
|
||||
'tlblogs', 'tlfeatures',
|
||||
'moderation', 'moderationaction',
|
||||
'activity', 'undo', 'pinned',
|
||||
'reply', 'replies', 'question', 'like',
|
||||
|
|
|
|||
|
|
@ -129,20 +129,6 @@ def _htmlTimelineNewPost(manuallyApproveFollowers: bool,
|
|||
'<a href="' + usersPath + '/newblog">' + \
|
||||
'<button class="button"><span>' + \
|
||||
translate['Post'] + '</span></button></a>'
|
||||
elif boxName == 'tlevents':
|
||||
if not iconsAsButtons:
|
||||
newPostButtonStr += \
|
||||
'<a class="imageAnchor" href="' + usersPath + \
|
||||
'/newevent?nodropdown"><img loading="lazy" src="/' + \
|
||||
'icons/newpost.png" title="' + \
|
||||
translate['Create a new event'] + '" alt="| ' + \
|
||||
translate['Create a new event'] + \
|
||||
'" class="timelineicon"/></a>\n'
|
||||
else:
|
||||
newPostButtonStr += \
|
||||
'<a href="' + usersPath + '/newevent?nodropdown">' + \
|
||||
'<button class="button"><span>' + \
|
||||
translate['Post'] + '</span></button></a>'
|
||||
elif boxName == 'tlshares':
|
||||
if not iconsAsButtons:
|
||||
newPostButtonStr += \
|
||||
|
|
@ -500,8 +486,6 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
sharesButton = 'buttonselectedhighlighted'
|
||||
elif boxName == 'tlbookmarks' or boxName == 'bookmarks':
|
||||
bookmarksButton = 'buttonselected'
|
||||
# elif boxName == 'tlevents':
|
||||
# eventsButton = 'buttonselected'
|
||||
|
||||
# get the full domain, including any port number
|
||||
fullDomain = getFullDomain(domain, port)
|
||||
|
|
@ -559,11 +543,6 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
|||
'<a href="' + usersPath + '/tlbookmarks"><button class="' + \
|
||||
bookmarksButton + '"><span>' + translate['Bookmarks'] + \
|
||||
'</span></button></a>'
|
||||
#
|
||||
# eventsButtonStr = \
|
||||
# '<a href="' + usersPath + '/tlevents"><button class="' + \
|
||||
# eventsButton + '"><span>' + translate['Events'] + \
|
||||
# '</span></button></a>'
|
||||
|
||||
instanceTitle = \
|
||||
getConfigParam(baseDir, 'instanceTitle')
|
||||
|
|
@ -1054,51 +1033,6 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str,
|
|||
accessKeys)
|
||||
|
||||
|
||||
def htmlEvents(cssCache: {}, defaultTimeline: str,
|
||||
recentPostsCache: {}, maxRecentPosts: int,
|
||||
translate: {}, pageNumber: int, itemsPerPage: int,
|
||||
session, baseDir: str,
|
||||
cachedWebfingers: {}, personCache: {},
|
||||
nickname: str, domain: str, port: int, bookmarksJson: {},
|
||||
allowDeletion: bool,
|
||||
httpPrefix: str, projectVersion: str,
|
||||
minimal: bool, YTReplacementDomain: str,
|
||||
showPublishedDateOnly: bool,
|
||||
newswire: {}, positiveVoting: bool,
|
||||
showPublishAsIcon: bool,
|
||||
fullWidthTimelineButtonHeader: bool,
|
||||
iconsAsButtons: bool,
|
||||
rssIconAtTop: bool,
|
||||
publishButtonAtTop: bool,
|
||||
authorized: bool, theme: str,
|
||||
peertubeInstances: [],
|
||||
allowLocalNetworkAccess: bool,
|
||||
textModeBanner: str,
|
||||
accessKeys: {}) -> str:
|
||||
"""Show the events as html
|
||||
"""
|
||||
manuallyApproveFollowers = \
|
||||
followerApprovalActive(baseDir, nickname, domain)
|
||||
|
||||
return htmlTimeline(cssCache, defaultTimeline,
|
||||
recentPostsCache, maxRecentPosts,
|
||||
translate, pageNumber,
|
||||
itemsPerPage, session, baseDir,
|
||||
cachedWebfingers, personCache,
|
||||
nickname, domain, port, bookmarksJson,
|
||||
'tlevents', allowDeletion,
|
||||
httpPrefix, projectVersion, manuallyApproveFollowers,
|
||||
minimal, YTReplacementDomain,
|
||||
showPublishedDateOnly,
|
||||
newswire, False, False,
|
||||
positiveVoting, showPublishAsIcon,
|
||||
fullWidthTimelineButtonHeader,
|
||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||
authorized, None, theme, peertubeInstances,
|
||||
allowLocalNetworkAccess, textModeBanner,
|
||||
accessKeys)
|
||||
|
||||
|
||||
def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
|
||||
recentPostsCache: {}, maxRecentPosts: int,
|
||||
translate: {}, pageNumber: int, itemsPerPage: int,
|
||||
|
|
|
|||
Loading…
Reference in New Issue