From cdba45bd68624cd3e1ea81cc5275561d99e75243 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 29 Jul 2019 21:36:26 +0100 Subject: [PATCH] Unfollowing from web interface --- daemon.py | 61 ++++++++++++++++++++++++++++++++++++++++++++++--- follow.py | 1 + webinterface.py | 30 ++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/daemon.py b/daemon.py index 771008b0e..267c099e2 100644 --- a/daemon.py +++ b/daemon.py @@ -66,6 +66,7 @@ from webinterface import htmlLogin from webinterface import htmlGetLoginCredentials from webinterface import htmlNewPost from webinterface import htmlFollowConfirm +from webinterface import htmlUnfollowConfirm from shares import getSharesFeedForPerson from shares import outboxShareUpload from shares import outboxUndoShareUpload @@ -594,6 +595,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.GETbusy=False return + # follow a person from the web interface by selecting Follow on the dropdown if '/users/' in self.path: if '?follow=' in self.path: followStr=self.path.split('?follow=')[1] @@ -601,6 +603,7 @@ class PubServer(BaseHTTPRequestHandler): if ';' in followStr: followActor=followStr.split(';')[0] followProfileUrl=followStr.split(';')[1] + # show the confirm follow screen self._set_headers('text/html',cookie) self.wfile.write(htmlFollowConfirm(self.server.baseDir,originPathStr,followActor,followProfileUrl).encode()) self.server.GETbusy=False @@ -608,6 +611,23 @@ class PubServer(BaseHTTPRequestHandler): self._redirect_headers(originPathStr,cookie) self.server.GETbusy=False return + + # Unfollow a person from the web interface by selecting Unfollow on the dropdown + if '/users/' in self.path: + if '?unfollow=' in self.path: + followStr=self.path.split('?unfollow=')[1] + originPathStr=self.path.split('?unfollow=')[0] + if ';' in followStr: + followActor=followStr.split(';')[0] + followProfileUrl=followStr.split(';')[1] + # show the confirm follow screen + self._set_headers('text/html',cookie) + self.wfile.write(htmlUnfollowConfirm(self.server.baseDir,originPathStr,followActor,followProfileUrl).encode()) + self.server.GETbusy=False + return + self._redirect_headers(originPathStr,cookie) + self.server.GETbusy=False + return if '/users/' in self.path and \ (self.path.endswith('/newpost') or \ @@ -1440,7 +1460,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.POSTbusy=False # decision to follow in the web interface is confirmed - if authorized and self.path.endswith('/followconfirm'): + if authorized and self.path.endswith('/followconfirm'): originPathStr=self.path.split('/followconfirm')[0] followerNickname=getNicknameFromActor(originPathStr) length = int(self.headers['Content-length']) @@ -1473,8 +1493,43 @@ class PubServer(BaseHTTPRequestHandler): self.server.cachedWebfingers, \ self.server.personCache, \ self.server.debug) - else: - print('Follow no') + self._redirect_headers(originPathStr,cookie) + self.server.POSTbusy=False + return + + # decision to unfollow in the web interface is confirmed + if authorized and self.path.endswith('/unfollowconfirm'): + originPathStr=self.path.split('/unfollowconfirm')[0] + followerNickname=getNicknameFromActor(originPathStr) + length = int(self.headers['Content-length']) + followConfirmParams=self.rfile.read(length).decode('utf-8') + if '&submitYes=' in followConfirmParams: + followingActor=followConfirmParams.replace('%3A',':').replace('%2F','/').split('actor=')[1] + if '&' in followingActor: + followingActor=followingActor.split('&')[0] + followingNickname=getNicknameFromActor(followingActor) + followingDomain,followingPort=getDomainFromActor(followingActor) + if followerNickname==followingNickname and \ + followingDomain==self.server.domain and \ + followingPort==self.server.port: + if self.server.debug: + print('You cannot unfollow yourself!') + else: + if self.server.debug: + print(followerNickname+' stops following '+followingActor) + followActor=self.server.httpPrefix+'://'+self.server.domainFull+'/users/'+followerNickname + unfollowJson = { + 'type': 'Undo', + 'actor': followActor, + 'object': { + 'type': 'Follow', + 'actor': followActor, + 'object': followingActor, + 'to': [followingActor], + 'cc': ['https://www.w3.org/ns/activitystreams#Public'] + } + } + self._postToOutbox(unfollowJson) self._redirect_headers(originPathStr,cookie) self.server.POSTbusy=False return diff --git a/follow.py b/follow.py index 3ed0d2b8d..d6fb3636c 100644 --- a/follow.py +++ b/follow.py @@ -706,6 +706,7 @@ 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 + TODO the unfollow should also be sent to the previously followed account """ if not messageJson.get('type'): return diff --git a/webinterface.py b/webinterface.py index 00af7fad1..6fef56053 100644 --- a/webinterface.py +++ b/webinterface.py @@ -591,3 +591,33 @@ def htmlFollowConfirm(baseDir: str,originPathStr: str,followActor: str,followPro followStr+='' followStr+=htmlFooter() return followStr + +def htmlUnfollowConfirm(baseDir: str,originPathStr: str,followActor: str,followProfileUrl: str) -> str: + """Asks to confirm unfollowing an actor + """ + followDomain,port=getDomainFromActor(followActor) + + if os.path.isfile(baseDir+'/img/follow-background.png'): + if not os.path.isfile(baseDir+'/accounts/follow-background.png'): + copyfile(baseDir+'/img/follow-background.png',baseDir+'/accounts/follow-background.png') + + with open(baseDir+'/epicyon-follow.css', 'r') as cssFile: + profileStyle = cssFile.read() + followStr=htmlHeader(profileStyle) + followStr+='
' + followStr+='
' + followStr+='
' + followStr+=' ' + followStr+=' ' + followStr+='

Stop following '+getNicknameFromActor(followActor)+'@'+followDomain+' ?

' + followStr+= \ + '
' \ + ' ' \ + ' ' \ + ' ' \ + '
' + followStr+='
' + followStr+='
' + followStr+='
' + followStr+=htmlFooter() + return followStr