Following and followers feeds

master
Bob Mottram 2019-06-29 21:21:37 +01:00
parent 1bd7a40892
commit 0765d21b24
3 changed files with 147 additions and 7 deletions

View File

@ -19,6 +19,7 @@ from person import personLookup
from person import personKeyLookup from person import personKeyLookup
from person import personOutboxJson from person import personOutboxJson
from inbox import inboxPermittedMessage from inbox import inboxPermittedMessage
from follow import getFollowingFeed
import os import os
import sys import sys
@ -34,6 +35,9 @@ maxMessageLength=5000
# maximum number of posts to list in outbox feed # maximum number of posts to list in outbox feed
maxPostsInFeed=20 maxPostsInFeed=20
# number of follows/followers per page
followsPerPage=2
# Whether to use https # Whether to use https
useHttps=True useHttps=True
@ -49,6 +53,7 @@ def readFollowList(filename: str):
username,domain = parseHandle(u) username,domain = parseHandle(u)
if username: if username:
followlist.append(username+'@'+domain) followlist.append(username+'@'+domain)
followUsers.close()
return followlist return followlist
class PubServer(BaseHTTPRequestHandler): class PubServer(BaseHTTPRequestHandler):
@ -113,6 +118,18 @@ class PubServer(BaseHTTPRequestHandler):
self.wfile.write(json.dumps(outboxFeed).encode('utf-8')) self.wfile.write(json.dumps(outboxFeed).encode('utf-8'))
self.GETbusy=False self.GETbusy=False
return return
following=getFollowingFeed(thisDomain,self.path,useHttps,followsPerPage)
if following:
self._set_headers('application/json')
self.wfile.write(json.dumps(following).encode('utf-8'))
self.GETbusy=False
return
followers=getFollowingFeed(thisDomain,self.path,useHttps,followsPerPage,'followers')
if followers:
self._set_headers('application/json')
self.wfile.write(json.dumps(followers).encode('utf-8'))
self.GETbusy=False
return
# look up a person # look up a person
getPerson = personLookup(thisDomain,self.path) getPerson = personLookup(thisDomain,self.path)
if getPerson: if getPerson:
@ -127,12 +144,12 @@ class PubServer(BaseHTTPRequestHandler):
self.GETbusy=False self.GETbusy=False
return return
# check that a json file was requested # check that a json file was requested
baseDir=os.getcwd()
if not self.path.endswith('.json'): if not self.path.endswith('.json'):
self._404() self._404()
self.GETbusy=False self.GETbusy=False
return return
# check that the file exists # check that the file exists
baseDir=os.getcwd()
filename=baseDir+self.path filename=baseDir+self.path
if os.path.isfile(filename): if os.path.isfile(filename):
self._set_headers('application/json') self._set_headers('application/json')

View File

@ -25,6 +25,7 @@ from httpsig import testHttpsig
from daemon import runDaemon from daemon import runDaemon
import socket import socket
from follow import clearFollows from follow import clearFollows
from follow import clearFollowers
from follow import followPerson from follow import followPerson
from follow import followerOfPerson from follow import followerOfPerson
from follow import unfollowPerson from follow import unfollowPerson
@ -43,14 +44,25 @@ clearFollows(username,domain)
followPerson(username,domain,'badger','wild.com') followPerson(username,domain,'badger','wild.com')
followPerson(username,domain,'squirrel','secret.com') followPerson(username,domain,'squirrel','secret.com')
followPerson(username,domain,'rodent','drainpipe.com') followPerson(username,domain,'rodent','drainpipe.com')
unfollowPerson(username,domain,'squirrel','secret.com') followPerson(username,domain,'batman','mesh.com')
sys.exit() followPerson(username,domain,'giraffe','trees.com')
asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} clearFollowers(username,domain)
followerOfPerson(username,domain,'badger','wild.com')
followerOfPerson(username,domain,'squirrel','secret.com')
followerOfPerson(username,domain,'rodent','drainpipe.com')
followerOfPerson(username,domain,'batman','mesh.com')
followerOfPerson(username,domain,'giraffe','trees.com')
#unfollowPerson(username,domain,'squirrel','secret.com')
#sys.exit()
#asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}
#userFollowing = getJson(session,"https://mastodon.social/users/Gargron/followers?page=true",asHeader,None) #userFollowing = getJson(session,"https://mastodon.social/users/Gargron/followers?page=true",asHeader,None)
userFollowing = getJson(session,"https://mastodon.social/users/Gargron/following?page=true",asHeader,None) #userFollowing = getJson(session,"https://mastodon.social/users/Gargron/following",asHeader,None)
pprint(userFollowing) #userFollowing = getJson(session,"https://mastodon.social/users/Gargron/following?page=1",asHeader,None)
sys.exit() #pprint(userFollowing)
#sys.exit()
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(username,domain,https,True) privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(username,domain,https,True)

111
follow.py
View File

@ -10,6 +10,7 @@ import json
from pprint import pprint from pprint import pprint
import os import os
import sys import sys
from person import validUsername
def followPerson(username: str, domain: str, followUsername: str, followDomain: str, followFile='following.txt') -> None: def followPerson(username: str, domain: str, followUsername: str, followDomain: str, followFile='following.txt') -> None:
"""Adds a person to the follow list """Adds a person to the follow list
@ -67,3 +68,113 @@ def clearFollows(username: str, domain: str,followFile='following.txt') -> None:
def clearFollowers(username: str, domain: str) -> None: def clearFollowers(username: str, domain: str) -> None:
clearFollows(username, domain,'followers.txt') clearFollows(username, domain,'followers.txt')
def getNoOfFollows(username: str,domain: str, followFile='following.txt') -> int:
handle=username.lower()+'@'+domain.lower()
baseDir=os.getcwd()
filename=baseDir+'/accounts/'+handle+'/'+followFile
if not os.path.isfile(filename):
return 0
ctr = 0
with open(filename, "r") as f:
lines = f.readlines()
for line in lines:
if '#' not in line:
if '@' in line and '.' in line and not line.startswith('http'):
ctr += 1
elif line.startswith('http') and '/users/' in line:
ctr += 1
return ctr
def getNoOfFollowers(username: str,domain: str) -> int:
return getNoOfFollows(username,domain,'followers.txt')
def getFollowingFeed(domain: str,path: str,https: bool,followsPerPage=12,followFile='following') -> {}:
if '/'+followFile not in path:
return None
# handle page numbers
headerOnly=True
pageNumber=None
if '?page=' in path:
pageNumber=path.split('?page=')[1]
if pageNumber=='true':
pageNumber=1
else:
try:
pageNumber=int(pageNumber)
except:
pass
path=path.split('?page=')[0]
headerOnly=False
if not path.endswith('/'+followFile):
return None
username=None
if path.startswith('/users/'):
username=path.replace('/users/','',1).replace('/'+followFile,'')
if path.startswith('/@'):
username=path.replace('/@','',1).replace('/'+followFile,'')
if not username:
return None
if not validUsername(username):
return None
prefix='https'
if not https:
prefix='http'
if headerOnly:
following = {
'@context': 'https://www.w3.org/ns/activitystreams',
'first': prefix+'://'+domain+'/users/'+username+'/'+followFile+'?page=1',
'id': prefix+'://'+domain+'/users/'+username+'/'+followFile,
'totalItems': getNoOfFollows(username,domain),
'type': 'OrderedCollection'}
return following
if not pageNumber:
pageNumber=1
nextPageNumber=int(pageNumber+1)
following = {
'@context': 'https://www.w3.org/ns/activitystreams',
'id': prefix+'://'+domain+'/users/'+username+'/'+followFile+'?page='+str(pageNumber),
'orderedItems': [],
'partOf': prefix+'://'+domain+'/users/'+username+'/'+followFile,
'totalItems': 0,
'type': 'OrderedCollectionPage'}
baseDir=os.getcwd()
handle=username.lower()+'@'+domain.lower()
filename=baseDir+'/accounts/'+handle+'/'+followFile+'.txt'
if not os.path.isfile(filename):
return following
currPage=1
pageCtr=0
totalCtr=0
with open(filename, "r") as f:
lines = f.readlines()
for line in lines:
if '#' not in line:
if '@' in line and '.' in line and not line.startswith('http'):
pageCtr += 1
totalCtr += 1
if currPage==pageNumber:
url = prefix + '://' + line.lower().replace('\n','').split('@')[1] + \
'/users/' + line.lower().replace('\n','').split('@')[0]
following['orderedItems'].append(url)
elif line.startswith('http') and '/users/' in line:
pageCtr += 1
totalCtr += 1
if currPage==pageNumber:
following['orderedItems'].append(line.lower().replace('\n',''))
if pageCtr>=followsPerPage:
pageCtr=0
currPage += 1
following['totalItems']=totalCtr
lastPage=int(totalCtr/followsPerPage)
if lastPage<1:
lastPage=1
if nextPageNumber>lastPage:
following['next']=prefix+'://'+domain+'/users/'+username+'/'+followFile+'?page='+str(lastPage)
return following