Skip to content

Commit

Permalink
add ATProto.send_chat
Browse files Browse the repository at this point in the history
for #1024, #966, #758, etc
  • Loading branch information
snarfed committed Aug 7, 2024
1 parent a49fa0d commit c8d6ba5
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 0 deletions.
37 changes: 37 additions & 0 deletions atproto.py
Original file line number Diff line number Diff line change
Expand Up @@ -834,3 +834,40 @@ def create_report(cls, input, from_user):
output = client.com.atproto.moderation.createReport(input)
logger.info(f'Created report on {mod_host}: {json_dumps(output)}')
return True

def send_chat(self, msg, from_user):
"""Sends a chat message to this user.
Args:
msg (dict): ``chat.bsky.convo.defs#messageInput``
from_user (models.User)
Returns:
bool: True if the report was sent successfully, False if the flag's
actor is not bridged into ATProto
"""
assert msg['$type'] == 'chat.bsky.convo.defs#messageInput'

to_did = self.key.id()
from_did = from_user.get_copy(ATProto)
if not from_did or not from_user.is_enabled(ATProto):
return False

repo = arroba.server.storage.load_repo(from_did)

chat_host = os.environ['CHAT_HOST']
token = service_jwt(host=chat_host,
aud=os.environ['CHAT_DID'],
repo_did=from_did,
privkey=repo.signing_key)
client = Client(f'https://{chat_host}', truncate=True, headers={
'User-Agent': USER_AGENT,
'Authorization': f'Bearer {token}',
})
convo = client.chat.bsky.convo.getConvoForMembers(members=[to_did])
output = client.chat.bsky.convo.sendMessage({
'convoId': convo['convo']['id'],
'message': msg,
})
logger.info(f'Sent chat message from {from_user.handle} to {self.handle} {to_did}: {json_dumps(output)}')
return True
3 changes: 3 additions & 0 deletions router.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ env_variables:
BGS_HOST: bsky.network
MOD_SERVICE_HOST: mod.bsky.app
MOD_SERVICE_DID: did:plc:ar7c4by46qjdydhdevvrndac
# https://bsky.app/profile/gargaj.umlaut.hu/post/3kxsvpqiuln26
CHAT_HOST: api.bsky.chat
CHAT_DID: did:web:api.bsky.chat

manual_scaling:
instances: 1
Expand Down
49 changes: 49 additions & 0 deletions tests/test_atproto.py
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,55 @@ def test_send_flag_createReport(self, _, mock_post):
'Authorization': ANY,
})

# sendMessage
@patch('requests.post', return_value=requests_response({
'id': 'chat456',
'rev': '22222222tef2d',
'sender': {'did': 'did:plc:user'},
'text': 'hello world',
}))
@patch('requests.get', side_effect=[
requests_response({ # getConvoForMembers
'convo': {
'id': 'convo123',
'rev': '22222222fuozt',
'members': [{
'did': 'did:plc:alice',
'handle': 'alice.bsky.social',
}, {
'did': 'did:plc:user',
'handle': 'handull',
}],
},
}),
requests_response(DID_DOC),
])
def test_send_chat(self, mock_get, mock_post):
user = self.make_user_and_repo()
alice = ATProto(id='did:plc:alice')

self.assertTrue(alice.send_chat({
'$type': 'chat.bsky.convo.defs#messageInput',
'text': 'hello world',
}, from_user=user))

mock_get.assert_any_call(
'https://chat.service.local/xrpc/chat.bsky.convo.getConvoForMembers?members=did%3Aplc%3Aalice',
json=None, data=None, headers=ANY)
mock_post.assert_called_with(
'https://chat.service.local/xrpc/chat.bsky.convo.sendMessage',
json={
'convoId': 'convo123',
'message': {
'$type': 'chat.bsky.convo.defs#messageInput',
'text': 'hello world',
},
}, data=None, headers={
'Content-Type': 'application/json',
'User-Agent': common.USER_AGENT,
'Authorization': ANY,
})

def test_datastore_client_get_record_datastore_object(self):
self.make_user_and_repo()
post = {
Expand Down
2 changes: 2 additions & 0 deletions tests/testutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ def setUp(self):
'PLC_HOST': 'plc.local',
'MOD_SERVICE_HOST': 'mod.service.local',
'MOD_SERVICE_DID': 'did:mod-service',
'CHAT_HOST': 'chat.service.local',
'CHAT_DID': 'did:chat-service',
})
atproto.appview.address = 'https://appview.local'

Expand Down

0 comments on commit c8d6ba5

Please sign in to comment.