kopia lustrzana https://github.com/snarfed/bridgy-fed
move pages.fetch_objects to models
rodzic
48f89cebc0
commit
f8b7d0c283
108
models.py
108
models.py
|
@ -1087,6 +1087,110 @@ class Follower(ndb.Model):
|
||||||
return followers, before, after
|
return followers, before, after
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_objects(query, by=None, user=None):
|
||||||
|
"""Fetches a page of :class:`Object` entities from a datastore query.
|
||||||
|
|
||||||
|
Wraps :func:`fetch_page` and adds attributes to the returned
|
||||||
|
:class:`Object` entities for rendering in ``objects.html``.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
query (ndb.Query)
|
||||||
|
by (ndb.model.Property): either :attr:`Object.updated` or
|
||||||
|
:attr:`Object.created`
|
||||||
|
user (User): current user
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(list of Object, str, str) tuple:
|
||||||
|
(results, new ``before`` query param, new ``after`` query param)
|
||||||
|
to fetch the previous and next pages, respectively
|
||||||
|
"""
|
||||||
|
assert by is Object.updated or by is Object.created
|
||||||
|
objects, new_before, new_after = fetch_page(query, Object, by=by)
|
||||||
|
objects = [o for o in objects if not o.deleted]
|
||||||
|
|
||||||
|
# synthesize human-friendly content for objects
|
||||||
|
for i, obj in enumerate(objects):
|
||||||
|
if obj.deleted:
|
||||||
|
continue
|
||||||
|
|
||||||
|
obj_as1 = obj.as1
|
||||||
|
inner_obj = as1.get_object(obj_as1)
|
||||||
|
|
||||||
|
# synthesize text snippet
|
||||||
|
type = as1.object_type(obj_as1)
|
||||||
|
if type == 'post':
|
||||||
|
inner_type = inner_obj.get('objectType')
|
||||||
|
if inner_type:
|
||||||
|
type = inner_type
|
||||||
|
|
||||||
|
phrases = {
|
||||||
|
'article': 'posted',
|
||||||
|
'comment': 'replied',
|
||||||
|
'delete': 'deleted',
|
||||||
|
'follow': 'followed',
|
||||||
|
'invite': 'is invited to',
|
||||||
|
'issue': 'filed issue',
|
||||||
|
'like': 'liked',
|
||||||
|
'note': 'posted',
|
||||||
|
'post': 'posted',
|
||||||
|
'repost': 'reposted',
|
||||||
|
'rsvp-interested': 'is interested in',
|
||||||
|
'rsvp-maybe': 'might attend',
|
||||||
|
'rsvp-no': 'is not attending',
|
||||||
|
'rsvp-yes': 'is attending',
|
||||||
|
'share': 'reposted',
|
||||||
|
'stop-following': 'unfollowed',
|
||||||
|
'update': 'updated',
|
||||||
|
}
|
||||||
|
obj.phrase = phrases.get(type)
|
||||||
|
|
||||||
|
content = (inner_obj.get('content')
|
||||||
|
or inner_obj.get('displayName')
|
||||||
|
or inner_obj.get('summary'))
|
||||||
|
if content:
|
||||||
|
content = util.parse_html(content).get_text()
|
||||||
|
|
||||||
|
urls = as1.object_urls(inner_obj)
|
||||||
|
id = common.unwrap(inner_obj.get('id', ''))
|
||||||
|
url = urls[0] if urls else id
|
||||||
|
if (type == 'update' and
|
||||||
|
(obj.users and (user.is_web_url(id)
|
||||||
|
or id.strip('/') == obj.users[0].id())
|
||||||
|
or obj.domains and id.strip('/') == f'https://{obj.domains[0]}')):
|
||||||
|
obj.phrase = 'updated'
|
||||||
|
obj_as1.update({
|
||||||
|
'content': 'their profile',
|
||||||
|
'url': id,
|
||||||
|
})
|
||||||
|
elif url:
|
||||||
|
# heuristics for sniffing Mastodon and similar fediverse URLs and
|
||||||
|
# converting them to more friendly @-names
|
||||||
|
# TODO: standardize this into granary.as2 somewhere?
|
||||||
|
if not content:
|
||||||
|
fedi_url = re.match(
|
||||||
|
r'https://[^/]+/(@|users/)([^/@]+)(@[^/@]+)?(/(?:statuses/)?[0-9]+)?', url)
|
||||||
|
if fedi_url:
|
||||||
|
content = '@' + fedi_url.group(2)
|
||||||
|
if fedi_url.group(4):
|
||||||
|
content += "'s post"
|
||||||
|
content = common.pretty_link(url, text=content)
|
||||||
|
|
||||||
|
obj.content = (obj_as1.get('content')
|
||||||
|
or obj_as1.get('displayName')
|
||||||
|
or obj_as1.get('summary'))
|
||||||
|
obj.url = util.get_first(obj_as1, 'url')
|
||||||
|
|
||||||
|
if type in ('like', 'follow', 'repost', 'share') or not obj.content:
|
||||||
|
if obj.url:
|
||||||
|
obj.phrase = common.pretty_link(obj.url, text=obj.phrase,
|
||||||
|
attrs={'class': 'u-url'})
|
||||||
|
if content:
|
||||||
|
obj.content = content
|
||||||
|
obj.url = url
|
||||||
|
|
||||||
|
return objects, new_before, new_after
|
||||||
|
|
||||||
|
|
||||||
def fetch_page(query, model_class, by=None):
|
def fetch_page(query, model_class, by=None):
|
||||||
"""Fetches a page of results from a datastore query.
|
"""Fetches a page of results from a datastore query.
|
||||||
|
|
||||||
|
@ -1099,8 +1203,8 @@ def fetch_page(query, model_class, by=None):
|
||||||
Args:
|
Args:
|
||||||
query (google.cloud.ndb.query.Query)
|
query (google.cloud.ndb.query.Query)
|
||||||
model_class (class)
|
model_class (class)
|
||||||
by (ndb.model.Property): paging property, eg :attr:`models.Object.updated`
|
by (ndb.model.Property): paging property, eg :attr:`Object.updated`
|
||||||
or :attr:`models.Object.created`
|
or :attr:`Object.created`
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(list of Object or Follower, str, str) tuple: (results, new_before,
|
(list of Object or Follower, str, str) tuple: (results, new_before,
|
||||||
|
|
106
pages.py
106
pages.py
|
@ -24,7 +24,7 @@ from activitypub import ActivityPub
|
||||||
import common
|
import common
|
||||||
from common import DOMAIN_RE
|
from common import DOMAIN_RE
|
||||||
from flask_app import app, cache
|
from flask_app import app, cache
|
||||||
from models import fetch_page, Follower, Object, PAGE_SIZE, PROTOCOLS
|
from models import fetch_objects, fetch_page, Follower, Object, PAGE_SIZE, PROTOCOLS
|
||||||
from protocol import Protocol
|
from protocol import Protocol
|
||||||
|
|
||||||
# precompute this because we get a ton of requests for non-existing users
|
# precompute this because we get a ton of requests for non-existing users
|
||||||
|
@ -291,110 +291,6 @@ def bridge_user():
|
||||||
return render_template('bridge_user.html')
|
return render_template('bridge_user.html')
|
||||||
|
|
||||||
|
|
||||||
def fetch_objects(query, by=None, user=None):
|
|
||||||
"""Fetches a page of :class:`models.Object` entities from a datastore query.
|
|
||||||
|
|
||||||
Wraps :func:`models.fetch_page` and adds attributes to the returned
|
|
||||||
:class:`models.Object` entities for rendering in ``objects.html``.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
query (ndb.Query)
|
|
||||||
by (ndb.model.Property): either :attr:`models.Object.updated` or
|
|
||||||
:attr:`models.Object.created`
|
|
||||||
user (models.User): current user
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
(list of models.Object, str, str) tuple:
|
|
||||||
(results, new ``before`` query param, new ``after`` query param)
|
|
||||||
to fetch the previous and next pages, respectively
|
|
||||||
"""
|
|
||||||
assert by is Object.updated or by is Object.created
|
|
||||||
objects, new_before, new_after = fetch_page(query, Object, by=by)
|
|
||||||
objects = [o for o in objects if not o.deleted]
|
|
||||||
|
|
||||||
# synthesize human-friendly content for objects
|
|
||||||
for i, obj in enumerate(objects):
|
|
||||||
if obj.deleted:
|
|
||||||
continue
|
|
||||||
|
|
||||||
obj_as1 = obj.as1
|
|
||||||
inner_obj = as1.get_object(obj_as1)
|
|
||||||
|
|
||||||
# synthesize text snippet
|
|
||||||
type = as1.object_type(obj_as1)
|
|
||||||
if type == 'post':
|
|
||||||
inner_type = inner_obj.get('objectType')
|
|
||||||
if inner_type:
|
|
||||||
type = inner_type
|
|
||||||
|
|
||||||
phrases = {
|
|
||||||
'article': 'posted',
|
|
||||||
'comment': 'replied',
|
|
||||||
'delete': 'deleted',
|
|
||||||
'follow': 'followed',
|
|
||||||
'invite': 'is invited to',
|
|
||||||
'issue': 'filed issue',
|
|
||||||
'like': 'liked',
|
|
||||||
'note': 'posted',
|
|
||||||
'post': 'posted',
|
|
||||||
'repost': 'reposted',
|
|
||||||
'rsvp-interested': 'is interested in',
|
|
||||||
'rsvp-maybe': 'might attend',
|
|
||||||
'rsvp-no': 'is not attending',
|
|
||||||
'rsvp-yes': 'is attending',
|
|
||||||
'share': 'reposted',
|
|
||||||
'stop-following': 'unfollowed',
|
|
||||||
'update': 'updated',
|
|
||||||
}
|
|
||||||
obj.phrase = phrases.get(type)
|
|
||||||
|
|
||||||
content = (inner_obj.get('content')
|
|
||||||
or inner_obj.get('displayName')
|
|
||||||
or inner_obj.get('summary'))
|
|
||||||
if content:
|
|
||||||
content = util.parse_html(content).get_text()
|
|
||||||
|
|
||||||
urls = as1.object_urls(inner_obj)
|
|
||||||
id = common.unwrap(inner_obj.get('id', ''))
|
|
||||||
url = urls[0] if urls else id
|
|
||||||
if (type == 'update' and
|
|
||||||
(obj.users and (user.is_web_url(id)
|
|
||||||
or id.strip('/') == obj.users[0].id())
|
|
||||||
or obj.domains and id.strip('/') == f'https://{obj.domains[0]}')):
|
|
||||||
obj.phrase = 'updated'
|
|
||||||
obj_as1.update({
|
|
||||||
'content': 'their profile',
|
|
||||||
'url': id,
|
|
||||||
})
|
|
||||||
elif url:
|
|
||||||
# heuristics for sniffing Mastodon and similar fediverse URLs and
|
|
||||||
# converting them to more friendly @-names
|
|
||||||
# TODO: standardize this into granary.as2 somewhere?
|
|
||||||
if not content:
|
|
||||||
fedi_url = re.match(
|
|
||||||
r'https://[^/]+/(@|users/)([^/@]+)(@[^/@]+)?(/(?:statuses/)?[0-9]+)?', url)
|
|
||||||
if fedi_url:
|
|
||||||
content = '@' + fedi_url.group(2)
|
|
||||||
if fedi_url.group(4):
|
|
||||||
content += "'s post"
|
|
||||||
content = common.pretty_link(url, text=content)
|
|
||||||
|
|
||||||
obj.content = (obj_as1.get('content')
|
|
||||||
or obj_as1.get('displayName')
|
|
||||||
or obj_as1.get('summary'))
|
|
||||||
obj.url = util.get_first(obj_as1, 'url')
|
|
||||||
|
|
||||||
if type in ('like', 'follow', 'repost', 'share') or not obj.content:
|
|
||||||
if obj.url:
|
|
||||||
obj.phrase = common.pretty_link(obj.url, text=obj.phrase,
|
|
||||||
attrs={'class': 'u-url'})
|
|
||||||
if content:
|
|
||||||
obj.content = content
|
|
||||||
obj.url = url
|
|
||||||
|
|
||||||
return objects, new_before, new_after
|
|
||||||
|
|
||||||
|
|
||||||
@app.get('/stats')
|
@app.get('/stats')
|
||||||
@canonicalize_request_domain(common.PROTOCOL_DOMAINS, common.PRIMARY_DOMAIN)
|
@canonicalize_request_domain(common.PROTOCOL_DOMAINS, common.PRIMARY_DOMAIN)
|
||||||
def stats():
|
def stats():
|
||||||
|
|
Ładowanie…
Reference in New Issue