kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
1686a2ba91
commit
f357ea1698
|
@ -57,7 +57,9 @@ WEB_OPT_OUT_DOMAINS = None
|
||||||
|
|
||||||
FEDI_URL_RE = re.compile(r'https://[^/]+/(@|users/)([^/@]+)(@[^/@]+)?(/(?:statuses/)?[0-9]+)?')
|
FEDI_URL_RE = re.compile(r'https://[^/]+/(@|users/)([^/@]+)(@[^/@]+)?(/(?:statuses/)?[0-9]+)?')
|
||||||
|
|
||||||
_BOT_ACTOR_IDS = None
|
# can't use translate_user_id because Web.owns_id checks valid_domain, which
|
||||||
|
# doesn't allow our protocol subdomains
|
||||||
|
BOT_ACTOR_IDS = [f'https://{domain}/{domain}' for domain in PROTOCOL_DOMAINS]
|
||||||
|
|
||||||
|
|
||||||
def instance_actor():
|
def instance_actor():
|
||||||
|
@ -68,15 +70,6 @@ def instance_actor():
|
||||||
return _INSTANCE_ACTOR
|
return _INSTANCE_ACTOR
|
||||||
|
|
||||||
|
|
||||||
def bot_actor_ids():
|
|
||||||
global _BOT_ACTOR_IDS
|
|
||||||
if _BOT_ACTOR_IDS is None:
|
|
||||||
from activitypub import ActivityPub
|
|
||||||
_BOT_ACTOR_IDS = [translate_user_id(id=domain, from_=Web, to=ActivityPub)
|
|
||||||
for domain in PROTOCOL_DOMAINS]
|
|
||||||
return _BOT_ACTOR_IDS
|
|
||||||
|
|
||||||
|
|
||||||
class ActivityPub(User, Protocol):
|
class ActivityPub(User, Protocol):
|
||||||
"""ActivityPub protocol class.
|
"""ActivityPub protocol class.
|
||||||
|
|
||||||
|
@ -939,7 +932,12 @@ def inbox(protocol=None, id=None):
|
||||||
# those as explicitly public. Use as2's is_public instead of as1's because
|
# those as explicitly public. Use as2's is_public instead of as1's because
|
||||||
# as1's interprets unlisted as true.
|
# as1's interprets unlisted as true.
|
||||||
# TODO: move this to Protocol
|
# TODO: move this to Protocol
|
||||||
if type == 'Create' and not as2.is_public(activity, unlisted=False):
|
object = as1.get_object(activity)
|
||||||
|
to_cc = set(as1.get_ids(object, 'to') + as1.get_ids(activity, 'cc') +
|
||||||
|
as1.get_ids(object, 'to') + as1.get_ids(object, 'cc'))
|
||||||
|
if (type == 'Create' and not as2.is_public(activity, unlisted=False)
|
||||||
|
# DM to one of our protocol bot users
|
||||||
|
and not (len(to_cc) == 1 and to_cc.pop() in BOT_ACTOR_IDS)):
|
||||||
logger.info('Dropping non-public activity')
|
logger.info('Dropping non-public activity')
|
||||||
return 'OK'
|
return 'OK'
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,9 @@ PROTOCOL_DOMAINS = (
|
||||||
'atproto.brid.gy',
|
'atproto.brid.gy',
|
||||||
'bluesky.brid.gy',
|
'bluesky.brid.gy',
|
||||||
'bsky.brid.gy',
|
'bsky.brid.gy',
|
||||||
|
'eefake.brid.gy',
|
||||||
'fa.brid.gy',
|
'fa.brid.gy',
|
||||||
|
'other.brid.gy',
|
||||||
'nostr.brid.gy',
|
'nostr.brid.gy',
|
||||||
'web.brid.gy',
|
'web.brid.gy',
|
||||||
)
|
)
|
||||||
|
|
22
protocol.py
22
protocol.py
|
@ -805,18 +805,18 @@ class Protocol:
|
||||||
return 'OK', 200
|
return 'OK', 200
|
||||||
|
|
||||||
elif obj.type == 'post':
|
elif obj.type == 'post':
|
||||||
to_cc = (util.get_list(inner_obj_as1, 'to')
|
to_cc = (as1.get_ids(inner_obj_as1, 'to')
|
||||||
+ util.get_list(inner_obj_as1, 'cc'))
|
+ as1.get_ids(inner_obj_as1, 'cc'))
|
||||||
if len(to_cc) == 1 and to_cc[0] in PROTOCOL_DOMAINS:
|
content = inner_obj_as1.get('content', '').strip().lower()
|
||||||
content = inner_obj_as1.get('content').strip().lower()
|
logger.info(f'got DM to {to_cc}: {content}')
|
||||||
logger.info(f'DM to bot user {to_cc}: {content}')
|
if len(to_cc) == 1:
|
||||||
proto = Protocol.for_bridgy_subdomain(to_cc[0])
|
proto = Protocol.for_bridgy_subdomain(to_cc[0])
|
||||||
assert proto
|
if proto:
|
||||||
if content in ('yes', 'ok'):
|
if content in ('yes', 'ok'):
|
||||||
from_user.enable_protocol(proto)
|
from_user.enable_protocol(proto)
|
||||||
elif content == 'no':
|
elif content == 'no':
|
||||||
from_user.disable_protocol(proto)
|
from_user.disable_protocol(proto)
|
||||||
return 'OK', 200
|
return 'OK', 200
|
||||||
|
|
||||||
# fetch actor if necessary
|
# fetch actor if necessary
|
||||||
if actor and actor.keys() == set(['id']):
|
if actor and actor.keys() == set(['id']):
|
||||||
|
|
|
@ -20,7 +20,7 @@ from werkzeug.exceptions import BadGateway, BadRequest
|
||||||
|
|
||||||
# import first so that Fake is defined before URL routes are registered
|
# import first so that Fake is defined before URL routes are registered
|
||||||
from . import testutil
|
from . import testutil
|
||||||
from .testutil import Fake, TestCase
|
from .testutil import ExplicitEnableFake, Fake, TestCase
|
||||||
|
|
||||||
import activitypub
|
import activitypub
|
||||||
from activitypub import (
|
from activitypub import (
|
||||||
|
@ -847,6 +847,26 @@ class ActivityPubTest(TestCase):
|
||||||
self.assertIsNone(Object.get_by_id(not_public['id']))
|
self.assertIsNone(Object.get_by_id(not_public['id']))
|
||||||
self.assertIsNone(Object.get_by_id(not_public['object']['id']))
|
self.assertIsNone(Object.get_by_id(not_public['object']['id']))
|
||||||
|
|
||||||
|
def test_inbox_dm_yes_to_bot_user_enables_protocol(self, *mocks):
|
||||||
|
user = self.make_user(ACTOR['id'], cls=ActivityPub)
|
||||||
|
self.assertFalse(ActivityPub.is_enabled_to(ExplicitEnableFake, user))
|
||||||
|
|
||||||
|
got = self.post('/ap/sharedInbox', json={
|
||||||
|
'type': 'Create',
|
||||||
|
'id': 'https://mas.to/dm#create',
|
||||||
|
'to': ['https://eefake.brid.gy/eefake.brid.gy'],
|
||||||
|
'object': {
|
||||||
|
'type': 'Note',
|
||||||
|
'id': 'https://mas.to/dm',
|
||||||
|
'attributedTo': ACTOR['id'],
|
||||||
|
'to': ['https://eefake.brid.gy/eefake.brid.gy'],
|
||||||
|
'content': 'yes',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
self.assertEqual(200, got.status_code, got.get_data(as_text=True))
|
||||||
|
user = user.key.get()
|
||||||
|
self.assertTrue(ActivityPub.is_enabled_to(ExplicitEnableFake, user))
|
||||||
|
|
||||||
def test_inbox_actor_blocklisted(self, mock_head, mock_get, mock_post):
|
def test_inbox_actor_blocklisted(self, mock_head, mock_get, mock_post):
|
||||||
got = self.post('/ap/sharedInbox', json={
|
got = self.post('/ap/sharedInbox', json={
|
||||||
'type': 'Delete',
|
'type': 'Delete',
|
||||||
|
|
Ładowanie…
Reference in New Issue