Unit test for following a group

merge-requests/30/head
Bob Mottram 2021-07-31 12:56:28 +01:00
parent 4efb5c9a30
commit d48aff4807
8 changed files with 205 additions and 99 deletions

View File

@ -17,7 +17,7 @@ from utils import domainPermitted
from utils import followPerson from utils import followPerson
from utils import hasObjectDict from utils import hasObjectDict
from utils import acctDir from utils import acctDir
from utils import hasGroupPath from utils import hasGroupType
def _createAcceptReject(baseDir: str, federationList: [], def _createAcceptReject(baseDir: str, federationList: [],
@ -162,7 +162,9 @@ def _acceptFollow(baseDir: str, domain: str, messageJson: {},
return return
# does the url path indicate that this is a group actor # does the url path indicate that this is a group actor
groupAccount = hasGroupPath(followedActor) groupAccount = hasGroupType(baseDir, followedActor, None)
if debug:
print('Accepted follow is a group: ' + str(groupAccount))
if followPerson(baseDir, if followPerson(baseDir,
nickname, acceptedDomainFull, nickname, acceptedDomainFull,

View File

@ -10,9 +10,11 @@ __module_group__ = "Core"
import os import os
import datetime import datetime
from session import urlExists from session import urlExists
from session import getJson
from utils import loadJson from utils import loadJson
from utils import saveJson from utils import saveJson
from utils import getFileCaseInsensitive from utils import getFileCaseInsensitive
from utils import getUserPaths
def _removePersonFromCache(baseDir: str, personUrl: str, def _removePersonFromCache(baseDir: str, personUrl: str,
@ -132,3 +134,52 @@ def getWebfingerFromCache(handle: str, cachedWebfingers: {}) -> {}:
if cachedWebfingers.get(handle): if cachedWebfingers.get(handle):
return cachedWebfingers[handle] return cachedWebfingers[handle]
return None return None
def getPersonPubKey(baseDir: str, session, personUrl: str,
personCache: {}, debug: bool,
projectVersion: str, httpPrefix: str,
domain: str, onionDomain: str) -> str:
if not personUrl:
return None
personUrl = personUrl.replace('#main-key', '')
usersPaths = getUserPaths()
for possibleUsersPath in usersPaths:
if personUrl.endswith(possibleUsersPath + 'inbox'):
if debug:
print('DEBUG: Obtaining public key for shared inbox')
personUrl = \
personUrl.replace(possibleUsersPath + 'inbox', '/inbox')
break
personJson = \
getPersonFromCache(baseDir, personUrl, personCache, True)
if not personJson:
if debug:
print('DEBUG: Obtaining public key for ' + personUrl)
personDomain = domain
if onionDomain:
if '.onion/' in personUrl:
personDomain = onionDomain
profileStr = 'https://www.w3.org/ns/activitystreams'
asHeader = {
'Accept': 'application/activity+json; profile="' + profileStr + '"'
}
personJson = \
getJson(session, personUrl, asHeader, None, debug,
projectVersion, httpPrefix, personDomain)
if not personJson:
return None
pubKey = None
if personJson.get('publicKey'):
if personJson['publicKey'].get('publicKeyPem'):
pubKey = personJson['publicKey']['publicKeyPem']
else:
if personJson.get('publicKeyPem'):
pubKey = personJson['publicKeyPem']
if not pubKey:
if debug:
print('DEBUG: Public key not found for ' + personUrl)
storePersonInCache(baseDir, personUrl, personJson, personCache, True)
return pubKey

View File

@ -92,7 +92,6 @@ from inbox import runInboxQueue
from inbox import runInboxQueueWatchdog from inbox import runInboxQueueWatchdog
from inbox import savePostToInboxQueue from inbox import savePostToInboxQueue
from inbox import populateReplies from inbox import populateReplies
from inbox import getPersonPubKey
from follow import isFollowingActor from follow import isFollowingActor
from follow import getFollowingFeed from follow import getFollowingFeed
from follow import sendFollowRequest from follow import sendFollowRequest
@ -273,7 +272,7 @@ from utils import isSuspended
from utils import dangerousMarkup from utils import dangerousMarkup
from utils import refreshNewswire from utils import refreshNewswire
from utils import isImageFile from utils import isImageFile
from utils import hasGroupPath from utils import hasGroupType
from manualapprove import manualDenyFollowRequest from manualapprove import manualDenyFollowRequest
from manualapprove import manualApproveFollowRequest from manualapprove import manualApproveFollowRequest
from announce import createAnnounce from announce import createAnnounce
@ -286,6 +285,7 @@ from media import processMetaData
from cache import checkForChangedActor from cache import checkForChangedActor
from cache import storePersonInCache from cache import storePersonInCache
from cache import getPersonFromCache from cache import getPersonFromCache
from cache import getPersonPubKey
from httpsig import verifyPostHeaders from httpsig import verifyPostHeaders
from theme import importTheme from theme import importTheme
from theme import exportTheme from theme import exportTheme
@ -2569,7 +2569,9 @@ class PubServer(BaseHTTPRequestHandler):
} }
pathUsersSection = path.split('/users/')[1] pathUsersSection = path.split('/users/')[1]
self.postToNickname = pathUsersSection.split('/')[0] self.postToNickname = pathUsersSection.split('/')[0]
groupAccount = hasGroupPath(followingActor) groupAccount = hasGroupType(self.server.baseDir,
followingActor,
self.server.personCache)
unfollowAccount(self.server.baseDir, self.postToNickname, unfollowAccount(self.server.baseDir, self.postToNickname,
self.server.domain, self.server.domain,
followingNickname, followingDomainFull, followingNickname, followingDomainFull,

View File

@ -28,13 +28,14 @@ from utils import saveJson
from utils import isAccountDir from utils import isAccountDir
from utils import getUserPaths from utils import getUserPaths
from utils import acctDir from utils import acctDir
from utils import hasGroupPath from utils import hasGroupType
from acceptreject import createAccept from acceptreject import createAccept
from acceptreject import createReject from acceptreject import createReject
from webfinger import webfingerHandle from webfinger import webfingerHandle
from auth import createBasicAuthHeader from auth import createBasicAuthHeader
from session import getJson from session import getJson
from session import postJson from session import postJson
from cache import getPersonPubKey
def createInitialLastSeen(baseDir: str, httpPrefix: str) -> None: def createInitialLastSeen(baseDir: str, httpPrefix: str) -> None:
@ -626,7 +627,7 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
cachedWebfingers: {}, personCache: {}, cachedWebfingers: {}, personCache: {},
messageJson: {}, federationList: [], messageJson: {}, federationList: [],
debug: bool, projectVersion: str, debug: bool, projectVersion: str,
maxFollowers: int) -> bool: maxFollowers: int, onionDomain: str) -> bool:
"""Receives a follow request within the POST section of HTTPServer """Receives a follow request within the POST section of HTTPServer
""" """
if not messageJson['type'].startswith('Follow'): if not messageJson['type'].startswith('Follow'):
@ -740,22 +741,34 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
else: else:
print('Follow request does not require approval') print('Follow request does not require approval')
# update the followers # update the followers
if os.path.isdir(baseDir + '/accounts/' + accountToBeFollowed = \
nicknameToFollow + '@' + domainToFollow): acctDir(baseDir, nicknameToFollow, domainToFollow)
followersFilename = \ if os.path.isdir(accountToBeFollowed):
baseDir + '/accounts/' + \ followersFilename = accountToBeFollowed + '/followers.txt'
nicknameToFollow + '@' + domainToFollow + '/followers.txt'
# for actors which don't follow the mastodon # for actors which don't follow the mastodon
# /users/ path convention store the full actor # /users/ path convention store the full actor
if '/users/' not in messageJson['actor']: if '/users/' not in messageJson['actor']:
approveHandle = messageJson['actor'] approveHandle = messageJson['actor']
# Get the actor for the follower and add it to the cache.
# Getting their public key has the same result
if debug:
print('Obtaining the following actor: ' + messageJson['actor'])
if not getPersonPubKey(baseDir, session, messageJson['actor'],
personCache, debug, projectVersion,
httpPrefix, domainToFollow, onionDomain):
if debug:
print('Unable to obtain following actor: ' +
messageJson['actor'])
print('Updating followers file: ' + print('Updating followers file: ' +
followersFilename + ' adding ' + approveHandle) followersFilename + ' adding ' + approveHandle)
if os.path.isfile(followersFilename): if os.path.isfile(followersFilename):
if approveHandle not in open(followersFilename).read(): if approveHandle not in open(followersFilename).read():
groupAccount = hasGroupPath(messageJson['object']) groupAccount = \
hasGroupType(baseDir, messageJson['object'],
personCache)
try: try:
with open(followersFilename, 'r+') as followersFile: with open(followersFilename, 'r+') as followersFile:
content = followersFile.read() content = followersFile.read()
@ -925,7 +938,7 @@ def sendFollowRequest(session, baseDir: str,
if followNickname: if followNickname:
followedId = followedActor followedId = followedActor
followHandle = followNickname + '@' + requestDomain followHandle = followNickname + '@' + requestDomain
groupAccount = hasGroupPath(followedActor) groupAccount = hasGroupType(baseDir, followedActor, personCache)
if groupAccount: if groupAccount:
followHandle = '!' + followHandle followHandle = '!' + followHandle
else: else:
@ -1435,7 +1448,7 @@ def outboxUndoFollow(baseDir: str, messageJson: {}, debug: bool) -> None:
getDomainFromActor(messageJson['object']['object']) getDomainFromActor(messageJson['object']['object'])
domainFollowingFull = getFullDomain(domainFollowing, portFollowing) domainFollowingFull = getFullDomain(domainFollowing, portFollowing)
groupAccount = hasGroupPath(messageJson['object']['object']) groupAccount = hasGroupType(baseDir, messageJson['object']['object'], None)
if unfollowAccount(baseDir, nicknameFollower, domainFollowerFull, if unfollowAccount(baseDir, nicknameFollower, domainFollowerFull,
nicknameFollowing, domainFollowingFull, nicknameFollowing, domainFollowingFull,
debug, groupAccount): debug, groupAccount):

View File

@ -45,19 +45,18 @@ from utils import loadJson
from utils import saveJson from utils import saveJson
from utils import updateLikesCollection from utils import updateLikesCollection
from utils import undoLikesCollectionEntry from utils import undoLikesCollectionEntry
from utils import hasGroupPath from utils import hasGroupType
from categories import getHashtagCategories from categories import getHashtagCategories
from categories import setHashtagCategory from categories import setHashtagCategory
from httpsig import verifyPostHeaders from httpsig import verifyPostHeaders
from session import createSession from session import createSession
from session import getJson
from follow import isFollowingActor from follow import isFollowingActor
from follow import receiveFollowRequest from follow import receiveFollowRequest
from follow import getFollowersOfActor from follow import getFollowersOfActor
from follow import unfollowerOfAccount from follow import unfollowerOfAccount
from pprint import pprint from pprint import pprint
from cache import getPersonFromCache
from cache import storePersonInCache from cache import storePersonInCache
from cache import getPersonPubKey
from acceptreject import receiveAcceptReject from acceptreject import receiveAcceptReject
from bookmarks import updateBookmarksCollection from bookmarks import updateBookmarksCollection
from bookmarks import undoBookmarksCollectionEntry from bookmarks import undoBookmarksCollectionEntry
@ -234,55 +233,6 @@ def validInboxFilenames(baseDir: str, nickname: str, domain: str,
return True return True
def getPersonPubKey(baseDir: str, session, personUrl: str,
personCache: {}, debug: bool,
projectVersion: str, httpPrefix: str,
domain: str, onionDomain: str) -> str:
if not personUrl:
return None
personUrl = personUrl.replace('#main-key', '')
usersPaths = getUserPaths()
for possibleUsersPath in usersPaths:
if personUrl.endswith(possibleUsersPath + 'inbox'):
if debug:
print('DEBUG: Obtaining public key for shared inbox')
personUrl = \
personUrl.replace(possibleUsersPath + 'inbox', '/inbox')
break
personJson = \
getPersonFromCache(baseDir, personUrl, personCache, True)
if not personJson:
if debug:
print('DEBUG: Obtaining public key for ' + personUrl)
personDomain = domain
if onionDomain:
if '.onion/' in personUrl:
personDomain = onionDomain
profileStr = 'https://www.w3.org/ns/activitystreams'
asHeader = {
'Accept': 'application/activity+json; profile="' + profileStr + '"'
}
personJson = \
getJson(session, personUrl, asHeader, None, debug,
projectVersion, httpPrefix, personDomain)
if not personJson:
return None
pubKey = None
if personJson.get('publicKey'):
if personJson['publicKey'].get('publicKeyPem'):
pubKey = personJson['publicKey']['publicKeyPem']
else:
if personJson.get('publicKeyPem'):
pubKey = personJson['publicKeyPem']
if not pubKey:
if debug:
print('DEBUG: Public key not found for ' + personUrl)
storePersonInCache(baseDir, personUrl, personJson, personCache, True)
return pubKey
def inboxMessageHasParams(messageJson: {}) -> bool: def inboxMessageHasParams(messageJson: {}) -> bool:
"""Checks whether an incoming message contains expected parameters """Checks whether an incoming message contains expected parameters
""" """
@ -676,7 +626,7 @@ def _receiveUndoFollow(session, baseDir: str, httpPrefix: str,
getDomainFromActor(messageJson['object']['object']) getDomainFromActor(messageJson['object']['object'])
domainFollowingFull = getFullDomain(domainFollowing, portFollowing) domainFollowingFull = getFullDomain(domainFollowing, portFollowing)
groupAccount = hasGroupPath(messageJson['object']['actor']) groupAccount = hasGroupType(baseDir, messageJson['object']['actor'], None)
if unfollowerOfAccount(baseDir, if unfollowerOfAccount(baseDir,
nicknameFollowing, domainFollowingFull, nicknameFollowing, domainFollowingFull,
nicknameFollower, domainFollowerFull, nicknameFollower, domainFollowerFull,
@ -3148,7 +3098,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
queueJson['post'], queueJson['post'],
federationList, federationList,
debug, projectVersion, debug, projectVersion,
maxFollowers): maxFollowers, onionDomain):
if os.path.isfile(queueFilename): if os.path.isfile(queueFilename):
os.remove(queueFilename) os.remove(queueFilename)
if len(queue) > 0: if len(queue) > 0:

View File

@ -12,7 +12,7 @@ from utils import isAccountDir
from utils import getNicknameFromActor from utils import getNicknameFromActor
from utils import getDomainFromActor from utils import getDomainFromActor
from utils import acctDir from utils import acctDir
from utils import hasGroupPath from utils import hasGroupType
from webfinger import webfingerHandle from webfinger import webfingerHandle
from blocking import isBlocked from blocking import isBlocked
from posts import getUserUrl from posts import getUserUrl
@ -103,7 +103,7 @@ def _updateMovedHandle(baseDir: str, nickname: str, domain: str,
if movedToPort: if movedToPort:
if movedToPort != 80 and movedToPort != 443: if movedToPort != 80 and movedToPort != 443:
movedToDomainFull = movedToDomain + ':' + str(movedToPort) movedToDomainFull = movedToDomain + ':' + str(movedToPort)
groupAccount = hasGroupPath(movedToUrl) groupAccount = hasGroupType(baseDir, movedToUrl, None)
if isBlocked(baseDir, nickname, domain, if isBlocked(baseDir, nickname, domain,
movedToNickname, movedToDomain): movedToNickname, movedToDomain):
# someone that you follow has moved to a blocked domain # someone that you follow has moved to a blocked domain

111
tests.py
View File

@ -39,6 +39,7 @@ from follow import clearFollowers
from follow import sendFollowRequestViaServer from follow import sendFollowRequestViaServer
from follow import sendUnfollowRequestViaServer from follow import sendUnfollowRequestViaServer
from siteactive import siteIsActive from siteactive import siteIsActive
from utils import isGroupActor
from utils import dateStringToSeconds from utils import dateStringToSeconds
from utils import dateSecondsToString from utils import dateSecondsToString
from utils import validPassword from utils import validPassword
@ -1261,6 +1262,7 @@ def testFollowBetweenServers():
assert 'bob@' + bobDomain in open(aliceDir + '/accounts/alice@' + assert 'bob@' + bobDomain in open(aliceDir + '/accounts/alice@' +
aliceDomain + aliceDomain +
'/followingCalendar.txt').read() '/followingCalendar.txt').read()
assert not isGroupActor(aliceDir, bobActor, alicePersonCache)
print('\n\n*********************************************************') print('\n\n*********************************************************')
print('Alice sends a message to Bob') print('Alice sends a message to Bob')
@ -1319,7 +1321,10 @@ def testGroupFollow():
print('Testing following of a group') print('Testing following of a group')
global testServerAliceRunning global testServerAliceRunning
global testServerGroupRunning
systemLanguage = 'en'
testServerAliceRunning = False testServerAliceRunning = False
testServerGroupRunning = False
# systemLanguage = 'en' # systemLanguage = 'en'
httpPrefix = 'http' httpPrefix = 'http'
@ -1399,17 +1404,18 @@ def testGroupFollow():
print('Alice sends a follow request to the test group') print('Alice sends a follow request to the test group')
os.chdir(aliceDir) os.chdir(aliceDir)
sessionAlice = createSession(proxyType) sessionAlice = createSession(proxyType)
# inReplyTo = None inReplyTo = None
# inReplyToAtomUri = None inReplyToAtomUri = None
# subject = None subject = None
alicePostLog = [] alicePostLog = []
# followersOnly = False followersOnly = False
# saveToFile = True saveToFile = True
clientToServer = False clientToServer = False
# ccUrl = None ccUrl = None
alicePersonCache = {} alicePersonCache = {}
aliceCachedWebfingers = {} aliceCachedWebfingers = {}
alicePostLog = [] alicePostLog = []
# aliceActor = httpPrefix + '://' + aliceAddress + '/users/alice'
testgroupActor = httpPrefix + '://' + testgroupAddress + '/users/testgroup' testgroupActor = httpPrefix + '://' + testgroupAddress + '/users/testgroup'
sendResult = \ sendResult = \
sendFollowRequest(sessionAlice, aliceDir, sendFollowRequest(sessionAlice, aliceDir,
@ -1422,32 +1428,88 @@ def testGroupFollow():
True, __version__) True, __version__)
print('sendResult: ' + str(sendResult)) print('sendResult: ' + str(sendResult))
aliceFollowingFilename = \
aliceDir + '/accounts/alice@' + aliceDomain + '/following.txt'
aliceFollowingCalendarFilename = \
aliceDir + '/accounts/alice@' + aliceDomain + \
'/followingCalendar.txt'
testgroupFollowersFilename = \
testgroupDir + '/accounts/testgroup@' + testgroupDomain + \
'/followers.txt'
for t in range(16): for t in range(16):
if os.path.isfile(testgroupDir + '/accounts/testgroup@' + if os.path.isfile(testgroupFollowersFilename):
testgroupDomain + '/followers.txt'): if os.path.isfile(aliceFollowingFilename):
if os.path.isfile(aliceDir + '/accounts/alice@' + if os.path.isfile(aliceFollowingCalendarFilename):
aliceDomain + '/following.txt'):
if os.path.isfile(aliceDir + '/accounts/alice@' +
aliceDomain + '/followingCalendar.txt'):
break break
time.sleep(1) time.sleep(1)
assert validInbox(testgroupDir, 'testgroup', testgroupDomain) assert validInbox(testgroupDir, 'testgroup', testgroupDomain)
assert validInboxFilenames(testgroupDir, 'testgroup', testgroupDomain, assert validInboxFilenames(testgroupDir, 'testgroup', testgroupDomain,
aliceDomain, alicePort) aliceDomain, alicePort)
assert 'alice@' + aliceDomain in open(testgroupDir + assert 'alice@' + aliceDomain in open(testgroupFollowersFilename).read()
'/accounts/testgroup@' +
testgroupDomain + testgroupWebfingerFilename = \
'/followers.txt').read() testgroupDir + '/wfendpoints/testgroup@' + \
assert 'testgroup@' + testgroupDomain in open(aliceDir + testgroupDomain + ':' + str(testgroupPort) + '.json'
'/accounts/alice@' + assert os.path.isfile(testgroupWebfingerFilename)
aliceDomain + assert 'group:testgroup@' in open(testgroupWebfingerFilename).read()
'/following.txt').read() print('group: exists within the webfinger endpoint for testgroup')
testgroupHandle = 'testgroup@' + testgroupDomain testgroupHandle = 'testgroup@' + testgroupDomain
assert testgroupHandle in open(aliceDir + followingStr = ''
'/accounts/alice@' + with open(aliceFollowingFilename, 'r') as fp:
aliceDomain + followingStr = fp.read()
'/followingCalendar.txt').read() print('Alice following.txt:\n\n' + followingStr)
if '!testgroup' not in followingStr:
print('Alice following.txt does not contain !testgroup@' +
testgroupDomain + ':' + str(testgroupPort))
assert isGroupActor(aliceDir, testgroupActor, alicePersonCache)
assert '!testgroup' in followingStr
assert testgroupHandle in open(aliceFollowingFilename).read()
assert testgroupHandle in open(aliceFollowingCalendarFilename).read()
print('Alice follows the test group')
print('\n\n*********************************************************')
print('Alice posts to the test group')
alicePostLog = []
alicePersonCache = {}
aliceCachedWebfingers = {}
alicePostLog = []
isArticle = False
city = 'London, England'
sendResult = \
sendPost(__version__,
sessionAlice, aliceDir, 'alice', aliceDomain, alicePort,
'testgroup', testgroupDomain, testgroupPort, ccUrl,
httpPrefix, "Alice group message", followersOnly,
saveToFile, clientToServer, True,
None, None, None, city, federationList,
aliceSendThreads, alicePostLog, aliceCachedWebfingers,
alicePersonCache, isArticle, systemLanguage, inReplyTo,
inReplyToAtomUri, subject)
print('sendResult: ' + str(sendResult))
queuePath = \
testgroupDir + '/accounts/testgroup@' + testgroupDomain + '/queue'
inboxPath = \
testgroupDir + '/accounts/testgroup@' + testgroupDomain + '/inbox'
aliceMessageArrived = False
startPosts = len([name for name in os.listdir(inboxPath)
if os.path.isfile(os.path.join(inboxPath, name))])
for i in range(20):
time.sleep(1)
if os.path.isdir(inboxPath):
currPosts = \
len([name for name in os.listdir(inboxPath)
if os.path.isfile(os.path.join(inboxPath, name))])
if currPosts > startPosts:
aliceMessageArrived = True
print('Alice post sent to test group!')
break
assert aliceMessageArrived is True
print('Post from Alice to test group succeeded')
# stop the servers # stop the servers
thrAlice.kill() thrAlice.kill()
@ -1465,6 +1527,7 @@ def testGroupFollow():
os.chdir(baseDir) os.chdir(baseDir)
shutil.rmtree(baseDir + '/.tests') shutil.rmtree(baseDir + '/.tests')
print('Testing following of a group is complete')
def _testFollowersOfPerson(): def _testFollowersOfPerson():

View File

@ -1081,6 +1081,9 @@ def followPerson(baseDir: str, nickname: str, domain: str,
else: else:
handleToFollow = followNickname + '@' + followDomain handleToFollow = followNickname + '@' + followDomain
if groupAccount:
handleToFollow = '!' + handleToFollow
# was this person previously unfollowed? # was this person previously unfollowed?
unfollowedFilename = baseDir + '/accounts/' + handle + '/unfollowed.txt' unfollowedFilename = baseDir + '/accounts/' + handle + '/unfollowed.txt'
if os.path.isfile(unfollowedFilename): if os.path.isfile(unfollowedFilename):
@ -1098,6 +1101,8 @@ def followPerson(baseDir: str, nickname: str, domain: str,
if not os.path.isdir(baseDir + '/accounts'): if not os.path.isdir(baseDir + '/accounts'):
os.mkdir(baseDir + '/accounts') os.mkdir(baseDir + '/accounts')
handleToFollow = followNickname + '@' + followDomain handleToFollow = followNickname + '@' + followDomain
if groupAccount:
handleToFollow = '!' + handleToFollow
filename = baseDir + '/accounts/' + handle + '/' + followFile filename = baseDir + '/accounts/' + handle + '/' + followFile
if os.path.isfile(filename): if os.path.isfile(filename):
if handleToFollow in open(filename).read(): if handleToFollow in open(filename).read():
@ -2682,13 +2687,33 @@ def dateSecondsToString(dateSec: int) -> str:
return thisDate.strftime("%Y-%m-%dT%H:%M:%SZ") return thisDate.strftime("%Y-%m-%dT%H:%M:%SZ")
def hasGroupPath(actor: str) -> bool: def hasGroupType(baseDir: str, actor: str, personCache: {}) -> bool:
"""Does the given actor url contain a path which indicates """Does the given actor url have a group type?
that it belongs to a group?
e.g. https://lemmy/c/groupname
""" """
# does the actor path clearly indicate that this is a group?
# eg. https://lemmy/c/groupname
groupPaths = getGroupPaths() groupPaths = getGroupPaths()
for grpPath in groupPaths: for grpPath in groupPaths:
if grpPath in actor: if grpPath in actor:
return True return True
# is there a cached actor which can be examined for Group type?
return isGroupActor(baseDir, actor, personCache)
def isGroupActor(baseDir: str, actor: str, personCache: {}) -> bool:
"""Is the given actor a group?
"""
if personCache:
if personCache.get(actor):
if personCache[actor].get('actor'):
if personCache[actor]['actor'].get('type'):
if personCache[actor]['actor']['type'] == 'Group':
return True
return False
cachedActorFilename = \
baseDir + '/cache/actors/' + (actor.replace('/', '#')) + '.json'
if not os.path.isfile(cachedActorFilename):
return False
if '"type": "Group"' in open(cachedActorFilename).read():
return True
return False return False