forked from indymedia/epicyon
unfollowing functions
parent
3813809958
commit
c55b5c9e15
|
@ -29,6 +29,7 @@ from inbox import inboxMessageHasParams
|
||||||
from inbox import runInboxQueue
|
from inbox import runInboxQueue
|
||||||
from inbox import savePostToInboxQueue
|
from inbox import savePostToInboxQueue
|
||||||
from follow import getFollowingFeed
|
from follow import getFollowingFeed
|
||||||
|
from follow import outboxUndoFollow
|
||||||
from auth import authorize
|
from auth import authorize
|
||||||
from auth import createPassword
|
from auth import createPassword
|
||||||
from threads import threadWithTrace
|
from threads import threadWithTrace
|
||||||
|
@ -200,6 +201,9 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.cachedWebfingers, \
|
self.server.cachedWebfingers, \
|
||||||
self.server.personCache, \
|
self.server.personCache, \
|
||||||
messageJson,self.server.debug)
|
messageJson,self.server.debug)
|
||||||
|
if self.server.debug:
|
||||||
|
print('DEBUG: handle any unfollow requests')
|
||||||
|
outboxUndoFollow(self.server.baseDir,messageJson,self.server.debug)
|
||||||
if self.server.debug:
|
if self.server.debug:
|
||||||
print('DEBUG: sending c2s post to named addresses')
|
print('DEBUG: sending c2s post to named addresses')
|
||||||
print('c2s sender: '+self.postToNickname+'@'+self.server.domain+':'+str(self.server.port))
|
print('c2s sender: '+self.postToNickname+'@'+self.server.domain+':'+str(self.server.port))
|
||||||
|
|
128
follow.py
128
follow.py
|
@ -62,7 +62,7 @@ def followerOfPerson(baseDir: str,nickname: str, domain: str, \
|
||||||
|
|
||||||
def unfollowPerson(baseDir: str,nickname: str, domain: str, \
|
def unfollowPerson(baseDir: str,nickname: str, domain: str, \
|
||||||
followNickname: str, followDomain: str, \
|
followNickname: str, followDomain: str, \
|
||||||
followFile='following.txt') -> None:
|
followFile='following.txt') -> bool:
|
||||||
"""Removes a person to the follow list
|
"""Removes a person to the follow list
|
||||||
"""
|
"""
|
||||||
handle=nickname.lower()+'@'+domain.lower()
|
handle=nickname.lower()+'@'+domain.lower()
|
||||||
|
@ -72,7 +72,8 @@ def unfollowPerson(baseDir: str,nickname: str, domain: str, \
|
||||||
if not os.path.isdir(baseDir+'/accounts/'+handle):
|
if not os.path.isdir(baseDir+'/accounts/'+handle):
|
||||||
os.mkdir(baseDir+'/accounts/'+handle)
|
os.mkdir(baseDir+'/accounts/'+handle)
|
||||||
filename=baseDir+'/accounts/'+handle+'/'+followFile
|
filename=baseDir+'/accounts/'+handle+'/'+followFile
|
||||||
if os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
|
return False
|
||||||
if handleToUnfollow not in open(filename).read():
|
if handleToUnfollow not in open(filename).read():
|
||||||
return
|
return
|
||||||
with open(filename, "r") as f:
|
with open(filename, "r") as f:
|
||||||
|
@ -432,6 +433,81 @@ def sendFollowRequestViaServer(session,fromNickname: str,password: str,
|
||||||
|
|
||||||
return newFollowJson
|
return newFollowJson
|
||||||
|
|
||||||
|
def sendUnfollowRequestViaServer(session,fromNickname: str,password: str,
|
||||||
|
fromDomain: str,fromPort: int, \
|
||||||
|
followNickname: str,followDomain: str,followPort: int, \
|
||||||
|
httpPrefix: str, \
|
||||||
|
cachedWebfingers: {},personCache: {}, \
|
||||||
|
debug: bool) -> {}:
|
||||||
|
"""Creates a unfollow request via c2s
|
||||||
|
"""
|
||||||
|
if not session:
|
||||||
|
print('WARN: No session for sendUnfollowRequestViaServer')
|
||||||
|
return 6
|
||||||
|
|
||||||
|
fromDomainFull=fromDomain
|
||||||
|
if fromPort!=80 and fromPort!=443:
|
||||||
|
fromDomainFull=fromDomain+':'+str(fromPort)
|
||||||
|
followDomainFull=followDomain
|
||||||
|
if followPort!=80 and followPort!=443:
|
||||||
|
followDomainFull=followDomain+':'+str(followPort)
|
||||||
|
|
||||||
|
followActor=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname
|
||||||
|
followedId=httpPrefix+'://'+followDomainFull+'/users/'+followNickname
|
||||||
|
|
||||||
|
unfollowJson = {
|
||||||
|
'type': 'Undo',
|
||||||
|
'actor': followActor,
|
||||||
|
'object': {
|
||||||
|
'type': 'Follow',
|
||||||
|
'actor': followActor,
|
||||||
|
'object': followedId,
|
||||||
|
'to': [followedId],
|
||||||
|
'cc': ['https://www.w3.org/ns/activitystreams#Public']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname
|
||||||
|
|
||||||
|
# lookup the inbox for the To handle
|
||||||
|
wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers)
|
||||||
|
if not wfRequest:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: announce webfinger failed for '+handle)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
postToBox='outbox'
|
||||||
|
|
||||||
|
# get the actor inbox for the To handle
|
||||||
|
inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition = \
|
||||||
|
getPersonBox(session,wfRequest,personCache,postToBox)
|
||||||
|
|
||||||
|
if not inboxUrl:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: No '+postToBox+' was found for '+handle)
|
||||||
|
return 3
|
||||||
|
if not fromPersonId:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: No actor was found for '+handle)
|
||||||
|
return 4
|
||||||
|
|
||||||
|
authHeader=createBasicAuthHeader(fromNickname,password)
|
||||||
|
|
||||||
|
headers = {'host': fromDomain, \
|
||||||
|
'Content-type': 'application/json', \
|
||||||
|
'Authorization': authHeader}
|
||||||
|
postResult = \
|
||||||
|
postJson(session,unfollowJson,[],inboxUrl,headers,"inbox:write")
|
||||||
|
#if not postResult:
|
||||||
|
# if debug:
|
||||||
|
# print('DEBUG: POST announce failed for c2s to '+inboxUrl)
|
||||||
|
# return 5
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: c2s POST unfollow success')
|
||||||
|
|
||||||
|
return unfollowJson
|
||||||
|
|
||||||
def getFollowersOfActor(baseDir :str,actor :str,debug: bool) -> {}:
|
def getFollowersOfActor(baseDir :str,actor :str,debug: bool) -> {}:
|
||||||
"""In a shared inbox if we receive a post we know who it's from
|
"""In a shared inbox if we receive a post we know who it's from
|
||||||
and if it's addressed to followers then we need to get a list of those.
|
and if it's addressed to followers then we need to get a list of those.
|
||||||
|
@ -493,3 +569,51 @@ def getFollowersOfActor(baseDir :str,actor :str,debug: bool) -> {}:
|
||||||
print(ocapFilename)
|
print(ocapFilename)
|
||||||
recipientsDict[account]=None
|
recipientsDict[account]=None
|
||||||
return recipientsDict
|
return recipientsDict
|
||||||
|
|
||||||
|
def outboxUndoFollow(baseDir: str,messageJson: {},debug: bool) -> None:
|
||||||
|
"""When an unfollow request is received by the outbox from c2s
|
||||||
|
This removes the followed handle from the following.txt file
|
||||||
|
of the relevant account
|
||||||
|
"""
|
||||||
|
if not messageJson.get('type'):
|
||||||
|
return
|
||||||
|
if not messageJson['type']=='Undo':
|
||||||
|
return
|
||||||
|
if not messageJson.get('object'):
|
||||||
|
return
|
||||||
|
if not isinstance(messageJson['object'], dict):
|
||||||
|
return
|
||||||
|
if not messageJson['object'].get('type'):
|
||||||
|
return
|
||||||
|
if not messageJson['object']['type']=='Follow':
|
||||||
|
return
|
||||||
|
if not messageJson['object'].get('object'):
|
||||||
|
return
|
||||||
|
if not messageJson['object'].get('actor'):
|
||||||
|
return
|
||||||
|
if not isinstance(messageJson['object']['object'], str):
|
||||||
|
return
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: undo follow arrived in outbox')
|
||||||
|
|
||||||
|
nicknameFollower=getNicknameFromActor(messageJson['object']['actor'])
|
||||||
|
domainFollower,portFollower=getDomainFromActor(messageJson['object']['actor'])
|
||||||
|
domainFollowerFull=domainFollower
|
||||||
|
if portFollower:
|
||||||
|
if portFollower!=80 and portFollower!=443:
|
||||||
|
domainFollowerFull=domainFollower+':'+str(portFollower)
|
||||||
|
|
||||||
|
nicknameFollowing=getNicknameFromActor(messageJson['object']['object'])
|
||||||
|
domainFollowing,portFollowing=getDomainFromActor(messageJson['object']['object'])
|
||||||
|
domainFollowingFull=domainFollowing
|
||||||
|
if portFollowing:
|
||||||
|
if portFollowing!=80 and portFollowing!=443:
|
||||||
|
domainFollowingFull=domainFollowing+':'+str(portFollowing)
|
||||||
|
|
||||||
|
if unfollowPerson(baseDir,nicknameFollower,domainFollowerFull, \
|
||||||
|
nicknameFollowing,domainFollowingFull):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: '+nicknameFollower+' unfollowed '+nicknameFollowing+'@'+domainFollowingFull)
|
||||||
|
else:
|
||||||
|
if debug:
|
||||||
|
print('WARN: '+nicknameFollower+' could not unfollow '+nicknameFollowing+'@'+domainFollowingFull)
|
||||||
|
|
91
inbox.py
91
inbox.py
|
@ -379,6 +379,82 @@ def inboxPostRecipients(baseDir :str,postJsonObject :{},httpPrefix :str,domain :
|
||||||
|
|
||||||
return recipientsDict,recipientsDictFollowers
|
return recipientsDict,recipientsDictFollowers
|
||||||
|
|
||||||
|
def receiveUndoFollow(session,baseDir: str,httpPrefix: str, \
|
||||||
|
port: int,messageJson: {},debug : bool) -> bool:
|
||||||
|
if not messageJson['object'].get('actor'):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: follow request has no actor within object')
|
||||||
|
return False
|
||||||
|
if '/users/' not in messageJson['object']['actor']:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: "users" missing from actor within object')
|
||||||
|
return False
|
||||||
|
if messageJson['object']['actor'] != messageJson['actor']:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: actors do not match')
|
||||||
|
return False
|
||||||
|
|
||||||
|
nicknameFollower=getNicknameFromActor(messageJson['object']['actor'])
|
||||||
|
domainFollower,portFollower=getDomainFromActor(messageJson['object']['actor'])
|
||||||
|
domainFollowerFull=domainFollower
|
||||||
|
if portFollower:
|
||||||
|
if portFollower!=80 and portFollower!=443:
|
||||||
|
domainFollowerFull=domainFollower+':'+str(portFollower)
|
||||||
|
|
||||||
|
nicknameFollowing=getNicknameFromActor(messageJson['object']['object'])
|
||||||
|
domainFollowing,portFollowing=getDomainFromActor(messageJson['object']['object'])
|
||||||
|
domainFollowingFull=domainFollowing
|
||||||
|
if portFollowing:
|
||||||
|
if portFollowing!=80 and portFollowing!=443:
|
||||||
|
domainFollowingFull=domainFollowing+':'+str(portFollowing)
|
||||||
|
|
||||||
|
unfollowerOfPerson(baseDir,nicknameFollower,domainFollowerFull, \
|
||||||
|
nicknameFollowing,domainFollowingFull,federationList,debug)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def receiveUndo(session,baseDir: str,httpPrefix: str, \
|
||||||
|
port: int,sendThreads: [],postLog: [], \
|
||||||
|
cachedWebfingers: {},personCache: {}, \
|
||||||
|
messageJson: {},federationList: [], \
|
||||||
|
debug : bool, \
|
||||||
|
acceptedCaps=["inbox:write","objects:read"]) -> bool:
|
||||||
|
"""Receives an undo request within the POST section of HTTPServer
|
||||||
|
"""
|
||||||
|
if not messageJson['type'].startswith('Undo'):
|
||||||
|
return False
|
||||||
|
if not messageJson.get('actor'):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: follow request has no actor')
|
||||||
|
return False
|
||||||
|
if '/users/' not in messageJson['actor']:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: "users" missing from actor')
|
||||||
|
return False
|
||||||
|
if not messageJson.get('object'):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: '+messageJson['type']+' has no object')
|
||||||
|
return False
|
||||||
|
if not isinstance(messageJson['object'], dict):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: '+messageJson['type']+' object is not a dict')
|
||||||
|
return False
|
||||||
|
if not messageJson['object'].get('type'):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: '+messageJson['type']+' has no object type')
|
||||||
|
return False
|
||||||
|
if not messageJson['object'].get('object'):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: '+messageJson['type']+' has no object within object')
|
||||||
|
return False
|
||||||
|
if not isinstance(messageJson['object']['object'], str):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: '+messageJson['type']+' object within object is not a string')
|
||||||
|
return False
|
||||||
|
if messageJson['object']['type']=='Follow':
|
||||||
|
return receiveUndoFollow(session,baseDir,httpPrefix, \
|
||||||
|
port,messageJson,debug)
|
||||||
|
return False
|
||||||
|
|
||||||
def receiveUpdate(session,baseDir: str, \
|
def receiveUpdate(session,baseDir: str, \
|
||||||
httpPrefix: str,domain :str,port: int, \
|
httpPrefix: str,domain :str,port: int, \
|
||||||
sendThreads: [],postLog: [],cachedWebfingers: {}, \
|
sendThreads: [],postLog: [],cachedWebfingers: {}, \
|
||||||
|
@ -953,6 +1029,21 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [], \
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: Signature check success')
|
print('DEBUG: Signature check success')
|
||||||
|
|
||||||
|
if receiveUndo(session, \
|
||||||
|
baseDir,httpPrefix,port, \
|
||||||
|
sendThreads,postLog, \
|
||||||
|
cachedWebfingers,
|
||||||
|
personCache,
|
||||||
|
queueJson['post'], \
|
||||||
|
federationList, \
|
||||||
|
debug, \
|
||||||
|
acceptedCaps=["inbox:write","objects:read"]):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: Undo accepted from '+keyId)
|
||||||
|
os.remove(queueFilename)
|
||||||
|
queue.pop(0)
|
||||||
|
continue
|
||||||
|
|
||||||
if receiveFollowRequest(session, \
|
if receiveFollowRequest(session, \
|
||||||
baseDir,httpPrefix,port, \
|
baseDir,httpPrefix,port, \
|
||||||
sendThreads,postLog, \
|
sendThreads,postLog, \
|
||||||
|
|
Loading…
Reference in New Issue