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()