mirror of https://gitlab.com/bashrc2/epicyon
				
				
				
			Remove id endings in a better way
							parent
							
								
									8151f32196
								
							
						
					
					
						commit
						86f2e9d8ab
					
				| 
						 | 
				
			
			@ -129,7 +129,7 @@ def createAnnounce(session, baseDir: str, federationList: [],
 | 
			
		|||
        'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname,
 | 
			
		||||
        'atomUri': atomUriStr,
 | 
			
		||||
        'cc': [],
 | 
			
		||||
        'id': newAnnounceId+'/activity',
 | 
			
		||||
        'id': newAnnounceId + '/activity',
 | 
			
		||||
        'object': objectUrl,
 | 
			
		||||
        'published': published,
 | 
			
		||||
        'to': [toUrl],
 | 
			
		||||
| 
						 | 
				
			
			@ -365,7 +365,7 @@ def sendAnnounceViaServer(baseDir: str, session,
 | 
			
		|||
        'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname,
 | 
			
		||||
        'atomUri': newAnnounceId,
 | 
			
		||||
        'cc': [ccUrl],
 | 
			
		||||
        'id': newAnnounceId+'/activity',
 | 
			
		||||
        'id': newAnnounceId + '/activity',
 | 
			
		||||
        'object': repeatObjectUrl,
 | 
			
		||||
        'published': published,
 | 
			
		||||
        'to': [toUrl],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
 | 
			
		|||
__status__ = "Production"
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import isEvil
 | 
			
		||||
from utils import locatePost
 | 
			
		||||
from utils import evilIncarnate
 | 
			
		||||
| 
						 | 
				
			
			@ -214,7 +215,7 @@ def outboxBlock(baseDir: str, httpPrefix: str,
 | 
			
		|||
    if debug:
 | 
			
		||||
        print('DEBUG: c2s block request arrived in outbox')
 | 
			
		||||
 | 
			
		||||
    messageId = messageJson['object'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['object'])
 | 
			
		||||
    if '/statuses/' not in messageId:
 | 
			
		||||
        if debug:
 | 
			
		||||
            print('DEBUG: c2s block object is not a status')
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +294,7 @@ def outboxUndoBlock(baseDir: str, httpPrefix: str,
 | 
			
		|||
    if debug:
 | 
			
		||||
        print('DEBUG: c2s undo block request arrived in outbox')
 | 
			
		||||
 | 
			
		||||
    messageId = messageJson['object']['object'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['object']['object'])
 | 
			
		||||
    if '/statuses/' not in messageId:
 | 
			
		||||
        if debug:
 | 
			
		||||
            print('DEBUG: c2s undo block object is not a status')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ __status__ = "Production"
 | 
			
		|||
 | 
			
		||||
import os
 | 
			
		||||
from pprint import pprint
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import removePostFromCache
 | 
			
		||||
from utils import urlPermitted
 | 
			
		||||
from utils import getNicknameFromActor
 | 
			
		||||
| 
						 | 
				
			
			@ -607,7 +608,7 @@ def outboxBookmark(recentPostsCache: {},
 | 
			
		|||
    if debug:
 | 
			
		||||
        print('DEBUG: c2s bookmark request arrived in outbox')
 | 
			
		||||
 | 
			
		||||
    messageId = messageJson['object'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['object'])
 | 
			
		||||
    if ':' in domain:
 | 
			
		||||
        domain = domain.split(':')[0]
 | 
			
		||||
    postFilename = locatePost(baseDir, nickname, domain, messageId)
 | 
			
		||||
| 
						 | 
				
			
			@ -667,7 +668,7 @@ def outboxUndoBookmark(recentPostsCache: {},
 | 
			
		|||
    if debug:
 | 
			
		||||
        print('DEBUG: c2s undo bookmark request arrived in outbox')
 | 
			
		||||
 | 
			
		||||
    messageId = messageJson['object']['object'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['object']['object'])
 | 
			
		||||
    if ':' in domain:
 | 
			
		||||
        domain = domain.split(':')[0]
 | 
			
		||||
    postFilename = locatePost(baseDir, nickname, domain, messageId)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										104
									
								
								daemon.py
								
								
								
								
							
							
						
						
									
										104
									
								
								daemon.py
								
								
								
								
							| 
						 | 
				
			
			@ -127,6 +127,7 @@ from webinterface import htmlIndividualPost
 | 
			
		|||
from webinterface import htmlProfile
 | 
			
		||||
from webinterface import htmlInbox
 | 
			
		||||
from webinterface import htmlBookmarks
 | 
			
		||||
from webinterface import htmlEvents
 | 
			
		||||
from webinterface import htmlShares
 | 
			
		||||
from webinterface import htmlOutbox
 | 
			
		||||
from webinterface import htmlModeration
 | 
			
		||||
| 
						 | 
				
			
			@ -154,6 +155,7 @@ from shares import getSharesFeedForPerson
 | 
			
		|||
from shares import addShare
 | 
			
		||||
from shares import removeShare
 | 
			
		||||
from shares import expireShares
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import updateLikesCollection
 | 
			
		||||
from utils import undoLikesCollectionEntry
 | 
			
		||||
from utils import deletePost
 | 
			
		||||
| 
						 | 
				
			
			@ -2734,10 +2736,9 @@ class PubServer(BaseHTTPRequestHandler):
 | 
			
		|||
 | 
			
		||||
        self._benchmarkGETtimings(GETstartTime, GETtimings, 32)
 | 
			
		||||
 | 
			
		||||
#        unrepeatPrivate = False
 | 
			
		||||
        if htmlGET and '?unrepeatprivate=' in self.path:
 | 
			
		||||
            self.path = self.path.replace('?unrepeatprivate=', '?unrepeat=')
 | 
			
		||||
#            unrepeatPrivate = True
 | 
			
		||||
 | 
			
		||||
        # undo an announce/repeat from the web interface
 | 
			
		||||
        if htmlGET and '?unrepeat=' in self.path:
 | 
			
		||||
            pageNumber = 1
 | 
			
		||||
| 
						 | 
				
			
			@ -4823,6 +4824,100 @@ class PubServer(BaseHTTPRequestHandler):
 | 
			
		|||
            self.server.GETbusy = False
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        # 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 '/users/' in self.path:
 | 
			
		||||
                if authorized:
 | 
			
		||||
                    eventsFeed = \
 | 
			
		||||
                        personBoxJson(self.server.recentPostsCache,
 | 
			
		||||
                                      self.server.session,
 | 
			
		||||
                                      self.server.baseDir,
 | 
			
		||||
                                      self.server.domain,
 | 
			
		||||
                                      self.server.port,
 | 
			
		||||
                                      self.path,
 | 
			
		||||
                                      self.server.httpPrefix,
 | 
			
		||||
                                      maxPostsInFeed, 'tlevents',
 | 
			
		||||
                                      authorized, self.server.ocapAlways)
 | 
			
		||||
                    if eventsFeed:
 | 
			
		||||
                        if self._requestHTTP():
 | 
			
		||||
                            nickname = self.path.replace('/users/', '')
 | 
			
		||||
                            nickname = nickname.replace('/tlevents', '')
 | 
			
		||||
                            nickname = nickname.replace('/events', '')
 | 
			
		||||
                            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 self.path:
 | 
			
		||||
                                # if no page was specified then show the first
 | 
			
		||||
                                eventsFeed = \
 | 
			
		||||
                                    personBoxJson(self.server.recentPostsCache,
 | 
			
		||||
                                                  self.server.session,
 | 
			
		||||
                                                  self.server.baseDir,
 | 
			
		||||
                                                  self.server.domain,
 | 
			
		||||
                                                  self.server.port,
 | 
			
		||||
                                                  self.path + '?page=1',
 | 
			
		||||
                                                  self.server.httpPrefix,
 | 
			
		||||
                                                  maxPostsInFeed,
 | 
			
		||||
                                                  'tlevents',
 | 
			
		||||
                                                  authorized,
 | 
			
		||||
                                                  self.server.ocapAlways)
 | 
			
		||||
                            msg = \
 | 
			
		||||
                                htmlEvents(self.server.defaultTimeline,
 | 
			
		||||
                                           self.server.recentPostsCache,
 | 
			
		||||
                                           self.server.maxRecentPosts,
 | 
			
		||||
                                           self.server.translate,
 | 
			
		||||
                                           pageNumber, maxPostsInFeed,
 | 
			
		||||
                                           self.server.session,
 | 
			
		||||
                                           self.server.baseDir,
 | 
			
		||||
                                           self.server.cachedWebfingers,
 | 
			
		||||
                                           self.server.personCache,
 | 
			
		||||
                                           nickname,
 | 
			
		||||
                                           self.server.domain,
 | 
			
		||||
                                           self.server.port,
 | 
			
		||||
                                           eventsFeed,
 | 
			
		||||
                                           self.server.allowDeletion,
 | 
			
		||||
                                           self.server.httpPrefix,
 | 
			
		||||
                                           self.server.projectVersion,
 | 
			
		||||
                                           self._isMinimal(nickname),
 | 
			
		||||
                                           self.server.YTReplacementDomain)
 | 
			
		||||
                            msg = msg.encode('utf-8')
 | 
			
		||||
                            self._set_headers('text/html',
 | 
			
		||||
                                              len(msg),
 | 
			
		||||
                                              cookie, callingDomain)
 | 
			
		||||
                            self._write(msg)
 | 
			
		||||
                        else:
 | 
			
		||||
                            # don't need authenticated fetch here because
 | 
			
		||||
                            # there is already the authorization check
 | 
			
		||||
                            msg = json.dumps(inboxFeed,
 | 
			
		||||
                                             ensure_ascii=False)
 | 
			
		||||
                            msg = msg.encode('utf-8')
 | 
			
		||||
                            self._set_headers('application/json',
 | 
			
		||||
                                              len(msg),
 | 
			
		||||
                                              None, callingDomain)
 | 
			
		||||
                            self._write(msg)
 | 
			
		||||
                        self.server.GETbusy = False
 | 
			
		||||
                        return
 | 
			
		||||
                else:
 | 
			
		||||
                    if self.server.debug:
 | 
			
		||||
                        nickname = self.path.replace('/users/', '')
 | 
			
		||||
                        nickname = nickname.replace('/tlevents', '')
 | 
			
		||||
                        nickname = nickname.replace('/events', '')
 | 
			
		||||
                        print('DEBUG: ' + nickname +
 | 
			
		||||
                              ' was not authorized to access ' + self.path)
 | 
			
		||||
            if self.server.debug:
 | 
			
		||||
                print('DEBUG: GET access to events is unauthorized')
 | 
			
		||||
            self.send_response(405)
 | 
			
		||||
            self.end_headers()
 | 
			
		||||
            self.server.GETbusy = False
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        self._benchmarkGETtimings(GETstartTime, GETtimings, 47)
 | 
			
		||||
 | 
			
		||||
        # get outbox feed for a person
 | 
			
		||||
| 
						 | 
				
			
			@ -7892,7 +7987,7 @@ class PubServer(BaseHTTPRequestHandler):
 | 
			
		|||
                    followId = followActor + '/statuses/' + str(statusNumber)
 | 
			
		||||
                    unfollowJson = {
 | 
			
		||||
                        '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
                        'id': followId+'/undo',
 | 
			
		||||
                        'id': followId + '/undo',
 | 
			
		||||
                        'type': 'Undo',
 | 
			
		||||
                        'actor': followActor,
 | 
			
		||||
                        'object': {
 | 
			
		||||
| 
						 | 
				
			
			@ -8682,8 +8777,7 @@ class PubServer(BaseHTTPRequestHandler):
 | 
			
		|||
        if self.outboxAuthenticated:
 | 
			
		||||
            if self._postToOutbox(messageJson, __version__):
 | 
			
		||||
                if messageJson.get('id'):
 | 
			
		||||
                    locnStr = messageJson['id'].replace('/activity', '')
 | 
			
		||||
                    locnStr = locnStr.replace('/undo', '')
 | 
			
		||||
                    locnStr = removeIdEnding(messageJson['id'])
 | 
			
		||||
                    self.headers['Location'] = locnStr
 | 
			
		||||
                self.send_response(201)
 | 
			
		||||
                self.end_headers()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ __maintainer__ = "Bob Mottram"
 | 
			
		|||
__email__ = "bob@freedombone.net"
 | 
			
		||||
__status__ = "Production"
 | 
			
		||||
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import getStatusNumber
 | 
			
		||||
from utils import urlPermitted
 | 
			
		||||
from utils import getNicknameFromActor
 | 
			
		||||
| 
						 | 
				
			
			@ -257,7 +258,7 @@ def outboxDelete(baseDir: str, httpPrefix: str,
 | 
			
		|||
        if debug:
 | 
			
		||||
            print('DEBUG: delete not permitted from other instances')
 | 
			
		||||
        return
 | 
			
		||||
    messageId = messageJson['object'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['object'])
 | 
			
		||||
    if '/statuses/' not in messageId:
 | 
			
		||||
        if debug:
 | 
			
		||||
            print('DEBUG: c2s delete object is not a status')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								inbox.py
								
								
								
								
							
							
						
						
									
										27
									
								
								inbox.py
								
								
								
								
							| 
						 | 
				
			
			@ -10,6 +10,7 @@ import json
 | 
			
		|||
import os
 | 
			
		||||
import datetime
 | 
			
		||||
import time
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import getProtocolPrefixes
 | 
			
		||||
from utils import isBlogPost
 | 
			
		||||
from utils import removeAvatarFromCache
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +94,7 @@ def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None:
 | 
			
		|||
            continue
 | 
			
		||||
        tagName = tag['name'].replace('#', '').strip()
 | 
			
		||||
        tagsFilename = tagsDir + '/' + tagName + '.txt'
 | 
			
		||||
        postUrl = postJsonObject['id'].replace('/activity', '')
 | 
			
		||||
        postUrl = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
        postUrl = postUrl.replace('/', '#')
 | 
			
		||||
        daysDiff = datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)
 | 
			
		||||
        daysSinceEpoch = daysDiff.days
 | 
			
		||||
| 
						 | 
				
			
			@ -354,15 +355,13 @@ def savePostToInboxQueue(baseDir: str, httpPrefix: str,
 | 
			
		|||
                        return None
 | 
			
		||||
    originalPostId = None
 | 
			
		||||
    if postJsonObject.get('id'):
 | 
			
		||||
        originalPostId = \
 | 
			
		||||
            postJsonObject['id'].replace('/activity', '').replace('/undo', '')
 | 
			
		||||
        originalPostId = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
 | 
			
		||||
    currTime = datetime.datetime.utcnow()
 | 
			
		||||
 | 
			
		||||
    postId = None
 | 
			
		||||
    if postJsonObject.get('id'):
 | 
			
		||||
        postId = postJsonObject['id'].replace('/activity', '')
 | 
			
		||||
        postId = postId.replace('/undo', '')
 | 
			
		||||
        postId = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
        published = currTime.strftime("%Y-%m-%dT%H:%M:%SZ")
 | 
			
		||||
    if not postId:
 | 
			
		||||
        statusNumber, published = getStatusNumber()
 | 
			
		||||
| 
						 | 
				
			
			@ -817,9 +816,7 @@ def receiveEventPost(recentPostsCache: {}, session, baseDir: str,
 | 
			
		|||
        if port != 80 and port != 443:
 | 
			
		||||
            handle += ':' + str(port)
 | 
			
		||||
 | 
			
		||||
    postId = \
 | 
			
		||||
        messageJson['id'].replace('/activity', '').replace('/', '#')
 | 
			
		||||
    postId = postId.replace('/event', '')
 | 
			
		||||
    postId = removeIdEnding(messageJson['id']).replace('/', '#')
 | 
			
		||||
 | 
			
		||||
    saveEventPost(baseDir, handle, postId, messageJson['object'])
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -910,7 +907,7 @@ def receiveUpdateToQuestion(recentPostsCache: {}, messageJson: {},
 | 
			
		|||
        return
 | 
			
		||||
    if not messageJson.get('actor'):
 | 
			
		||||
        return
 | 
			
		||||
    messageId = messageJson['id'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['id'])
 | 
			
		||||
    if '#' in messageId:
 | 
			
		||||
        messageId = messageId.split('#', 1)[0]
 | 
			
		||||
    # find the question post
 | 
			
		||||
| 
						 | 
				
			
			@ -1367,8 +1364,7 @@ def receiveDelete(session, handle: str, isGroup: bool, baseDir: str,
 | 
			
		|||
    if not os.path.isdir(baseDir + '/accounts/' + handle):
 | 
			
		||||
        print('DEBUG: unknown recipient of like - ' + handle)
 | 
			
		||||
    # if this post in the outbox of the person?
 | 
			
		||||
    messageId = messageJson['object'].replace('/activity', '')
 | 
			
		||||
    messageId = messageId.replace('/undo', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['object'])
 | 
			
		||||
    removeModerationPostFromIndex(baseDir, messageId, debug)
 | 
			
		||||
    postFilename = locatePost(baseDir, handle.split('@')[0],
 | 
			
		||||
                              handle.split('@')[1], messageId)
 | 
			
		||||
| 
						 | 
				
			
			@ -1653,8 +1649,7 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
 | 
			
		|||
        return False
 | 
			
		||||
    # populate a text file containing the ids of replies
 | 
			
		||||
    postRepliesFilename = postFilename.replace('.json', '.replies')
 | 
			
		||||
    messageId = messageJson['id'].replace('/activity', '')
 | 
			
		||||
    messageId = messageId.replace('/undo', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['id'])
 | 
			
		||||
    if os.path.isfile(postRepliesFilename):
 | 
			
		||||
        numLines = sum(1 for line in open(postRepliesFilename))
 | 
			
		||||
        if numLines > maxReplies:
 | 
			
		||||
| 
						 | 
				
			
			@ -2070,8 +2065,7 @@ def inboxUpdateCalendar(baseDir: str, handle: str, postJsonObject: {}) -> None:
 | 
			
		|||
                                   actorNickname, actorDomain):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    postId = \
 | 
			
		||||
        postJsonObject['id'].replace('/activity', '').replace('/', '#')
 | 
			
		||||
    postId = removeIdEnding(postJsonObject['id']).replace('/', '#')
 | 
			
		||||
 | 
			
		||||
    # look for events within the tags list
 | 
			
		||||
    for tagDict in postJsonObject['object']['tag']:
 | 
			
		||||
| 
						 | 
				
			
			@ -2375,6 +2369,9 @@ def inboxAfterCapabilities(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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								like.py
								
								
								
								
							
							
						
						
									
										5
									
								
								like.py
								
								
								
								
							| 
						 | 
				
			
			@ -6,6 +6,7 @@ __maintainer__ = "Bob Mottram"
 | 
			
		|||
__email__ = "bob@freedombone.net"
 | 
			
		||||
__status__ = "Production"
 | 
			
		||||
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import urlPermitted
 | 
			
		||||
from utils import getNicknameFromActor
 | 
			
		||||
from utils import getDomainFromActor
 | 
			
		||||
| 
						 | 
				
			
			@ -411,7 +412,7 @@ def outboxLike(recentPostsCache: {},
 | 
			
		|||
    if debug:
 | 
			
		||||
        print('DEBUG: c2s like request arrived in outbox')
 | 
			
		||||
 | 
			
		||||
    messageId = messageJson['object'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['object'])
 | 
			
		||||
    if ':' in domain:
 | 
			
		||||
        domain = domain.split(':')[0]
 | 
			
		||||
    postFilename = locatePost(baseDir, nickname, domain, messageId)
 | 
			
		||||
| 
						 | 
				
			
			@ -462,7 +463,7 @@ def outboxUndoLike(recentPostsCache: {},
 | 
			
		|||
    if debug:
 | 
			
		||||
        print('DEBUG: c2s undo like request arrived in outbox')
 | 
			
		||||
 | 
			
		||||
    messageId = messageJson['object']['object'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(messageJson['object']['object'])
 | 
			
		||||
    if ':' in domain:
 | 
			
		||||
        domain = domain.split(':')[0]
 | 
			
		||||
    postFilename = locatePost(baseDir, nickname, domain, messageId)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								outbox.py
								
								
								
								
							
							
						
						
									
										11
									
								
								outbox.py
								
								
								
								
							| 
						 | 
				
			
			@ -13,6 +13,7 @@ from posts import outboxMessageCreateWrap
 | 
			
		|||
from posts import savePostToBox
 | 
			
		||||
from posts import sendToFollowersThread
 | 
			
		||||
from posts import sendToNamedAddresses
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import getDomainFromActor
 | 
			
		||||
from blocking import isBlockedDomain
 | 
			
		||||
from blocking import outboxBlock
 | 
			
		||||
| 
						 | 
				
			
			@ -159,8 +160,7 @@ def postMessageToOutbox(messageJson: {}, postToNickname: str,
 | 
			
		|||
                  ' is not a permitted activity type')
 | 
			
		||||
        return False
 | 
			
		||||
    if messageJson.get('id'):
 | 
			
		||||
        postId = \
 | 
			
		||||
            messageJson['id'].replace('/activity', '').replace('/undo', '')
 | 
			
		||||
        postId = removeIdEnding(messageJson['id'])
 | 
			
		||||
        if debug:
 | 
			
		||||
            print('DEBUG: id attribute exists within POST to outbox')
 | 
			
		||||
    else:
 | 
			
		||||
| 
						 | 
				
			
			@ -172,13 +172,15 @@ def postMessageToOutbox(messageJson: {}, postToNickname: str,
 | 
			
		|||
    if messageJson['type'] != 'Upgrade':
 | 
			
		||||
        outboxName = 'outbox'
 | 
			
		||||
 | 
			
		||||
        # if this is a blog post then save to its own box
 | 
			
		||||
        # if this is a blog post or an event then save to its own box
 | 
			
		||||
        if messageJson['type'] == 'Create':
 | 
			
		||||
            if messageJson.get('object'):
 | 
			
		||||
                if isinstance(messageJson['object'], dict):
 | 
			
		||||
                    if messageJson['object'].get('type'):
 | 
			
		||||
                        if messageJson['object']['type'] == 'Article':
 | 
			
		||||
                            outboxName = 'tlblogs'
 | 
			
		||||
                        elif messageJson['object']['type'] == 'Event':
 | 
			
		||||
                            outboxName = 'tlevents'
 | 
			
		||||
 | 
			
		||||
        savedFilename = \
 | 
			
		||||
            savePostToBox(baseDir,
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +198,8 @@ def postMessageToOutbox(messageJson: {}, postToNickname: str,
 | 
			
		|||
           messageJson['type'] == 'Announce':
 | 
			
		||||
            indexes = [outboxName, "inbox"]
 | 
			
		||||
            for boxNameIndex in indexes:
 | 
			
		||||
                if boxNameIndex == 'inbox' and outboxName == 'tlblogs':
 | 
			
		||||
                if ((boxNameIndex == 'inbox') and
 | 
			
		||||
                   (outboxName == 'tlblogs' or outboxName == 'tlevents')):
 | 
			
		||||
                    continue
 | 
			
		||||
                selfActor = \
 | 
			
		||||
                    httpPrefix + '://' + domainFull + \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ from posts import createRepliesTimeline
 | 
			
		|||
from posts import createMediaTimeline
 | 
			
		||||
from posts import createBlogsTimeline
 | 
			
		||||
from posts import createBookmarksTimeline
 | 
			
		||||
from posts import createEventsTimeline
 | 
			
		||||
from posts import createInbox
 | 
			
		||||
from posts import createOutbox
 | 
			
		||||
from posts import createModeration
 | 
			
		||||
| 
						 | 
				
			
			@ -598,7 +599,8 @@ def personBoxJson(recentPostsCache: {},
 | 
			
		|||
       boxname != 'tlreplies' and boxname != 'tlmedia' and \
 | 
			
		||||
       boxname != 'tlblogs' and \
 | 
			
		||||
       boxname != 'outbox' and boxname != 'moderation' and \
 | 
			
		||||
       boxname != 'tlbookmarks' and boxname != 'bookmarks':
 | 
			
		||||
       boxname != 'tlbookmarks' and boxname != 'bookmarks' and \
 | 
			
		||||
       boxname != 'tlevents' and boxname != 'events':
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    if not '/' + boxname in path:
 | 
			
		||||
| 
						 | 
				
			
			@ -646,6 +648,11 @@ def personBoxJson(recentPostsCache: {},
 | 
			
		|||
                                       port, httpPrefix,
 | 
			
		||||
                                       noOfItems, headerOnly, ocapAlways,
 | 
			
		||||
                                       pageNumber)
 | 
			
		||||
    elif boxname == 'tlevents' or boxname == 'events':
 | 
			
		||||
        return createEventsTimeline(session, baseDir, nickname, domain,
 | 
			
		||||
                                    port, httpPrefix,
 | 
			
		||||
                                    noOfItems, headerOnly, ocapAlways,
 | 
			
		||||
                                    pageNumber)
 | 
			
		||||
    elif boxname == 'tlreplies':
 | 
			
		||||
        return createRepliesTimeline(session, baseDir, nickname, domain,
 | 
			
		||||
                                     port, httpPrefix,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										50
									
								
								posts.py
								
								
								
								
							
							
						
						
									
										50
									
								
								posts.py
								
								
								
								
							| 
						 | 
				
			
			@ -29,6 +29,7 @@ from session import postJsonString
 | 
			
		|||
from session import postImage
 | 
			
		||||
from webfinger import webfingerHandle
 | 
			
		||||
from httpsig import createSignedHeader
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import siteIsActive
 | 
			
		||||
from utils import removePostFromCache
 | 
			
		||||
from utils import getCachedPostFilename
 | 
			
		||||
| 
						 | 
				
			
			@ -502,7 +503,8 @@ def deleteAllPosts(baseDir: str,
 | 
			
		|||
                   nickname: str, domain: str, boxname: str) -> None:
 | 
			
		||||
    """Deletes all posts for a person from inbox or outbox
 | 
			
		||||
    """
 | 
			
		||||
    if boxname != 'inbox' and boxname != 'outbox' and boxname != 'tlblogs':
 | 
			
		||||
    if boxname != 'inbox' and boxname != 'outbox' and \
 | 
			
		||||
       boxname != 'tlblogs' and boxname != 'tlevents':
 | 
			
		||||
        return
 | 
			
		||||
    boxDir = createPersonDir(nickname, domain, baseDir, boxname)
 | 
			
		||||
    for deleteFilename in os.scandir(boxDir):
 | 
			
		||||
| 
						 | 
				
			
			@ -524,7 +526,8 @@ def savePostToBox(baseDir: str, httpPrefix: str, postId: str,
 | 
			
		|||
    Returns the filename
 | 
			
		||||
    """
 | 
			
		||||
    if boxname != 'inbox' and boxname != 'outbox' and \
 | 
			
		||||
       boxname != 'tlblogs' and boxname != 'scheduled':
 | 
			
		||||
       boxname != 'tlblogs' and boxname != 'tlevents' and \
 | 
			
		||||
       boxname != 'scheduled':
 | 
			
		||||
        return None
 | 
			
		||||
    originalDomain = domain
 | 
			
		||||
    if ':' in domain:
 | 
			
		||||
| 
						 | 
				
			
			@ -845,7 +848,7 @@ def createPostBase(baseDir: str, nickname: str, domain: str, port: int,
 | 
			
		|||
            '/statuses/' + statusNumber + '/replies'
 | 
			
		||||
        newPost = {
 | 
			
		||||
            '@context': postContext,
 | 
			
		||||
            'id': newPostId+'/activity',
 | 
			
		||||
            'id': newPostId + '/activity',
 | 
			
		||||
            'capability': capabilityIdList,
 | 
			
		||||
            'type': 'Create',
 | 
			
		||||
            'actor': actorUrl,
 | 
			
		||||
| 
						 | 
				
			
			@ -977,12 +980,15 @@ def createPostBase(baseDir: str, nickname: str, domain: str, port: int,
 | 
			
		|||
                  'date and time values')
 | 
			
		||||
            return newPost
 | 
			
		||||
    elif saveToFile:
 | 
			
		||||
        if not isArticle:
 | 
			
		||||
            savePostToBox(baseDir, httpPrefix, newPostId,
 | 
			
		||||
                          nickname, domain, newPost, 'outbox')
 | 
			
		||||
        else:
 | 
			
		||||
        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')
 | 
			
		||||
    return newPost
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1009,10 +1015,10 @@ def outboxMessageCreateWrap(httpPrefix: str,
 | 
			
		|||
    capabilityUrl = []
 | 
			
		||||
    newPost = {
 | 
			
		||||
        "@context": "https://www.w3.org/ns/activitystreams",
 | 
			
		||||
        'id': newPostId+'/activity',
 | 
			
		||||
        'id': newPostId + '/activity',
 | 
			
		||||
        'capability': capabilityUrl,
 | 
			
		||||
        'type': 'Create',
 | 
			
		||||
        'actor': httpPrefix+'://'+domain+'/users/'+nickname,
 | 
			
		||||
        'actor': httpPrefix + '://' + domain + '/users/' + nickname,
 | 
			
		||||
        'published': published,
 | 
			
		||||
        'to': messageJson['to'],
 | 
			
		||||
        'cc': cc,
 | 
			
		||||
| 
						 | 
				
			
			@ -1473,8 +1479,9 @@ def createReportPost(baseDir: str,
 | 
			
		|||
            continue
 | 
			
		||||
 | 
			
		||||
        # update the inbox index with the report filename
 | 
			
		||||
        # indexFilename=baseDir+'/accounts/'+handle+'/inbox.index'
 | 
			
		||||
        # indexEntry=postJsonObject['id'].replace('/activity','').replace('/','#')+'.json'
 | 
			
		||||
        # indexFilename = baseDir+'/accounts/'+handle+'/inbox.index'
 | 
			
		||||
        # indexEntry = \
 | 
			
		||||
        #     removeIdEnding(postJsonObject['id']).replace('/','#') + '.json'
 | 
			
		||||
        # if indexEntry not in open(indexFilename).read():
 | 
			
		||||
        #     try:
 | 
			
		||||
        #         with open(indexFilename, 'a+') as fp:
 | 
			
		||||
| 
						 | 
				
			
			@ -2419,6 +2426,16 @@ def createBookmarksTimeline(session, baseDir: str, nickname: str, domain: str,
 | 
			
		|||
                            True, ocapAlways, pageNumber)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def createEventsTimeline(session, baseDir: str, nickname: str, domain: str,
 | 
			
		||||
                         port: int, httpPrefix: str, itemsPerPage: int,
 | 
			
		||||
                         headerOnly: bool, ocapAlways: bool,
 | 
			
		||||
                         pageNumber=None) -> {}:
 | 
			
		||||
    return createBoxIndexed({}, session, baseDir, 'tlevents',
 | 
			
		||||
                            nickname, domain,
 | 
			
		||||
                            port, httpPrefix, itemsPerPage, headerOnly,
 | 
			
		||||
                            True, ocapAlways, pageNumber)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def createDMTimeline(session, baseDir: str, nickname: str, domain: str,
 | 
			
		||||
                     port: int, httpPrefix: str, itemsPerPage: int,
 | 
			
		||||
                     headerOnly: bool, ocapAlways: bool,
 | 
			
		||||
| 
						 | 
				
			
			@ -2791,14 +2808,19 @@ def createBoxIndexed(recentPostsCache: {},
 | 
			
		|||
       boxname != 'tlreplies' and boxname != 'tlmedia' and \
 | 
			
		||||
       boxname != 'tlblogs' and \
 | 
			
		||||
       boxname != 'outbox' and boxname != 'tlbookmarks' and \
 | 
			
		||||
       boxname != 'bookmarks':
 | 
			
		||||
       boxname != 'bookmarks' and \
 | 
			
		||||
       boxname != 'tlevents' and boxname != 'events':
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    # bookmarks timeline is like the inbox but has its own separate index
 | 
			
		||||
    # bookmarks and events timelines are like the inbox
 | 
			
		||||
    # but have their own separate index
 | 
			
		||||
    indexBoxName = boxname
 | 
			
		||||
    if boxname == "tlbookmarks":
 | 
			
		||||
        boxname = "bookmarks"
 | 
			
		||||
        indexBoxName = boxname
 | 
			
		||||
    elif boxname == "tlevents":
 | 
			
		||||
        boxname = "events"
 | 
			
		||||
        indexBoxName = boxname
 | 
			
		||||
 | 
			
		||||
    if port:
 | 
			
		||||
        if port != 80 and port != 443:
 | 
			
		||||
| 
						 | 
				
			
			@ -3489,7 +3511,7 @@ def mutePost(baseDir: str, nickname: str, domain: str, postId: str,
 | 
			
		|||
    # if the post is in the recent posts cache then mark it as muted
 | 
			
		||||
    if recentPostsCache.get('index'):
 | 
			
		||||
        postId = \
 | 
			
		||||
            postJsonObject['id'].replace('/activity', '').replace('/', '#')
 | 
			
		||||
            removeIdEnding(postJsonObject['id']).replace('/', '#')
 | 
			
		||||
        if postId in recentPostsCache['index']:
 | 
			
		||||
            print('MUTE: ' + postId + ' is in recent posts cache')
 | 
			
		||||
            if recentPostsCache['json'].get(postId):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										30
									
								
								tests.py
								
								
								
								
							
							
						
						
									
										30
									
								
								tests.py
								
								
								
								
							| 
						 | 
				
			
			@ -31,6 +31,7 @@ from follow import clearFollows
 | 
			
		|||
from follow import clearFollowers
 | 
			
		||||
from follow import sendFollowRequestViaServer
 | 
			
		||||
from follow import sendUnfollowRequestViaServer
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import siteIsActive
 | 
			
		||||
from utils import updateRecentPostsCache
 | 
			
		||||
from utils import followPerson
 | 
			
		||||
| 
						 | 
				
			
			@ -1364,7 +1365,7 @@ def testClientToServer():
 | 
			
		|||
            outboxPostFilename = outboxPath + '/' + name
 | 
			
		||||
            postJsonObject = loadJson(outboxPostFilename, 0)
 | 
			
		||||
            if postJsonObject:
 | 
			
		||||
                outboxPostId = postJsonObject['id'].replace('/activity', '')
 | 
			
		||||
                outboxPostId = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
    assert outboxPostId
 | 
			
		||||
    print('message id obtained: ' + outboxPostId)
 | 
			
		||||
    assert validInbox(bobDir, 'bob', bobDomain)
 | 
			
		||||
| 
						 | 
				
			
			@ -2014,8 +2015,35 @@ def testJsonPostAllowsComments():
 | 
			
		|||
    assert not jsonPostAllowsComments(postJsonObject)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def testRemoveIdEnding():
 | 
			
		||||
    print('testRemoveIdEnding')
 | 
			
		||||
    testStr = 'https://activitypub.somedomain.net'
 | 
			
		||||
    resultStr = removeIdEnding(testStr)
 | 
			
		||||
    assert resultStr == 'https://activitypub.somedomain.net'
 | 
			
		||||
 | 
			
		||||
    testStr = \
 | 
			
		||||
        'https://activitypub.somedomain.net/users/foo/' + \
 | 
			
		||||
        'statuses/34544814814/activity'
 | 
			
		||||
    resultStr = removeIdEnding(testStr)
 | 
			
		||||
    assert resultStr == \
 | 
			
		||||
        'https://activitypub.somedomain.net/users/foo/statuses/34544814814'
 | 
			
		||||
 | 
			
		||||
    testStr = \
 | 
			
		||||
        'https://undo.somedomain.net/users/foo/statuses/34544814814/undo'
 | 
			
		||||
    resultStr = removeIdEnding(testStr)
 | 
			
		||||
    assert resultStr == \
 | 
			
		||||
        'https://undo.somedomain.net/users/foo/statuses/34544814814'
 | 
			
		||||
 | 
			
		||||
    testStr = \
 | 
			
		||||
        'https://event.somedomain.net/users/foo/statuses/34544814814/event'
 | 
			
		||||
    resultStr = removeIdEnding(testStr)
 | 
			
		||||
    assert resultStr == \
 | 
			
		||||
        'https://event.somedomain.net/users/foo/statuses/34544814814'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def runAllTests():
 | 
			
		||||
    print('Running tests...')
 | 
			
		||||
    testRemoveIdEnding()
 | 
			
		||||
    testJsonPostAllowsComments()
 | 
			
		||||
    runHtmlReplaceQuoteMarks()
 | 
			
		||||
    testDangerousMarkup()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "ملاحظات",
 | 
			
		||||
    "Allow replies.": "السماح بالردود.",
 | 
			
		||||
    "Event": "حدث",
 | 
			
		||||
    "Events": "الأحداث",
 | 
			
		||||
    "Create an event": "أنشئ حدثًا",
 | 
			
		||||
    "Describe the event": "صف الحدث",
 | 
			
		||||
    "Start Date": "تاريخ البدء",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Notes",
 | 
			
		||||
    "Allow replies.": "Permetre respostes.",
 | 
			
		||||
    "Event": "Esdeveniment",
 | 
			
		||||
    "Events": "Esdeveniments",
 | 
			
		||||
    "Create an event": "Crea un esdeveniment",
 | 
			
		||||
    "Describe the event": "Descriviu l’esdeveniment",
 | 
			
		||||
    "Start Date": "Data d'inici",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Nodiadau",
 | 
			
		||||
    "Allow replies.": "Caniatáu atebion.",
 | 
			
		||||
    "Event": "Digwyddiad",
 | 
			
		||||
    "Events": "Digwyddiadau",
 | 
			
		||||
    "Create an event": "Creu digwyddiad",
 | 
			
		||||
    "Describe the event": "Disgrifiwch y digwyddiad",
 | 
			
		||||
    "Start Date": "Dyddiad cychwyn",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Anmerkungen",
 | 
			
		||||
    "Allow replies.": "Antworten zulassen.",
 | 
			
		||||
    "Event": "Veranstaltung",
 | 
			
		||||
    "Events": "Veranstaltungen",
 | 
			
		||||
    "Create an event": "Erstellen Sie ein Ereignis",
 | 
			
		||||
    "Describe the event": "Beschreiben Sie das Ereignis",
 | 
			
		||||
    "Start Date": "Anfangsdatum",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Notes",
 | 
			
		||||
    "Allow replies.": "Allow replies.",
 | 
			
		||||
    "Event": "Event",
 | 
			
		||||
    "Events": "Events",
 | 
			
		||||
    "Create an event": "Create an event",
 | 
			
		||||
    "Describe the event": "Describe the event",
 | 
			
		||||
    "Start Date": "Start Date",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Notas",
 | 
			
		||||
    "Allow replies.": "Permitir respuestas.",
 | 
			
		||||
    "Event": "Evento",
 | 
			
		||||
    "Events": "Eventos",
 | 
			
		||||
    "Create an event": "Crea un evento",
 | 
			
		||||
    "Describe the event": "Describe el evento",
 | 
			
		||||
    "Start Date": "Fecha de inicio",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Remarques",
 | 
			
		||||
    "Allow replies.": "Autoriser les réponses.",
 | 
			
		||||
    "Event": "un événement",
 | 
			
		||||
    "Events": "Événements",
 | 
			
		||||
    "Create an event": "Créer un événement",
 | 
			
		||||
    "Describe the event": "Décrivez l'événement",
 | 
			
		||||
    "Start Date": "Date de début",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Nótaí",
 | 
			
		||||
    "Allow replies.": "Ceadaigh freagraí.",
 | 
			
		||||
    "Event": "Imeacht",
 | 
			
		||||
    "Events": "Imeachtaí",
 | 
			
		||||
    "Create an event": "Cruthaigh imeacht",
 | 
			
		||||
    "Describe the event": "Déan cur síos ar an ócáid",
 | 
			
		||||
    "Start Date": "Dáta tosaigh",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "टिप्पणियाँ",
 | 
			
		||||
    "Allow replies.": "जवाब दें।",
 | 
			
		||||
    "Event": "प्रतिस्पर्धा",
 | 
			
		||||
    "Events": "आयोजन",
 | 
			
		||||
    "Create an event": "एक घटना बनाएँ",
 | 
			
		||||
    "Describe the event": "घटना का वर्णन करें",
 | 
			
		||||
    "Start Date": "आरंभ करने की तिथि",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Appunti",
 | 
			
		||||
    "Allow replies.": "Consenti risposte.",
 | 
			
		||||
    "Event": "Evento",
 | 
			
		||||
    "Events": "Eventi",
 | 
			
		||||
    "Create an event": "Crea un evento",
 | 
			
		||||
    "Describe the event": "Descrivi l'evento",
 | 
			
		||||
    "Start Date": "Data d'inizio",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "ノート",
 | 
			
		||||
    "Allow replies.": "返信を許可します。",
 | 
			
		||||
    "Event": "イベント",
 | 
			
		||||
    "Events": "イベント",
 | 
			
		||||
    "Create an event": "イベントを作成する",
 | 
			
		||||
    "Describe the event": "イベントについて説明する",
 | 
			
		||||
    "Start Date": "開始日",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -254,6 +254,7 @@
 | 
			
		|||
    "Notes": "Notes",
 | 
			
		||||
    "Allow replies.": "Allow replies.",
 | 
			
		||||
    "Event": "Event",
 | 
			
		||||
    "Events": "Events",
 | 
			
		||||
    "Create an event": "Create an event",
 | 
			
		||||
    "Describe the event": "Describe the event",
 | 
			
		||||
    "Start Date": "Start Date",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Notas",
 | 
			
		||||
    "Allow replies.": "Permitir respostas.",
 | 
			
		||||
    "Event": "Evento",
 | 
			
		||||
    "Events": "Eventos",
 | 
			
		||||
    "Create an event": "Crie um evento",
 | 
			
		||||
    "Describe the event": "Descreva o evento",
 | 
			
		||||
    "Start Date": "Data de início",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "Ноты",
 | 
			
		||||
    "Allow replies.": "Разрешить ответы.",
 | 
			
		||||
    "Event": "Мероприятие",
 | 
			
		||||
    "Events": "События",
 | 
			
		||||
    "Create an event": "Создать мероприятие",
 | 
			
		||||
    "Describe the event": "Опишите событие",
 | 
			
		||||
    "Start Date": "Дата начала",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,6 +258,7 @@
 | 
			
		|||
    "Notes": "笔记",
 | 
			
		||||
    "Allow replies.": "允许回复。",
 | 
			
		||||
    "Event": "事件",
 | 
			
		||||
    "Events": "大事记",
 | 
			
		||||
    "Create an event": "建立活动",
 | 
			
		||||
    "Describe the event": "描述事件",
 | 
			
		||||
    "Start Date": "开始日期",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								utils.py
								
								
								
								
							
							
						
						
									
										35
									
								
								utils.py
								
								
								
								
							| 
						 | 
				
			
			@ -19,6 +19,18 @@ from calendar import monthrange
 | 
			
		|||
from followingCalendar import addPersonToCalendar
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def removeIdEnding(idStr: str) -> str:
 | 
			
		||||
    """Removes endings such as /activity and /undo
 | 
			
		||||
    """
 | 
			
		||||
    if idStr.endswith('/activity'):
 | 
			
		||||
        idStr = idStr[:-len('/activity')]
 | 
			
		||||
    elif idStr.endswith('/undo'):
 | 
			
		||||
        idStr = idStr[:-len('/undo')]
 | 
			
		||||
    elif idStr.endswith('/event'):
 | 
			
		||||
        idStr = idStr[:-len('/event')]
 | 
			
		||||
    return idStr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getProtocolPrefixes() -> []:
 | 
			
		||||
    """Returns a list of valid prefixes
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -384,13 +396,13 @@ def locatePost(baseDir: str, nickname: str, domain: str,
 | 
			
		|||
        extension = 'replies'
 | 
			
		||||
 | 
			
		||||
    # if this post in the shared inbox?
 | 
			
		||||
    postUrl = postUrl.replace('/', '#').replace('/activity', '').strip()
 | 
			
		||||
    postUrl = removeIdEnding(postUrl.strip()).replace('/', '#')
 | 
			
		||||
 | 
			
		||||
    # add the extension
 | 
			
		||||
    postUrl = postUrl + '.' + extension
 | 
			
		||||
 | 
			
		||||
    # search boxes
 | 
			
		||||
    boxes = ('inbox', 'outbox', 'tlblogs')
 | 
			
		||||
    boxes = ('inbox', 'outbox', 'tlblogs', 'tlevents')
 | 
			
		||||
    accountDir = baseDir + '/accounts/' + nickname + '@' + domain + '/'
 | 
			
		||||
    for boxName in boxes:
 | 
			
		||||
        postFilename = accountDir + boxName + '/' + postUrl
 | 
			
		||||
| 
						 | 
				
			
			@ -435,7 +447,7 @@ def removeModerationPostFromIndex(baseDir: str, postUrl: str,
 | 
			
		|||
    moderationIndexFile = baseDir + '/accounts/moderation.txt'
 | 
			
		||||
    if not os.path.isfile(moderationIndexFile):
 | 
			
		||||
        return
 | 
			
		||||
    postId = postUrl.replace('/activity', '')
 | 
			
		||||
    postId = removeIdEnding(postUrl)
 | 
			
		||||
    if postId in open(moderationIndexFile).read():
 | 
			
		||||
        with open(moderationIndexFile, "r") as f:
 | 
			
		||||
            lines = f.readlines()
 | 
			
		||||
| 
						 | 
				
			
			@ -463,7 +475,7 @@ def isReplyToBlogPost(baseDir: str, nickname: str, domain: str,
 | 
			
		|||
        nickname + '@' + domain + '/tlblogs.index'
 | 
			
		||||
    if not os.path.isfile(blogsIndexFilename):
 | 
			
		||||
        return False
 | 
			
		||||
    postId = postJsonObject['object']['inReplyTo'].replace('/activity', '')
 | 
			
		||||
    postId = removeIdEnding(postJsonObject['object']['inReplyTo'])
 | 
			
		||||
    postId = postId.replace('/', '#')
 | 
			
		||||
    if postId in open(blogsIndexFilename).read():
 | 
			
		||||
        return True
 | 
			
		||||
| 
						 | 
				
			
			@ -494,7 +506,7 @@ def deletePost(baseDir: str, httpPrefix: str,
 | 
			
		|||
        # remove from recent posts cache in memory
 | 
			
		||||
        if recentPostsCache:
 | 
			
		||||
            postId = \
 | 
			
		||||
                postJsonObject['id'].replace('/activity', '').replace('/', '#')
 | 
			
		||||
                removeIdEnding(postJsonObject['id']).replace('/', '#')
 | 
			
		||||
            if recentPostsCache.get('index'):
 | 
			
		||||
                if postId in recentPostsCache['index']:
 | 
			
		||||
                    recentPostsCache['index'].remove(postId)
 | 
			
		||||
| 
						 | 
				
			
			@ -526,7 +538,7 @@ def deletePost(baseDir: str, httpPrefix: str,
 | 
			
		|||
            if isinstance(postJsonObject['object'], dict):
 | 
			
		||||
                if postJsonObject['object'].get('moderationStatus'):
 | 
			
		||||
                    if postJsonObject.get('id'):
 | 
			
		||||
                        postId = postJsonObject['id'].replace('/activity', '')
 | 
			
		||||
                        postId = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
                        removeModerationPostFromIndex(baseDir, postId, debug)
 | 
			
		||||
 | 
			
		||||
        # remove any hashtags index entries
 | 
			
		||||
| 
						 | 
				
			
			@ -540,8 +552,7 @@ def deletePost(baseDir: str, httpPrefix: str,
 | 
			
		|||
            if postJsonObject['object'].get('id') and \
 | 
			
		||||
               postJsonObject['object'].get('tag'):
 | 
			
		||||
                # get the id of the post
 | 
			
		||||
                postId = \
 | 
			
		||||
                    postJsonObject['object']['id'].replace('/activity', '')
 | 
			
		||||
                postId = removeIdEnding(postJsonObject['object']['id'])
 | 
			
		||||
                for tag in postJsonObject['object']['tag']:
 | 
			
		||||
                    if tag['type'] != 'Hashtag':
 | 
			
		||||
                        continue
 | 
			
		||||
| 
						 | 
				
			
			@ -710,7 +721,7 @@ def getCachedPostFilename(baseDir: str, nickname: str, domain: str,
 | 
			
		|||
        return None
 | 
			
		||||
    cachedPostFilename = \
 | 
			
		||||
        cachedPostDir + \
 | 
			
		||||
        '/' + postJsonObject['id'].replace('/activity', '').replace('/', '#')
 | 
			
		||||
        '/' + removeIdEnding(postJsonObject['id']).replace('/', '#')
 | 
			
		||||
    cachedPostFilename = cachedPostFilename + '.html'
 | 
			
		||||
    return cachedPostFilename
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -727,7 +738,7 @@ def removePostFromCache(postJsonObject: {}, recentPostsCache: {}):
 | 
			
		|||
    postId = postJsonObject['id']
 | 
			
		||||
    if '#' in postId:
 | 
			
		||||
        postId = postId.split('#', 1)[0]
 | 
			
		||||
    postId = postId.replace('/activity', '').replace('/', '#')
 | 
			
		||||
    postId = removeIdEnding(postId).replace('/', '#')
 | 
			
		||||
    if postId not in recentPostsCache['index']:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -747,7 +758,7 @@ def updateRecentPostsCache(recentPostsCache: {}, maxRecentPosts: int,
 | 
			
		|||
    postId = postJsonObject['id']
 | 
			
		||||
    if '#' in postId:
 | 
			
		||||
        postId = postId.split('#', 1)[0]
 | 
			
		||||
    postId = postId.replace('/activity', '').replace('/', '#')
 | 
			
		||||
    postId = removeIdEnding(postId).replace('/', '#')
 | 
			
		||||
    if recentPostsCache.get('index'):
 | 
			
		||||
        if postId in recentPostsCache['index']:
 | 
			
		||||
            return
 | 
			
		||||
| 
						 | 
				
			
			@ -1071,7 +1082,7 @@ def updateAnnounceCollection(recentPostsCache: {},
 | 
			
		|||
            return
 | 
			
		||||
        if not isinstance(postJsonObject['object'], dict):
 | 
			
		||||
            return
 | 
			
		||||
        postUrl = postJsonObject['id'].replace('/activity', '') + '/shares'
 | 
			
		||||
        postUrl = removeIdEnding(postJsonObject['id']) + '/shares'
 | 
			
		||||
        if not postJsonObject['object'].get('shares'):
 | 
			
		||||
            if debug:
 | 
			
		||||
                print('DEBUG: Adding initial shares (announcements) to ' +
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ from ssb import getSSBAddress
 | 
			
		|||
from tox import getToxAddress
 | 
			
		||||
from matrix import getMatrixAddress
 | 
			
		||||
from donate import getDonationUrl
 | 
			
		||||
from utils import removeIdEnding
 | 
			
		||||
from utils import getProtocolPrefixes
 | 
			
		||||
from utils import getFileCaseInsensitive
 | 
			
		||||
from utils import searchBoxPosts
 | 
			
		||||
| 
						 | 
				
			
			@ -3313,7 +3314,7 @@ def insertQuestion(baseDir: str, translate: {},
 | 
			
		|||
        return content
 | 
			
		||||
    if len(postJsonObject['object']['oneOf']) == 0:
 | 
			
		||||
        return content
 | 
			
		||||
    messageId = postJsonObject['id'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
    if '#' in messageId:
 | 
			
		||||
        messageId = messageId.split('#', 1)[0]
 | 
			
		||||
    pageNumberStr = ''
 | 
			
		||||
| 
						 | 
				
			
			@ -3781,7 +3782,7 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
 | 
			
		|||
    avatarPosition = ''
 | 
			
		||||
    messageId = ''
 | 
			
		||||
    if postJsonObject.get('id'):
 | 
			
		||||
        messageId = postJsonObject['id'].replace('/activity', '')
 | 
			
		||||
        messageId = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
 | 
			
		||||
    messageIdStr = ''
 | 
			
		||||
    if messageId:
 | 
			
		||||
| 
						 | 
				
			
			@ -3870,7 +3871,7 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
 | 
			
		|||
    if boxName == 'tlbookmarks' or boxName == 'bookmarks':
 | 
			
		||||
        return ''
 | 
			
		||||
 | 
			
		||||
    timelinePostBookmark = postJsonObject['id'].replace('/activity', '')
 | 
			
		||||
    timelinePostBookmark = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
    timelinePostBookmark = timelinePostBookmark.replace('://', '-')
 | 
			
		||||
    timelinePostBookmark = timelinePostBookmark.replace('/', '-')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4007,8 +4008,8 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
 | 
			
		|||
 | 
			
		||||
    editStr = ''
 | 
			
		||||
    if fullDomain + '/users/' + nickname in postJsonObject['actor']:
 | 
			
		||||
        if isBlogPost(postJsonObject):
 | 
			
		||||
            if '/statuses/' in postJsonObject['object']['id']:
 | 
			
		||||
        if '/statuses/' in postJsonObject['object']['id']:
 | 
			
		||||
            if isBlogPost(postJsonObject):
 | 
			
		||||
                editStr += \
 | 
			
		||||
                    '<a class="imageAnchor" href="/users/' + nickname + \
 | 
			
		||||
                    '/tlblogs?editblogpost=' + \
 | 
			
		||||
| 
						 | 
				
			
			@ -4629,6 +4630,7 @@ def htmlTimeline(defaultTimeline: str,
 | 
			
		|||
        repliesButton = 'buttonhighlighted'
 | 
			
		||||
    mediaButton = 'button'
 | 
			
		||||
    bookmarksButton = 'button'
 | 
			
		||||
    eventsButton = 'button'
 | 
			
		||||
    sentButton = 'button'
 | 
			
		||||
    sharesButton = 'button'
 | 
			
		||||
    if newShare:
 | 
			
		||||
| 
						 | 
				
			
			@ -4662,6 +4664,8 @@ def htmlTimeline(defaultTimeline: str,
 | 
			
		|||
            sharesButton = 'buttonselectedhighlighted'
 | 
			
		||||
    elif boxName == 'tlbookmarks' or boxName == 'bookmarks':
 | 
			
		||||
        bookmarksButton = 'buttonselected'
 | 
			
		||||
    elif boxName == 'tlevents' or boxName == 'events':
 | 
			
		||||
        eventsButton = 'buttonselected'
 | 
			
		||||
 | 
			
		||||
    fullDomain = domain
 | 
			
		||||
    if port != 80 and port != 443:
 | 
			
		||||
| 
						 | 
				
			
			@ -4702,6 +4706,7 @@ def htmlTimeline(defaultTimeline: str,
 | 
			
		|||
 | 
			
		||||
    sharesButtonStr = ''
 | 
			
		||||
    bookmarksButtonStr = ''
 | 
			
		||||
    eventsButtonStr = ''
 | 
			
		||||
    if not minimal:
 | 
			
		||||
        sharesButtonStr = \
 | 
			
		||||
            '<a href="' + usersPath + '/tlshares"><button class="' + \
 | 
			
		||||
| 
						 | 
				
			
			@ -4714,6 +4719,11 @@ def htmlTimeline(defaultTimeline: str,
 | 
			
		|||
            bookmarksButton + '"><span>' + translate['Bookmarks'] + \
 | 
			
		||||
            ' </span></button></a>\n'
 | 
			
		||||
 | 
			
		||||
        eventsButtonStr = \
 | 
			
		||||
            '<a href="' + usersPath + '/tlevents"><button class="' + \
 | 
			
		||||
            eventsButton + '"><span>' + translate['Events'] + \
 | 
			
		||||
            ' </span></button></a>\n'
 | 
			
		||||
 | 
			
		||||
    tlStr = htmlHeader(cssFilename, profileStyle)
 | 
			
		||||
 | 
			
		||||
    if boxName != 'dm':
 | 
			
		||||
| 
						 | 
				
			
			@ -4835,7 +4845,7 @@ def htmlTimeline(defaultTimeline: str,
 | 
			
		|||
        sentButton+'"><span>' + translate['Outbox'] + \
 | 
			
		||||
        '</span></button></a>\n'
 | 
			
		||||
    tlStr += \
 | 
			
		||||
        sharesButtonStr + bookmarksButtonStr + \
 | 
			
		||||
        sharesButtonStr + bookmarksButtonStr + eventsButtonStr + \
 | 
			
		||||
        moderationButtonStr + newPostButtonStr
 | 
			
		||||
    tlStr += \
 | 
			
		||||
        '    <a class="imageAnchor" href="' + usersPath + \
 | 
			
		||||
| 
						 | 
				
			
			@ -4963,7 +4973,7 @@ def htmlTimeline(defaultTimeline: str,
 | 
			
		|||
                if boxName != 'tlmedia' and \
 | 
			
		||||
                   recentPostsCache.get('index'):
 | 
			
		||||
                    postId = \
 | 
			
		||||
                        item['id'].replace('/activity', '').replace('/', '#')
 | 
			
		||||
                        removeIdEnding(item['id']).replace('/', '#')
 | 
			
		||||
                    if postId in recentPostsCache['index']:
 | 
			
		||||
                        if not item.get('muted'):
 | 
			
		||||
                            if recentPostsCache['html'].get(postId):
 | 
			
		||||
| 
						 | 
				
			
			@ -5075,6 +5085,28 @@ def htmlBookmarks(defaultTimeline: str,
 | 
			
		|||
                        minimal, YTReplacementDomain)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def htmlEvents(defaultTimeline: str,
 | 
			
		||||
               recentPostsCache: {}, maxRecentPosts: int,
 | 
			
		||||
               translate: {}, pageNumber: int, itemsPerPage: int,
 | 
			
		||||
               session, baseDir: str, wfRequest: {}, personCache: {},
 | 
			
		||||
               nickname: str, domain: str, port: int, bookmarksJson: {},
 | 
			
		||||
               allowDeletion: bool,
 | 
			
		||||
               httpPrefix: str, projectVersion: str,
 | 
			
		||||
               minimal: bool, YTReplacementDomain: str) -> str:
 | 
			
		||||
    """Show the events as html
 | 
			
		||||
    """
 | 
			
		||||
    manuallyApproveFollowers = \
 | 
			
		||||
        followerApprovalActive(baseDir, nickname, domain)
 | 
			
		||||
 | 
			
		||||
    return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts,
 | 
			
		||||
                        translate, pageNumber,
 | 
			
		||||
                        itemsPerPage, session, baseDir, wfRequest, personCache,
 | 
			
		||||
                        nickname, domain, port, bookmarksJson,
 | 
			
		||||
                        'tlevents', allowDeletion,
 | 
			
		||||
                        httpPrefix, projectVersion, manuallyApproveFollowers,
 | 
			
		||||
                        minimal, YTReplacementDomain)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def htmlInboxDMs(defaultTimeline: str,
 | 
			
		||||
                 recentPostsCache: {}, maxRecentPosts: int,
 | 
			
		||||
                 translate: {}, pageNumber: int, itemsPerPage: int,
 | 
			
		||||
| 
						 | 
				
			
			@ -5238,7 +5270,7 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
 | 
			
		|||
                             httpPrefix, projectVersion, 'inbox',
 | 
			
		||||
                             YTReplacementDomain,
 | 
			
		||||
                             False, authorized, False, False, False)
 | 
			
		||||
    messageId = postJsonObject['id'].replace('/activity', '')
 | 
			
		||||
    messageId = removeIdEnding(postJsonObject['id'])
 | 
			
		||||
 | 
			
		||||
    # show the previous posts
 | 
			
		||||
    if isinstance(postJsonObject['object'], dict):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue