Skip to content

Instantly share code, notes, and snippets.

@gtmanfred
Created February 19, 2018 20:27
Show Gist options
  • Save gtmanfred/3d02b0ee179a886bb8cd88b6c01e7731 to your computer and use it in GitHub Desktop.
Save gtmanfred/3d02b0ee179a886bb8cd88b6c01e7731 to your computer and use it in GitHub Desktop.
import irc3
import json
import re
@irc3.plugin
class Slack:
def __init__(self, bot):
self.web = irc3.utils.maybedotted('aiohttp')
self.bot = bot
self.config = self.bot.config.get(__name__, {})
self.channels = self.bot.config.get(f'{__name__}.channels', {})
self.slack_channels = {}
if 'token' not in self.config:
self.bot.log.warning('No slack token is set.')
async def api_call(self, method, data=None):
"""Slack API call."""
async with self.web.ClientSession() as session:
form = self.web.FormData(data or {})
form.add_field('token', self.config['token'])
async with session.post('https://slack.com/api/{0}'.format(method), data=form) as response:
assert 200 == response.status, ('{0} with {1} failed.'.format(method, data))
return await response.json()
def server_ready(self):
irc3.asyncio.ensure_future(self.connect())
'''
def parse_text(self, message):
matches = [
(r'\n|\r\n|\r', ''),
(r'<!channel>', '@channel'),
(r'<!group>', '@group'),
(r'<!everyone>', '@everyone'),
]
.replace(/<#(C\w+)\|?(\w+)?>/g, (match, channelId, readable) => {
const { name } = dataStore.getChannelById(channelId);
return readable || `#${name}`;
})
.replace(/<@(U\w+)\|?(\w+)?>/g, (match, userId, readable) => {
const { name } = dataStore.getUserById(userId);
return readable || `@${name}`;
})
.replace(/<(?!!)([^|]+?)>/g, (match, link) => link)
.replace(/<!(\w+)\|?(\w+)?>/g, (match, command, label) =>
`<${label || command}>`
)
.replace(/:(\w+):/g, (match, emoji) => {
if (emoji in emojis) {
return emojis[emoji];
}
return match;
})
.replace(/<.+?\|(.+?)>/g, (match, readable) => readable)
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&amp;/g, '&');
'''
async def connect(self):
channels = await self.api_call('channels.list')
groups = await self.api_call('groups.list')
for channel in channels.get('channels', []):
self.slack_channels[channel['id']] = channel
if channel['name'] in self.channels:
self.channels[channel['id']] = self.channels.pop(channel['name'])
for channel in groups.get('groups', []):
self.slack_channels[channel['id']] = channel
if channel['name'] in self.channels:
self.channels[channel['id']] = self.channels.pop(channel['name'])
rtm = await self.api_call('rtm.start')
if not rtm['ok']:
raise Exception('Error connecting to RTM')
while True:
async with self.web.ClientSession() as session:
async with session.ws_connect(rtm['url']) as ws:
async for msg in ws:
if msg.type == self.web.WSMsgType.TEXT:
message = json.loads(msg.data)
self.bot.log.debug(f'Sending message to irc: {message}')
if message['type'] == 'message' and message.get('subtype') != 'bot_message':
user = await self.api_call('users.info', {'user': message['user']})
for channel in self.channels.get(message['channel'], []):
await self.bot.privmsg(channel, f"<{user['user']['name']}> {message['text']}")
elif msg.type == self.web.WSMsgType.CLOSED:
break
elif msg.type == self.web.WSMsgType.ERROR:
break
@irc3.event(irc3.rfc.MY_PRIVMSG)
def on_message(self, target=None, nick=None, data=None, **kwargs):
self.bot.log.info(f'{target} {nick} {data}')
irc3.asyncio.ensure_future(self.forward_message(target, nick, data))
async def forward_message(self, target, nick, data):
for channel, irc in self.channels.items():
if target in irc:
payload = {
'channel': channel,
'text': data,
'as_user': False,
'username': nick,
'icon_url': f'http://api.adorable.io/avatars/48/{nick}.jpg'
}
await self.api_call('chat.postMessage', data=payload)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment