diff --git a/viera/actor.py b/viera/actor.py index c5ebd0d..ae166d3 100644 --- a/viera/actor.py +++ b/viera/actor.py @@ -41,6 +41,7 @@ async def actor(request): "sharedInbox": "https://{}/inbox".format(request.host) }, "followers": "https://{}/followers".format(request.host), + "following": "https://{}/following".format(request.host), "inbox": "https://{}/inbox".format(request.host), "name": "Viera", "type": "Application", @@ -76,19 +77,24 @@ async def push_message_to_actor(actor, message, our_key_id): } headers['signature'] = sign_headers(headers, PRIVKEY, our_key_id) + logging.debug('%r', headers) + logging.debug('%r >> %r', actor['inbox'], message) + async with aiohttp.ClientSession() as session: async with session.post(actor['inbox'], data=data, headers=headers) as resp: pass async def follow_remote_actor(actor_uri): + logging.info('following: %r', actor_uri) + actor = await fetch_actor(actor_uri) message = { "@context": "https://www.w3.org/ns/activitystreams", "type": "Follow", "to": [actor['id']], - "object": [actor['id']], + "object": actor['id'], "id": "https://{}/activities/{}".format(AP_CONFIG['host'], uuid.uuid4()), "actor": "https://{}/actor".format(AP_CONFIG['host']) } @@ -106,7 +112,7 @@ from .authreqs import check_reqs, get_irc_bot async def handle_create(actor, data, request): # for now, we only care about Notes - if data['object']['type'] != Note: + if data['object']['type'] != 'Note': return # strip the HTML if present @@ -119,7 +125,7 @@ async def handle_create(actor, data, request): # fetch our IRC bot bot = get_irc_bot() - bot.relay_message(actor, data['object'], content) + bot.relay_message(actor, data['object'], ' '.join(content)) async def handle_follow(actor, data, request): diff --git a/viera/irc.py b/viera/irc.py index 11d97ff..61a5b91 100644 --- a/viera/irc.py +++ b/viera/irc.py @@ -5,6 +5,7 @@ import base64 from blinker import signal from . import CONFIG +from .actor import follow_remote_actor from .irc_envelope import RFC1459Message from .authreqs import new_auth_req, set_irc_bot, check_auth, fetch_auth, drop_auth @@ -99,6 +100,10 @@ class IRCProtocol(asyncio.Protocol): return self.say(chan, '\x02{0}\x02: \x02{1}\x02'.format(nickname, data), verb='PRIVMSG') + def follow(self, nickname, actor_uri): + asyncio.ensure_future(follow_remote_actor(actor_uri)) + self.say(nickname, 'Following \x02{}\x02'.format(actor_uri)) + def set_pending_action(self, nickname, action): if nickname not in self.pending_actions: self.pending_actions[nickname] = action @@ -117,6 +122,9 @@ class IRCProtocol(asyncio.Protocol): self.say(nickname, "The association of \x02{0}\x02 with \x02{1}\x02 has been dropped.".format(account, data)) elif 'whois' in action: self.whois(nickname, action['whois'], account) + elif 'follow' in action: + logging.info('allowed follow: %r', action['follow']) + self.follow(nickname, action['follow']) def handle_auth_req(self, req): self.say(req.irc_nickname, "The actor \x02{0}\x02 is now linked to the IRC account \x02{1}\x02.".format(req.actor, req.irc_account)) @@ -155,6 +163,12 @@ class IRCProtocol(asyncio.Protocol): elif message.params[1] in ('voice', 'invite', 'drop'): self.set_pending_action(source_nick, message.params[1]) self.fetch_account_whox(message) + elif message.params[1][0:6] == 'follow': + chunks = message.params[1].split() + logging.info('considering whether to follow: %r', chunks[1]) + + self.set_pending_action(source_nick, {'follow': chunks[1]}) + self.fetch_account_whox(message) def handle_public_message(self, message): if not message.params[1].startswith(IRC_CONFIG['nickname']):