class SlackClient(object): def __init__(self, token): self.token = token self.server = Server(self.token, False) def rtm_connect(self): try: self.server.rtm_connect() return True except: return False def api_call(self, method, **kwargs): return self.server.api_call(method, kwargs) def rtm_read(self): #in the future, this should handle some events internally i.e. channel creation if self.server: json_data = self.server.websocket_safe_read() data = [] if json_data != '': for d in json_data.split('\n'): data.append(json.loads(d)) return data else: raise SlackNotConnected def rtm_send_message(self, channel, message): return self.server.channels.find(channel).send_message(message)
class Slack: def __init__(self, token, debug=False): self.debug = debug self.slackRTM = Server(token) slack = SlackClient(token) # Get user listen user_response = slack.api_call("users.list") self.users = {user['id']: user for user in user_response['members']} self.callbacks = {'message': []} self.slackRTM.rtm_connect() self.slackRTM.websocket.sock.setblocking(1) def start(self): while 1: recvd = self.slackRTM.websocket.recv() recvd = json.loads(recvd) if self.debug: print recvd if recvd['type'] == "message" and 'hidden' not in recvd: user = self.users[recvd['user']] team = recvd['team'] if 'team' in recvd else False args = (user['name'], recvd['channel'], recvd['text'], recvd['ts'], team) self.run_callbacks('message', args) def run_callbacks(self, callback_type, args): for callback in self.callbacks[callback_type]: callback(*args) def add_callback(self, callback_type, function): self.callbacks[callback_type].append(function)
def __init__(self, token, debug=False): self.debug = debug self.slackRTM = Server(token) slack = SlackClient(token) # Get user listen user_response = slack.api_call("users.list") self.users = {user['id']: user for user in user_response['members']} self.callbacks = {'message': []} self.slackRTM.rtm_connect() self.slackRTM.websocket.sock.setblocking(1)
class SlackClient(object): def __init__(self, token): self.token = token self.server = Server(self.token, False) def rtm_connect(self): try: self.server.rtm_connect() return True except: return False def api_call(self, method, **kwargs): return self.server.api_call(method, **kwargs) def rtm_read(self): # in the future, this should handle some events internally i.e. channel # creation if self.server: json_data = self.server.websocket_safe_read() data = [] if json_data != '': for d in json_data.split('\n'): data.append(json.loads(d)) for item in data: self.process_changes(item) return data else: raise SlackNotConnected def rtm_send_message(self, channel, message): return self.server.channels.find(channel).send_message(message) def process_changes(self, data): if "type" in data.keys(): if data["type"] in ('channel_created', 'group_joined'): channel = data["channel"] self.server.attach_channel(channel["name"], channel["id"], []) if data["type"] == 'im_created': channel = data["channel"] self.server.attach_channel(channel["user"], channel["id"], []) if data["type"] == "team_join": user = data["user"] self.server.parse_user_data([user]) pass
class Slack: def __init__(self, token, debug=False): self.debug = debug self.slackRTM = Server(token) slack = SlackClient(token) # Get user listen user_response = slack.api_call("users.list") self.users = { user['id']: user for user in user_response['members'] } self.callbacks = { 'message': [] } self.slackRTM.rtm_connect() self.slackRTM.websocket.sock.setblocking(1) def start(self): while 1: recvd = self.slackRTM.websocket.recv() recvd = json.loads(recvd) if self.debug: print recvd if recvd['type'] == "message" and 'hidden' not in recvd: user = self.users[recvd['user']] team = recvd['team'] if 'team' in recvd else False args = ( user['name'], recvd['channel'], recvd['text'], recvd['ts'], team ) self.run_callbacks('message', args) def run_callbacks(self, callback_type, args): for callback in self.callbacks[callback_type]: callback(*args) def add_callback(self, callback_type, function): self.callbacks[callback_type].append(function)
def __init__(self, token, debug=False): self.debug = debug self.slackRTM = Server(token) slack = SlackClient(token) # Get user listen user_response = slack.api_call("users.list") self.users = { user['id']: user for user in user_response['members'] } self.callbacks = { 'message': [] } self.slackRTM.rtm_connect() self.slackRTM.websocket.sock.setblocking(1)
def _do_slack_connection(self): if self._server: self._server.websocket.abort() self._server = Server(self._opts['slack_token'], False) self._server.rtm_connect() self._parse_login_data(self._server.login_data) self._server.websocket.sock.setblocking(1) self.api.im.close(channel='D038BM8HQ') try: while True: frame = self._server.websocket.recv() self._handle_frame(frame) except Exception as e: logger.error(e, exc_info=True)
def _do_slack_connection(self): if self._server: self._server.websocket.abort() self._server = Server(self._opts['slack_token'], False) self._server.rtm_connect() self._parse_login_data(self._server.login_data) self._server.websocket.sock.setblocking(1) self.api.im.close(channel='D038BM8HQ') while True: try: frame = self._server.websocket.recv() self._handle_frame(frame) except WebSocketConnectionClosedException: logger.error('WebSocket connection closed.') self._server.rtm_connect(reconnect=True) logger.info('Restarted WebSocket connection')
class SlackClient(object): ''' The SlackClient makes API Calls to the `Slack Web API <https://api.slack.com/web>`_ as well as managing connections to the `Real-time Messaging API via websocket <https://api.slack.com/rtm>`_ It also manages some of the Client state for Channels that the associated token (User or Bot) is associated with. For more information, check out the `Slack API Docs <https://api.slack.com/>`_ Init: :Args: token (str): Your Slack Authentication token. You can find or generate a test token `here <https://api.slack.com/docs/oauth-test-tokens>`_ Note: Be `careful with your token <https://api.slack.com/docs/oauth-safety>`_ ''' def __init__(self, token): self.token = token self.server = Server(self.token, False) def rtm_connect(self): ''' Connects to the RTM Websocket :Args: None :Returns: False on exceptions ''' try: self.server.rtm_connect() return True except: return False def api_call(self, method, **kwargs): ''' Call the Slack Web API as documented here: https://api.slack.com/web :Args: method (str): The API Method to call. See `the full list here <https://api.slack.com/methods>`_ :Kwargs: (optional) kwargs: any arguments passed here will be bundled and sent to the api requester as post_data and will be passed along to the API. Example:: sc.server.api_call( "channels.setPurpose", channel="CABC12345", purpose="Writing some code!" ) :Returns: str -- returns the text of the HTTP response. Examples:: u'{"ok":true,"purpose":"Testing bots"}' or u'{"ok":false,"error":"channel_not_found"}' See here for more information on responses: https://api.slack.com/web ''' result = json.loads(self.server.api_call(method, **kwargs)) if self.server: if method == 'im.open': if "ok" in result and result["ok"]: self.server.attach_channel(kwargs["user"], result["channel"]["id"]) elif method in ('mpim.open', 'groups.create', 'groups.createchild'): if "ok" in result and result["ok"]: self.server.attach_channel( result['group']['name'], result['group']['id'], result['group']['members'] ) elif method in ('channels.create', 'channels.join'): if 'ok' in result and result['ok']: self.server.attach_channel( result['channel']['name'], result['channel']['id'], result['channel']['members'] ) return result def rtm_read(self): ''' Reads from the RTM Websocket stream then calls `self.process_changes(item)` for each line in the returned data. Multiple events may be returned, always returns a list [], which is empty if there are no incoming messages. :Args: None :Returns: data (json) - The server response. For example:: [{u'presence': u'active', u'type': u'presence_change', u'user': u'UABC1234'}] :Raises: SlackNotConnected if self.server is not defined. ''' # in the future, this should handle some events internally i.e. channel # creation if self.server: json_data = self.server.websocket_safe_read() data = [] if json_data != '': for d in json_data.split('\n'): data.append(json.loads(d)) for item in data: self.process_changes(item) return data else: raise SlackNotConnected def rtm_send_message(self, channel, message): ''' Sends a message to a given channel. :Args: channel (str) - the string identifier for a channel or channel name (e.g. 'C1234ABC', 'bot-test' or '#bot-test') message (message) - the string you'd like to send to the channel :Returns: None ''' return self.server.channels.find(channel).send_message(message) def process_changes(self, data): ''' Internal method which processes RTM events and modifies the local data store accordingly. Stores new channels when joining a group (Multi-party DM), IM (DM) or channel. Stores user data on a team join event. ''' if "type" in data.keys(): if data["type"] in ('channel_created', 'group_joined'): channel = data["channel"] self.server.attach_channel(channel["name"], channel["id"], []) if data["type"] == 'im_created': channel = data["channel"] self.server.attach_channel(channel["user"], channel["id"], []) if data["type"] == "team_join": user = data["user"] self.server.parse_user_data([user]) pass
def __init__(self, token): self.token = token self.server = Server(self.token, False)
def server(monkeypatch): my_server = Server('xoxp-1234123412341234-12341234-1234', False) return my_server
def __init__(self, token, proxies=None): self.token = token self.server = Server(self.token, False, proxies)
class SlackAdapter(object): """ This adapter exposes a webhook that listens for slack messages. The web listener for this is independent of Jeev's WSGI server. They cannot run on the same port. This adapter works the same as Slack's Hubot adapter. So, when integrating with Jeev, from Slack's integration, use Hubot, and point it to the the adapter's listen host and port. """ class SlackObject(object): def __init__(self, data): self.data = data self._in_name_sets = set() @property def id(self): return self.data['id'] @property def name(self): return self.data['name'] def _iter_name_sets(self): pass def _link(self, name): self._in_name_sets.add(name) def _unlink(self): self._in_name_sets.clear() def iter_names(self): return iter(self._in_name_sets) def _update(self, **kwargs): for k, v in kwargs.iteritems(): if k == 'ok': continue self.data[k] = v def __str__(self): return self.name class SlackUser(SlackObject): @property def presence(self): return self.data['presence'] def __repr__(self): return '<SlackUser id=%r, name=%r, presence=%s>' % (self.id, self.name, self.presence) class _SlackChannelBase(SlackObject): is_direct_message = False def __init__(self, data, adapter): super(SlackAdapter._SlackChannelBase, self).__init__(data) self._adapter = adapter @property def topic(self): if 'topic' in self.data: return self.data['topic']['value'] @topic.setter def topic(self, val): if val != self.data['topic']: self._adapter.api.channels.setTopic(channel=self, topic=val) @property def purpose(self): if 'purpose' in self.data: return self.data['purpose']['value'] @purpose.setter def purpose(self, val): raise NotImplementedError("Bots cannot set channel purpose.") class SlackChannel(_SlackChannelBase): @property def members(self): members = [] for m in self.data['members']: members.append(self._adapter._users[m]) return members def _left(self, archive=False): keep_keys = 'created', 'creator', 'id', 'is_archived', 'is_channel', 'is_general' for k in self.data.keys(): if k not in keep_keys: del self.data[k] self.data.update( members=[], is_member=False ) if archive: self.data['is_archived'] = True def __repr__(self): return "<SlackChannel id=%r, name=%r, members=%r>" % ( self.id, self.name, self.members ) class _SlackGroupBase(SlackObject): is_direct_message = False def __init__(self, data, adapter): super(SlackAdapter._SlackGroupBase, self).__init__(data) self._adapter = adapter @property def topic(self): if 'topic' in self.data: return self.data['topic']['value'] @topic.setter def topic(self, val): if val != self.data['topic']: self._adapter.api.groups.setTopic(channel=self, topic=val) @property def purpose(self): if 'purpose' in self.data: return self.data['purpose']['value'] @purpose.setter def purpose(self, val): raise NotImplementedError("Bots cannot set group purpose.") class SlackGroup(_SlackGroupBase): @property def members(self): members = [] for m in self.data['members']: members.append(self._adapter._users[m]) return members def _left(self, archive=False): keep_keys = 'created', 'creator', 'id', 'is_archived', 'is_group', 'is_general' for k in self.data.keys(): if k not in keep_keys: del self.data[k] self.data.update( members=[], is_member=False ) if archive: self.data['is_archived'] = True def __repr__(self): return "<SlackGroup id=%r, name=%r, members=%r>" % ( self.id, self.name, self.members ) class SlackDirectMessage(_SlackChannelBase): is_direct_message = True @property def user(self): return self._adapter._users[self.data['user']] @property def members(self): return [self.user] def __repr__(self): return '<SlackDirectMessage id=%r, name=%r, user=%r>' % ( self.id, self.name, self.user ) class SlackObjectList(object): def __init__(self): self._obj_by_id = {} self._obj_by_name = defaultdict(set) def clear(self): self._obj_by_id.clear() self._obj_by_name.clear() def add(self, obj): if obj in self: self.remove(obj) self._obj_by_id[obj.id] = obj name = obj.name.lower() obj._link(name) self._obj_by_name[obj.name.lower()].add(obj) def remove(self, obj): self._obj_by_id.pop(obj.id) for name in obj.iter_names(): self._obj_by_name[name].discard(obj) obj._unlink() def __contains__(self, item): if isinstance(item, SlackAdapter.SlackObject): return item.id in self._obj_by_id and self._obj_by_id[item.id] is item else: return item in self._obj_by_id def __getitem__(self, key): if key in self._obj_by_id: return self._obj_by_id[key] raise KeyError(key) def __delitem__(self, key): if key in self._obj_by_id: obj = self._obj_by_id[key] self.remove(obj) else: raise KeyError(key) def find(self, name_or_id): if name_or_id in self: return self[name_or_id] name_or_id = name_or_id.lower() if name_or_id in self._obj_by_name: return next(iter(self._obj_by_name[name_or_id]), None) def names(self): return [k for k, v in self._obj_by_name.iteritems() if v] class SlackApi(object): def __init__(self, adapter=None, parent=None, part=None): if parent: self._adapter = parent._adapter self._parts = parent._parts[:] else: self._parts = [] self._adapter = adapter if part: self._parts.append(part) def __getattr__(self, item): return SlackAdapter.SlackApi(parent=self, part=item) def __call__(self, **kwargs): for k, v in kwargs.items(): if isinstance(v, SlackAdapter.SlackObject): kwargs[k] = v.id method = '.'.join(self._parts) or '?' logger.debug('Making API call %r with args %r', method, kwargs) result = json.loads(self._adapter._server.api_call(method, **kwargs)) logger.debug('Got response %r', result) result = self._adapter._process_post_method_hooks(method, kwargs, result) return result class MutableOutgoingMessage(object): def __init__(self, adapter, channel, message): self.channel = channel self.adapter = adapter self.id = adapter._generate_message_id() self.message = message self.needs_update = False self.ts = None def _recv_reply(self, data): self.ts = data['ts'] if self.needs_update: self._do_update() def _do_update(self): self.adapter.api.chat.update( ts=self.ts, channel=self.channel.id, text=self.message ) self.needs_update = False def update(self, message): self.message = message if self.ts: self._do_update() else: self.needs_update = True def serialize(self): return { 'text': self.message, 'channel': self.channel.id, 'type': 'message', 'id': self.id } def __repr__(self): return "<MutableOutgoingMessage id=%r, channel=%r, message=%r>" % ( self.id, self.channel, self.message ) def __init__(self, jeev, opts): self._jeev = jeev self._opts = opts self._server = None self._greenlet = None self._channels = self.SlackObjectList() self._dms = self.SlackObjectList() self._groups = self.SlackObjectList() self._users = self.SlackObjectList() self._outgoing_messages = {} self._last_id = 1 self.api = self.SlackApi(self) def start(self): if self._greenlet: raise RuntimeError("SlackAdapter Already Started.") self._greenlet = Greenlet(self._run) self._greenlet.start() def stop(self): self._greenlet.kill() def _run(self): while True: self._do_slack_connection() sleep(10) def _do_slack_connection(self): if self._server: self._server.websocket.abort() self._server = Server(self._opts['slack_token'], False) self._server.rtm_connect() self._parse_login_data(self._server.login_data) self._server.websocket.sock.setblocking(1) self.api.im.close(channel='D038BM8HQ') try: while True: frame = self._server.websocket.recv() self._handle_frame(frame) except Exception as e: logger.error(e, exc_info=True) def _handle_frame(self, frame): data = json.loads(frame) logger.debug("Got frame %r", frame) if 'reply_to' in data: message = self._outgoing_messages.pop(data['reply_to'], None) if message: logger.debug("Received reply for Message: %r", message) message._recv_reply(data) if 'type' not in data: return handler = getattr(self, '_handle_%s' % data['type'], None) if handler: return handler(data) else: logger.debug("No handler defined for message type %s", data['type']) def _handle_message(self, data): if 'subtype' not in data and 'reply_to' not in data: message = Message(data, self._get_channel_group_or_dm(data['channel']), self._users[data['user']], data['text']) return self._jeev._handle_message(message) def _handle_user_change(self, data): user = self._get_user(data['user']['id']) if user is None: return user._update(**data['user']) self._users.add(user) self._broadcast_event(events.User.Changed, user=user) def _handle_presence_change(self, data): # For reasons that aren't clear, slack does a presence change notification before telling jeev about a new user user = self._get_user(data['user']) if user is None: return user._update(presence=data['presence']) self._broadcast_event(events.User.PresenceChanged, user=user) def _handle_channel_created(self, data): channel = data['channel'].copy() channel.update(members=[], is_general=False, is_member=False, is_archived=False) channel = self.SlackChannel(channel, self) self._channels.add(channel) self._broadcast_event(events.Channel.Created, channel=channel) def _handle_channel_left(self, data): channel = self._channels[data['channel']] channel._left() self._broadcast_event(events.Channel.Left, channel=channel) def _handle_channel_deleted(self, data): self._handle_channel_left(data) channel = self._channels[data['channel']] self._channels.remove(channel) self._broadcast_event(events.Channel.Deleted, channel=channel) def _handle_channel_rename(self, data): channel = self._channels[data['channel']['id']] channel._update(**data['channel']) self._channels.add(channel) self._broadcast_event(events.Channel.Renamed, channel=channel) def _handle_channel_archive(self, data): channel = self._channels[data['channel']] channel._left(archive=True) self._broadcast_event(events.Channel.Archived, channel=channel) def _handle_channel_unarchive(self, data): channel = self._channels[data['channel']] channel._update(is_archived=False) self._broadcast_event(events.Channel.UnArchived, channel=channel) def _handle_channel_joined(self, data): channel_id = data['channel']['id'] if channel_id in self._channels: channel = self._channels[channel_id] channel._update(**data['channel']) self._channels.add(channel) else: channel = self.SlackChannel(data['channel'], self) self._channels.add(channel) self._broadcast_event(events.Channel.Created, channel=channel) self._broadcast_event(events.Channel.Joined, channel=channel) def _process_team_join(self, data): user = self.SlackUser(data['user']) self._users.add(user) self._broadcast_event(events.Team.Joined, user=user) def _parse_login_data(self, login_data): import pprint pprint.pprint(login_data) self._users.clear() self._channels.clear() self._dms.clear() self._outgoing_messages.clear() for user in login_data['users']: self._users.add(self.SlackUser(user)) for group in login_data['groups']: self._groups.add(self.SlackGroup(group, self)) for dm in login_data['ims']: self._dms.add(self.SlackDirectMessage(dm, self)) for channel in login_data['channels']: self._channels.add(self.SlackChannel(channel, self)) def _process_post_method_hooks(self, method, kwargs, data): if data['ok']: if method == 'channels.setTopic': channel = self._channels[kwargs['channel']] channel._update(**data) return data def _broadcast_event(self, event, **kwargs): pass def send_message(self, channel, message): if not isinstance(channel, SlackAdapter._SlackChannelBase) and \ not isinstance(channel, SlackAdapter._SlackGroupBase): channel = self._channels.find(channel) if not channel: raise RuntimeError("Channel with name or ID of %s not found." % channel) message = SlackAdapter.MutableOutgoingMessage(self, channel, message) logging.debug("Sending message %r", message) self._server.send_to_websocket(message.serialize()) self._outgoing_messages[message.id] = message return message def send_messages(self, channel, *messages): for message in messages: self.send_message(channel, message) def send_attachment(self, channel, *attachments): if not isinstance(channel, SlackAdapter._SlackChannelBase): channel = self._channels.find(channel) if not channel: raise RuntimeError("Channel with name or ID of %s not found." % channel) args = { 'type': 'message', 'channel': channel.id, 'attachments': [a.serialize() for a in attachments] } for a in attachments: if not a.has_message_overrides: continue for k, v in a.message_overrides.items(): args[k] = v self._server.send_to_websocket(args) def _generate_message_id(self): self._last_id += 1 return self._last_id def _get_channel_group_or_dm(self, id): if id.startswith('D'): return self._get_dm(id) elif id.startswith('G'): return self._get_group(id) else: return self._get_channel(id) def _get_dm(self, id): if id not in self._dms: self._refresh_dms() return self._dms[id] def _refresh_dms(self): dms = self.api.im.list() for dm in dms['ims']: self._dms.add(self.SlackDirectMessage(dm, self)) def _get_group(self, id): if id not in self._groups: self._refresh_groups() return self._groups[id] def _refresh_groups(self): groups = self.api.groups.list() for group in groups['groups']: self._groups.add(self.SlackDirectMessage(group, self)) def _get_channel(self, id): if id not in self._channels: self._refresh_channels() return self._channels[id] def _refresh_channels(self): channels = self.api.channels.list() for channel in channels['channels']: self._channels.add(self.SlackDirectMessage(channel, self)) def _get_user(self, id): if id not in self._users: user = self.api.user.info(user=id) if not user['ok']: return None self._users.add(self.SlackUser(user['user'])) return self._users[id]
class SlackClient(object): ''' The SlackClient makes API Calls to the `Slack Web API <https://api.slack.com/web>`_ as well as managing connections to the `Real-time Messaging API via websocket <https://api.slack.com/rtm>`_ It also manages some of the Client state for Channels that the associated token (User or Bot) is associated with. For more information, check out the `Slack API Docs <https://api.slack.com/>`_ Init: :Args: token (str): Your Slack Authentication token. You can find or generate a test token `here <https://api.slack.com/docs/oauth-test-tokens>`_ Note: Be `careful with your token <https://api.slack.com/docs/oauth-safety>`_ proxies (dict): Proxies to use when create websocket or api calls, declare http and websocket proxies using {'http': 'http://127.0.0.1'}, and https proxy using {'https': 'https://127.0.0.1:443'} ''' def __init__(self, token, proxies=None): self.token = token self.server = Server(self.token, False, proxies) def append_user_agent(self, name, version): self.server.append_user_agent(name, version) def rtm_connect(self): ''' Connects to the RTM Websocket :Args: None :Returns: False on exceptions ''' try: self.server.rtm_connect() return True except: return False def api_call(self, method, timeout=None, **kwargs): ''' Call the Slack Web API as documented here: https://api.slack.com/web :Args: method (str): The API Method to call. See `the full list here <https://api.slack.com/methods>`_ :Kwargs: (optional) kwargs: any arguments passed here will be bundled and sent to the api requester as post_data and will be passed along to the API. Example:: sc.server.api_call( "channels.setPurpose", channel="CABC12345", purpose="Writing some code!" ) :Returns: str -- returns the text of the HTTP response. Examples:: u'{"ok":true,"purpose":"Testing bots"}' or u'{"ok":false,"error":"channel_not_found"}' See here for more information on responses: https://api.slack.com/web ''' result = json.loads(self.server.api_call(method, timeout=timeout, **kwargs)) if self.server: if method == 'im.open': if "ok" in result and result["ok"]: self.server.attach_channel(kwargs["user"], result["channel"]["id"]) elif method in ('mpim.open', 'groups.create', 'groups.createchild'): if "ok" in result and result["ok"]: self.server.attach_channel( result['group']['name'], result['group']['id'], result['group']['members'] ) elif method in ('channels.create', 'channels.join'): if 'ok' in result and result['ok']: self.server.attach_channel( result['channel']['name'], result['channel']['id'], result['channel']['members'] ) return result def rtm_read(self): ''' Reads from the RTM Websocket stream then calls `self.process_changes(item)` for each line in the returned data. Multiple events may be returned, always returns a list [], which is empty if there are no incoming messages. :Args: None :Returns: data (json) - The server response. For example:: [{u'presence': u'active', u'type': u'presence_change', u'user': u'UABC1234'}] :Raises: SlackNotConnected if self.server is not defined. ''' # in the future, this should handle some events internally i.e. channel # creation if self.server: json_data = self.server.websocket_safe_read() data = [] if json_data != '': for d in json_data.split('\n'): data.append(json.loads(d)) for item in data: self.process_changes(item) return data else: raise SlackNotConnected def rtm_send_message(self, channel, message, thread=None, reply_broadcast=None): ''' Sends a message to a given channel. :Args: channel (str) - the string identifier for a channel or channel name (e.g. 'C1234ABC', 'bot-test' or '#bot-test') message (message) - the string you'd like to send to the channel thread (str or None) - the parent message ID, if sending to a thread reply_broadcast (bool) - if messaging a thread, whether to also send the message back to the channel :Returns: None ''' return self.server.channels.find(channel).send_message( message, thread, reply_broadcast, ) def process_changes(self, data): ''' Internal method which processes RTM events and modifies the local data store accordingly. Stores new channels when joining a group (Multi-party DM), IM (DM) or channel. Stores user data on a team join event. ''' if "type" in data.keys(): if data["type"] in ('channel_created', 'group_joined'): channel = data["channel"] self.server.attach_channel(channel["name"], channel["id"], []) if data["type"] == 'im_created': channel = data["channel"] self.server.attach_channel(channel["user"], channel["id"], []) if data["type"] == "team_join": user = data["user"] self.server.parse_user_data([user]) pass
class SlackClient(object): def __init__(self, token): self.token = token self.server = Server(self.token, False) def rtm_connect(self): try: self.server.rtm_connect() return True except: return False def api_call(self, method, **kwargs): result = json.loads(self.server.api_call(method, **kwargs)) if self.server: if method == 'im.open': if "ok" in result and result["ok"]: self.server.attach_channel(kwargs["user"], result["channel"]["id"]) elif method in ('mpim.open', 'groups.create', 'groups.createchild'): if "ok" in result and result["ok"]: self.server.attach_channel( result['group']['name'], result['group']['id'], result['group']['members'] ) elif method in ('channels.create', 'channels.join'): if 'ok' in result and result['ok']: self.server.attach_channel( result['channel']['name'], result['channel']['id'], result['channel']['members'] ) return result def rtm_read(self): # in the future, this should handle some events internally i.e. channel # creation if self.server: for item in self.server.websocket_safe_read(): data = json.loads(item) yield data if item: self.process_changes(data) else: raise SlackNotConnected def rtm_send_message(self, channel, message): return self.server.channels.find(channel).send_message(message) def process_changes(self, data): if "type" in data.keys(): if data["type"] in ('channel_created', 'group_joined'): channel = data["channel"] self.server.attach_channel(channel["name"], channel["id"], []) if data["type"] == 'im_created': channel = data["channel"] self.server.attach_channel(channel["user"], channel["id"], []) if data["type"] == "team_join": user = data["user"] self.server.parse_user_data([user]) pass