kopia lustrzana https://github.com/snarfed/bridgy-fed
opt in/out prompt: accept yes/no DMs to bot users to enable/disable protocols
for #880pull/968/head
rodzic
0c37d94191
commit
1686a2ba91
|
@ -30,6 +30,7 @@ from common import (
|
|||
host_url,
|
||||
LOCAL_DOMAINS,
|
||||
PRIMARY_DOMAIN,
|
||||
PROTOCOL_DOMAINS,
|
||||
redirect_wrap,
|
||||
subdomain_wrap,
|
||||
unwrap,
|
||||
|
@ -56,6 +57,8 @@ WEB_OPT_OUT_DOMAINS = None
|
|||
|
||||
FEDI_URL_RE = re.compile(r'https://[^/]+/(@|users/)([^/@]+)(@[^/@]+)?(/(?:statuses/)?[0-9]+)?')
|
||||
|
||||
_BOT_ACTOR_IDS = None
|
||||
|
||||
|
||||
def instance_actor():
|
||||
global _INSTANCE_ACTOR
|
||||
|
@ -65,6 +68,15 @@ def 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):
|
||||
"""ActivityPub protocol class.
|
||||
|
||||
|
@ -926,6 +938,7 @@ def inbox(protocol=None, id=None):
|
|||
# follows, or other activity types, since Mastodon doesn't currently mark
|
||||
# those as explicitly public. Use as2's is_public instead of as1's because
|
||||
# as1's interprets unlisted as true.
|
||||
# TODO: move this to Protocol
|
||||
if type == 'Create' and not as2.is_public(activity, unlisted=False):
|
||||
logger.info('Dropping non-public activity')
|
||||
return 'OK'
|
||||
|
|
14
protocol.py
14
protocol.py
|
@ -804,6 +804,20 @@ class Protocol:
|
|||
from_user.disable_protocol(proto)
|
||||
return 'OK', 200
|
||||
|
||||
elif obj.type == 'post':
|
||||
to_cc = (util.get_list(inner_obj_as1, 'to')
|
||||
+ util.get_list(inner_obj_as1, 'cc'))
|
||||
if len(to_cc) == 1 and to_cc[0] in PROTOCOL_DOMAINS:
|
||||
content = inner_obj_as1.get('content').strip().lower()
|
||||
logger.info(f'DM to bot user {to_cc}: {content}')
|
||||
proto = Protocol.for_bridgy_subdomain(to_cc[0])
|
||||
assert proto
|
||||
if content in ('yes', 'ok'):
|
||||
from_user.enable_protocol(proto)
|
||||
elif content == 'no':
|
||||
from_user.disable_protocol(proto)
|
||||
return 'OK', 200
|
||||
|
||||
# fetch actor if necessary
|
||||
if actor and actor.keys() == set(['id']):
|
||||
logger.info('Fetching actor so we have name, profile photo, etc')
|
||||
|
|
|
@ -829,6 +829,9 @@ class ActivityPubTest(TestCase):
|
|||
def test_inbox_unlisted(self, *mocks):
|
||||
self._test_inbox_with_to_ignored(['@unlisted'], *mocks)
|
||||
|
||||
def test_inbox_dm(self, *mocks):
|
||||
self._test_inbox_with_to_ignored(['http://localhost/web/user.com'], *mocks)
|
||||
|
||||
def _test_inbox_with_to_ignored(self, to, mock_head, mock_get, mock_post):
|
||||
Follower.get_or_create(to=self.make_user(ACTOR['id'], cls=ActivityPub),
|
||||
from_=self.user)
|
||||
|
|
|
@ -1796,7 +1796,7 @@ class ProtocolReceiveTest(TestCase):
|
|||
user = self.make_user('eefake:user', cls=ExplicitEnableFake)
|
||||
self.assertFalse(ExplicitEnableFake.is_enabled_to(Fake, user))
|
||||
|
||||
# protocol isn't enabled yet, block should be a noop
|
||||
# fake protocol isn't enabled yet, block should be a noop
|
||||
self.assertEqual(('OK', 200), ExplicitEnableFake.receive_as1(block))
|
||||
user = user.key.get()
|
||||
self.assertEqual([], user.enabled_protocols)
|
||||
|
@ -1826,6 +1826,45 @@ class ProtocolReceiveTest(TestCase):
|
|||
self.assertEqual([], user.enabled_protocols)
|
||||
self.assertFalse(ExplicitEnableFake.is_enabled_to(Fake, user))
|
||||
|
||||
def test_dm_no_yes_sets_enabled_protocols(self):
|
||||
dm = {
|
||||
'objectType': 'note',
|
||||
'id': 'eefake:dm',
|
||||
'actor': 'eefake:user',
|
||||
'to': ['fa.brid.gy'],
|
||||
'content': 'no',
|
||||
}
|
||||
|
||||
user = self.make_user('eefake:user', cls=ExplicitEnableFake)
|
||||
self.assertFalse(ExplicitEnableFake.is_enabled_to(Fake, user))
|
||||
|
||||
# fake protocol isn't enabled yet, no DM should be a noop
|
||||
self.assertEqual(('OK', 200), ExplicitEnableFake.receive_as1(dm))
|
||||
user = user.key.get()
|
||||
self.assertEqual([], user.enabled_protocols)
|
||||
|
||||
# yes DM should add to enabled_protocols
|
||||
dm['id'] += '2'
|
||||
dm['content'] = 'yes'
|
||||
self.assertEqual(('OK', 200), ExplicitEnableFake.receive_as1(dm))
|
||||
user = user.key.get()
|
||||
self.assertEqual(['fake'], user.enabled_protocols)
|
||||
self.assertTrue(ExplicitEnableFake.is_enabled_to(Fake, user))
|
||||
|
||||
# another yes DM should be a noop
|
||||
dm['id'] += '3'
|
||||
self.assertEqual(('OK', 200), ExplicitEnableFake.receive_as1(dm))
|
||||
user = user.key.get()
|
||||
self.assertEqual(['fake'], user.enabled_protocols)
|
||||
|
||||
# block should remove from enabled_protocols
|
||||
dm['id'] += '4'
|
||||
dm['content'] = ' \n NO '
|
||||
self.assertEqual(('OK', 200), ExplicitEnableFake.receive_as1(dm))
|
||||
user = user.key.get()
|
||||
self.assertEqual([], user.enabled_protocols)
|
||||
self.assertFalse(ExplicitEnableFake.is_enabled_to(Fake, user))
|
||||
|
||||
def test_receive_task_handler(self):
|
||||
note = {
|
||||
'id': 'fake:post',
|
||||
|
|
Ładowanie…
Reference in New Issue