kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
ea02b82f39
commit
74ebbc428b
|
@ -250,16 +250,14 @@ def follower_collection(domain, collection):
|
|||
if not User.get_by_id(domain):
|
||||
return f'User {domain} not found', 404
|
||||
|
||||
# this query is duplicated in pages.followers_or_following()
|
||||
logger.info(f"Counting {domain}'s {collection}")
|
||||
followers, before, after = common.fetch_followers(domain, collection)
|
||||
|
||||
domain_prop = Follower.dest if collection == 'followers' else Follower.src
|
||||
query = Follower.query(
|
||||
Follower.status == 'active',
|
||||
domain_prop == domain,
|
||||
)
|
||||
count = query.count()
|
||||
followers, before, after = common.fetch_page(query, Follower)
|
||||
|
||||
ret = {
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
'summary': f"{domain}'s {collection}",
|
||||
|
|
28
common.py
28
common.py
|
@ -22,7 +22,7 @@ from oauth_dropins.webutil.util import json_dumps, json_loads
|
|||
import requests
|
||||
from werkzeug.exceptions import BadGateway
|
||||
|
||||
from models import Activity, User
|
||||
from models import Activity, Follower, User
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -589,6 +589,32 @@ def actor(domain, user=None):
|
|||
return actor
|
||||
|
||||
|
||||
def fetch_followers(domain, collection):
|
||||
"""Fetches a page of Follower entities.
|
||||
|
||||
Wraps :func:`common.fetch_page`. Paging uses the `before` and `after` query
|
||||
parameters, if available in the request.
|
||||
|
||||
Args:
|
||||
domain: str, user to fetch entities for
|
||||
collection, str, 'followers' or 'following'
|
||||
|
||||
Returns:
|
||||
(results, new_before, new_after) tuple with:
|
||||
results: list of Follower entities
|
||||
new_before, new_after: str query param values for `before` and `after`
|
||||
to fetch the previous and next pages, respectively
|
||||
"""
|
||||
assert collection in ('followers', 'following'), collection
|
||||
|
||||
domain_prop = Follower.dest if collection == 'followers' else Follower.src
|
||||
query = Follower.query(
|
||||
Follower.status == 'active',
|
||||
domain_prop == domain,
|
||||
).order(-Follower.updated)
|
||||
return fetch_page(query, Follower)
|
||||
|
||||
|
||||
def fetch_page(query, model_class):
|
||||
"""Fetches a page of results from a datastore query.
|
||||
|
||||
|
|
10
pages.py
10
pages.py
|
@ -103,16 +103,10 @@ def user(domain):
|
|||
|
||||
@app.get(f'/user/<regex("{DOMAIN_RE}"):domain>/<any(followers,following):collection>')
|
||||
def followers_or_following(domain, collection):
|
||||
if not (user := User.get_by_id(domain)):
|
||||
if not (user := User.get_by_id(domain)): # user var is used in template
|
||||
return render_template('user_not_found.html', domain=domain), 404
|
||||
|
||||
# this query is duplicated in activitypub.followers_collection()
|
||||
domain_prop = Follower.dest if collection == 'followers' else Follower.src
|
||||
query = Follower.query(
|
||||
Follower.status == 'active',
|
||||
domain_prop == domain,
|
||||
).order(-Follower.updated)
|
||||
followers, before, after = common.fetch_page(query, Follower)
|
||||
followers, before, after = common.fetch_followers(domain, collection)
|
||||
|
||||
for f in followers:
|
||||
f.url = f.src if collection == 'followers' else f.dest
|
||||
|
|
|
@ -9,7 +9,7 @@ import requests
|
|||
|
||||
from .test_activitypub import ACTOR, FOLLOW, FOLLOW_WITH_ACTOR, FOLLOW_WITH_OBJECT
|
||||
from . import testutil
|
||||
from models import Follower
|
||||
from models import Follower, User
|
||||
|
||||
ACTOR_DECLARATION = {
|
||||
'$type': 'app.bsky.system.declRef',
|
||||
|
@ -49,7 +49,14 @@ class XrpcGraphTest(testutil.TestCase):
|
|||
query_string={'user': 'not a domain'})
|
||||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_getFollowers_no_user(self, mock_get):
|
||||
resp = self.client.get('/xrpc/app.bsky.graph.getFollowers',
|
||||
query_string={'user': 'no.com'})
|
||||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_getFollowers_empty(self, mock_get):
|
||||
User.get_or_create('foo.com')
|
||||
|
||||
resp = self.client.get('/xrpc/app.bsky.graph.getFollowers',
|
||||
query_string={'user': 'foo.com'})
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
@ -60,6 +67,8 @@ class XrpcGraphTest(testutil.TestCase):
|
|||
}, resp.json)
|
||||
|
||||
def test_getFollowers(self, mock_get):
|
||||
User.get_or_create('foo.com')
|
||||
|
||||
other_follow = copy.deepcopy(FOLLOW)
|
||||
other_follow['actor'] = {
|
||||
'url': 'http://other',
|
||||
|
@ -89,6 +98,8 @@ class XrpcGraphTest(testutil.TestCase):
|
|||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_getFollows_empty(self, mock_get):
|
||||
User.get_or_create('foo.com')
|
||||
|
||||
resp = self.client.get('/xrpc/app.bsky.graph.getFollows',
|
||||
query_string={'user': 'foo.com'})
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
@ -99,6 +110,8 @@ class XrpcGraphTest(testutil.TestCase):
|
|||
}, resp.json)
|
||||
|
||||
def test_getFollows(self, mock_get):
|
||||
User.get_or_create('foo.com')
|
||||
|
||||
other_follow = copy.deepcopy(FOLLOW)
|
||||
other_follow['object'] = {
|
||||
'url': 'http://other',
|
||||
|
|
|
@ -6,7 +6,8 @@ from granary import bluesky
|
|||
from oauth_dropins.webutil import util
|
||||
|
||||
from app import xrpc_server
|
||||
from models import Follower
|
||||
import common
|
||||
from models import Follower, User
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -24,12 +25,17 @@ def get_followers(query_prop, output_field, user=None, limit=50, before=None):
|
|||
# TODO: what is user?
|
||||
if not user or not re.match(util.DOMAIN_RE, user):
|
||||
raise ValueError(f'{user} is not a domain')
|
||||
elif not User.get_by_id(user):
|
||||
raise ValueError(f'Unknown user {user}')
|
||||
|
||||
followers = []
|
||||
for follower in Follower.query(query_prop == user).fetch(limit):
|
||||
collection = 'followers' if output_field == 'followers' else 'following'
|
||||
followers, before, after = common.fetch_followers(user, collection)
|
||||
|
||||
actors = []
|
||||
for follower in followers:
|
||||
actor = follower.to_as1()
|
||||
if actor:
|
||||
followers.append({
|
||||
actors.append({
|
||||
**bluesky.actor_to_ref(actor),
|
||||
'$type': 'app.bsky.graph.getFollowers#follower',
|
||||
'indexedAt': util.now().isoformat(),
|
||||
|
@ -37,7 +43,7 @@ def get_followers(query_prop, output_field, user=None, limit=50, before=None):
|
|||
|
||||
return {
|
||||
'subject': bluesky.actor_to_ref({'url': f'https://{user}/'}),
|
||||
output_field: followers,
|
||||
output_field: actors,
|
||||
'cursor': '',
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue