kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
a6cd9f22ab
commit
1b78e86e6c
|
@ -63,7 +63,7 @@ How to add a new protocol
|
|||
1. Implement the protocol in a new `.py` file as a subclass of both [`Protocol`](https://github.com/snarfed/bridgy-fed/blob/main/protocol.py) and [`User`](https://github.com/snarfed/bridgy-fed/blob/main/models.py). Implement the `send`, `fetch`, `serve`, and `target_for` methods from `Protocol` and `handle` and `web_url` from `User` .
|
||||
1. TODO: add a new usage section to the docs for the new protocol.
|
||||
1. TODO: does the new protocol need any new UI or signup functionality? Unusual, but not impossible. Add that if necessary.
|
||||
1. Add the new protocol's logo to `static/`, use it in [`templates/user.html`](https://github.com/snarfed/bridgy-fed/blob/main/templates/user.html).
|
||||
1. Protocol logos may be emoji or image files. If this one is a file, add it `static/`. Then add the emoji or file `<img>` tag in the `Protocol` subclass's `LOGO_HTML` constant.
|
||||
|
||||
|
||||
Stats
|
||||
|
|
|
@ -62,6 +62,7 @@ class ActivityPub(User, Protocol):
|
|||
Key id is AP/AS2 actor id URL. (*Not* fediverse/WebFinger @-@ handle!)
|
||||
"""
|
||||
ABBREV = 'ap'
|
||||
LOGO_HTML = '<img src="/static/fediverse_logo.svg">'
|
||||
|
||||
def _pre_put_hook(self):
|
||||
"""Validate id, require URL, don't allow Bridgy Fed domains.
|
||||
|
|
|
@ -56,6 +56,7 @@ class ATProto(User, Protocol):
|
|||
https://atproto.com/specs/did
|
||||
"""
|
||||
ABBREV = 'atproto'
|
||||
LOGO_HTML = '<img src="/static/atproto_logo.png">'
|
||||
|
||||
def _pre_put_hook(self):
|
||||
"""Validate id, require did:plc or non-blocklisted did:web.
|
||||
|
|
|
@ -119,7 +119,7 @@ def pretty_link(url, text=None, **kwargs):
|
|||
kwargs: passed through to :func:`oauth_dropins.webutil.util.pretty_link`
|
||||
"""
|
||||
if g.user and g.user.is_web_url(url):
|
||||
return g.user.user_page_link()
|
||||
return g.user.user_link()
|
||||
|
||||
if text is None:
|
||||
match = re.match(r'https?://([^/]+)/(@|users/)([^/]+)$', url)
|
||||
|
|
14
models.py
14
models.py
|
@ -465,11 +465,17 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
|
|||
|
||||
return path
|
||||
|
||||
def user_page_link(self):
|
||||
"""Returns a pretty user page link with the user's name and profile picture."""
|
||||
def user_link(self):
|
||||
"""Returns a pretty link to the external user with name and profile picture."""
|
||||
actor = self.obj.as1 if self.obj and self.obj.as1 else {}
|
||||
img = util.get_url(actor, 'image') or ''
|
||||
return f'<a class="h-card u-author" href="{self.user_page_path()}"><img src="{img}" class="profile"> {self.name()}</a>'
|
||||
return f"""\
|
||||
<a class="h-card u-author" href="{self.web_url()}">
|
||||
<img src="{img}" class="profile">
|
||||
<span class="logo">{self.LOGO_HTML}</span>
|
||||
{self.name()}
|
||||
</a>
|
||||
"""
|
||||
|
||||
|
||||
class Object(StringIdModel):
|
||||
|
@ -835,7 +841,7 @@ class Object(StringIdModel):
|
|||
if (self.source_protocol in ('web', 'webmention', 'ui') and g.user
|
||||
and (g.user.key in self.users or g.user.key.id() in self.domains)):
|
||||
# outbound; show a nice link to the user
|
||||
return g.user.user_page_link()
|
||||
return g.user.user_link()
|
||||
|
||||
actor = {}
|
||||
if self.as1:
|
||||
|
|
|
@ -59,9 +59,11 @@ class Protocol:
|
|||
LABEL (str): human-readable lower case name
|
||||
OTHER_LABELS (list of str): label aliases
|
||||
ABBREV (str): lower case abbreviation, used in URL paths
|
||||
LOGO_HTML (str): logo emoji or ``<img>`` tag
|
||||
"""
|
||||
ABBREV = None
|
||||
OTHER_LABELS = ()
|
||||
LOGO_HTML = ''
|
||||
|
||||
def __init__(self):
|
||||
assert False
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 225 KiB |
|
@ -1,6 +1,6 @@
|
|||
<div class="row">
|
||||
<div class="big" style="display: inline">
|
||||
{{ g.user.user_page_link()|safe }}
|
||||
{{ g.user.user_link()|safe }}
|
||||
·
|
||||
<span title="Fediverse address">
|
||||
<nobr>
|
||||
|
|
|
@ -31,9 +31,12 @@ class CommonTest(TestCase):
|
|||
|
||||
# current user's homepage gets converted to BF user page
|
||||
g.user = Web(id='user.com')
|
||||
self.assertEqual(
|
||||
'<a class="h-card u-author" href="/web/user.com"><img src="" class="profile"> user.com</a>',
|
||||
common.pretty_link('https://user.com/'))
|
||||
self.assert_multiline_equals("""\
|
||||
<a class="h-card u-author" href="https://user.com/">
|
||||
<img src="" class="profile">
|
||||
<span class="logo">🕸️</span>
|
||||
user.com
|
||||
</a>""", common.pretty_link('https://user.com/'))
|
||||
|
||||
def test_redirect_wrap_empty(self):
|
||||
self.assertIsNone(common.redirect_wrap(None))
|
||||
|
|
|
@ -135,10 +135,21 @@ class UserTest(TestCase):
|
|||
self.assertEqual('/web/y.z/followers', g.user.user_page_path('followers'))
|
||||
self.assertEqual('/fa/foo', self.make_user('foo', cls=Fake).user_page_path())
|
||||
|
||||
def test_user_page_link(self):
|
||||
self.assertEqual('<a class="h-card u-author" href="/web/y.z"><img src="" class="profile"> y.z</a>', g.user.user_page_link())
|
||||
def test_user_link(self):
|
||||
self.assert_multiline_equals("""\
|
||||
<a class="h-card u-author" href="https://y.z/">
|
||||
<img src="" class="profile">
|
||||
<span class="logo">🕸️</span>
|
||||
y.z
|
||||
</a>""", g.user.user_link())
|
||||
|
||||
g.user.obj = Object(id='a', as2=ACTOR)
|
||||
self.assertEqual('<a class="h-card u-author" href="/web/y.z"><img src="https://user.com/me.jpg" class="profile"> Mrs. ☕ Foo</a>', g.user.user_page_link())
|
||||
self.assert_multiline_equals("""\
|
||||
<a class="h-card u-author" href="https://y.z/">
|
||||
<img src="https://user.com/me.jpg" class="profile">
|
||||
<span class="logo">🕸️</span>
|
||||
Mrs. ☕ Foo
|
||||
</a>""", g.user.user_link())
|
||||
|
||||
def test_is_web_url(self):
|
||||
for url in 'y.z', '//y.z', 'http://y.z', 'https://y.z':
|
||||
|
@ -398,11 +409,12 @@ class ObjectTest(TestCase):
|
|||
self.assert_multiline_in(expected, obj.actor_link())
|
||||
|
||||
def test_actor_link_user(self):
|
||||
g.user = Fake(id='user.com', obj=Object(id='a', as2={"name": "Alice"}))
|
||||
g.user = Fake(id='fake:user', obj=Object(id='a', as2={"name": "Alice"}))
|
||||
obj = Object(id='x', source_protocol='ui', users=[g.user.key])
|
||||
self.assertIn(
|
||||
'href="/fa/user.com"><img src="" class="profile"> Alice</a>',
|
||||
obj.actor_link())
|
||||
|
||||
got = obj.actor_link()
|
||||
self.assertIn('href="fake:user">', got)
|
||||
self.assertIn('Alice', got)
|
||||
|
||||
def test_put_updates_load_cache(self):
|
||||
obj = Object(id='x', as2={})
|
||||
|
|
1
web.py
1
web.py
|
@ -68,6 +68,7 @@ class Web(User, Protocol):
|
|||
"""
|
||||
ABBREV = 'web'
|
||||
OTHER_LABELS = ('webmention',)
|
||||
LOGO_HTML = '🕸️'
|
||||
|
||||
has_redirects = ndb.BooleanProperty()
|
||||
redirects_error = ndb.TextProperty()
|
||||
|
|
Ładowanie…
Reference in New Issue