def __init__(self, token, connect=True): self.token = token self.username = None self.domain = None self.login_data = None self.websocket = None self.users = SearchList() self.channels = SearchList() self.connected = False self.pingcounter = 0 self.api_requester = SlackRequest() if connect: self.rtm_connect()
class Server(object): def __init__(self, token, connect=True): self.token = token self.username = None self.domain = None self.login_data = None self.websocket = None self.users = SearchList() self.channels = SearchList() self.connected = False self.pingcounter = 0 self.api_requester = SlackRequest() if connect: self.rtm_connect() def __eq__(self, compare_str): if compare_str == self.domain or compare_str == self.token: return True else: return False def __str__(self): data = "" for key in list(self.__dict__.keys()): data += "{} : {}\n".format(key, str(self.__dict__[key])[:40]) return data def __repr__(self): return self.__str__() @asyncio.coroutine def rtm_connect(self, reconnect=False): reply = yield from self.api_requester.do(self.token, "rtm.start") if reply.code != 200: raise SlackConnectionError else: login_data = json.loads(reply.read().decode('utf-8')) if login_data["ok"]: self.ws_url = login_data['url'] if not reconnect: self.parse_slack_login_data(login_data) yield from self.connect_slack_websocket(self.ws_url) else: raise SlackLoginError def parse_slack_login_data(self, login_data): self.login_data = login_data self.domain = self.login_data["team"]["domain"] self.username = self.login_data["self"]["name"] self.parse_channel_data(login_data["channels"]) self.parse_channel_data(login_data["groups"]) self.parse_channel_data(login_data["ims"]) self.parse_user_data(login_data["users"]) @asyncio.coroutine def connect_slack_websocket(self, ws_url): try: self.websocket = yield from websockets.connect(ws_url) except: raise SlackConnectionError def parse_channel_data(self, channel_data): for channel in channel_data: if "name" not in channel: channel["name"] = channel["id"] if "members" not in channel: channel["members"] = [] self.attach_channel(channel["name"], channel["id"], channel["members"]) def parse_user_data(self, user_data): for user in user_data: if "tz" not in user: user["tz"] = "unknown" if "real_name" not in user: user["real_name"] = user["name"] self.attach_user(user["name"], user["id"], user["real_name"], user["tz"]) @asyncio.coroutine def send_to_websocket(self, data): """Send (data) directly to the websocket.""" try: data = json.dumps(data) yield from self.websocket.send(data) except: yield from self.rtm_connect(reconnect=True) def ping(self): res = yield from self.send_to_websocket({"type": "ping"}) return res @asyncio.coroutine def websocket_safe_read(self): """ Returns data if available, otherwise ''. Newlines indicate multiple messages """ data = "" while True: try: raw_data = yield from self.websocket.recv() data += "{}\n".format(raw_data) except SSLError as e: if e.errno == 2: # errno 2 occurs when trying to read or write data, but more # data needs to be received on the underlying TCP transport # before the request can be fulfilled. # # Python 2.7.9+ and Python 3.3+ give this its own exception, # SSLWantReadError return '' raise return data.rstrip() def attach_user(self, name, id, real_name, tz): if self.users.find(id) is None: self.users.append(User(self, name, id, real_name, tz)) def attach_channel(self, name, id, members=[]): if self.channels.find(id) is None: self.channels.append(Channel(self, name, id, members)) def join_channel(self, name): res = yield from self.api_requester.do(self.token, "channels.join?name={}".format(name)) print(res.read()) @asyncio.coroutine def api_call(self, method, **kwargs): reply = yield from self.api_requester.do(self.token, method, kwargs) return reply.read()