Beispiel #1
0
    def __init__(self,
                 name,
                 password=None,
                 guest_limit=None,
                 admin_list=None,
                 is_public=False):
        super().__init__()

        self.name = name
        self.id = slugify(name)
        self.clients = {}
        self.password_hash = None if password is None else generate_password_hash(
            password)
        self.guest_limit = guest_limit
        self.admin_list = admin_list if admin_list is not None else []
        self.is_public = is_public
        self._last_active = time_ms()

        async def check_expire():
            now = time_ms() / 1000
            last_active = self.last_active / 1000

            if now - last_active > self._reap_timeout:
                logging.info('Room %s expired', self.id)
                self.emit('expire')
            else:
                new_timeout = last_active + self._reap_timeout - now
                self._timer = MTimer(new_timeout, check_expire)

        self._reap_timeout = 3600
        self._timer = MTimer(self._reap_timeout, check_expire)

        logging.info('Created room %s', self.id)
Beispiel #2
0
        async def check_expire():
            now = time_ms() / 1000
            last_active = self.last_active / 1000

            if now - last_active > self._reap_timeout:
                logging.info('Room %s expired', self.id)
                self.emit('expire')
            else:
                new_timeout = last_active + self._reap_timeout - now
                self._timer = MTimer(new_timeout, check_expire)
Beispiel #3
0
        async def check_expire():
            """Check whether the room has expired.

            Rooms expire and are cleaned up after 60 minutes of inactivity.
            """

            now = time_ms() / 1000
            last_active = self.last_active / 1000

            if now - last_active > self._reap_timeout:
                logging.info('Room %s expired', self.id)
                self.emit('expire')
            else:
                new_timeout = last_active + self._reap_timeout - now
                self._timer = MTimer(new_timeout, check_expire)
Beispiel #4
0
    def create_client(self, client_id=None):
        if client_id is None:
            client_id = uuid.uuid4().hex

        if client_id in self.clients:
            raise ChatException('Client {} already exists'.format(client_id))

        client = ChatClient(client_id)
        client.timer = MTimer(self._reap_timeout, self._reap, client=client)

        greeting = ChatMessage()
        greeting.sender = self._message_address
        greeting.receiver = client.id
        greeting.type = 'greeting'
        greeting.data = 'This is Ground Control to Major Tom: You\'ve really made the grade. Now it\'s time to leave the capsule if you dare.'
        client.send(greeting.json())

        @client.on("message")
        async def on_message(message):
            # Reap this client if we haven't seen it for too long
            if client.timer is not None:
                client.timer.cancel()
            client.timer = MTimer(self._reap_timeout,
                                  self._reap,
                                  client=client)

            await self._handle_message(message, client)

        return client
Beispiel #5
0
        async def on_message(message):
            # Reap this client if we haven't seen it for too long
            if client.timer is not None:
                client.timer.cancel()
            client.timer = MTimer(self._reap_timeout, self._reap, client=client)

            await self._handle_message(message, client)
Beispiel #6
0
class ChatRoom(AsyncIOEventEmitter):
    def __init__(self,
                 name,
                 password=None,
                 guest_limit=None,
                 admin_list=None,
                 is_public=False):
        super().__init__()

        self.name = name
        self.id = slugify(name)
        self.clients = {}
        self.password_hash = None if password is None else generate_password_hash(
            password)
        self.guest_limit = guest_limit
        self.admin_list = admin_list if admin_list is not None else []
        self.is_public = is_public
        self._last_active = time_ms()

        async def check_expire():
            now = time_ms() / 1000
            last_active = self.last_active / 1000

            if now - last_active > self._reap_timeout:
                logging.info('Room %s expired', self.id)
                self.emit('expire')
            else:
                new_timeout = last_active + self._reap_timeout - now
                self._timer = MTimer(new_timeout, check_expire)

        self._reap_timeout = 3600
        self._timer = MTimer(self._reap_timeout, check_expire)

        logging.info('Created room %s', self.id)

    @property
    def last_active(self):
        last_seen = [client.last_seen for client in self.clients.values()]
        self._last_active = max([self._last_active, *last_seen])
        return self._last_active

    @property
    def active_ago(self):
        return int((time_ms() - self.last_active) / 60000)

    @property
    def info(self):
        clients = [{
            'id': client.id,
            'username': client.username
        } for client in self.get_clients()]

        return {'room_id': self.id, 'clients': clients}

    def authenticate(self, password=None):
        if password is None:
            return self.password_hash is None

        return check_password_hash(self.password_hash, password)

    def is_full(self):
        return self.guest_limit is not None and len(
            self.clients) == self.guest_limit

    def add_client(self, client):
        if self.is_full():
            raise ChatException('Guest limit already reached')

        self.clients[client.id] = client
        client.room = self

    def remove_client(self, client):
        logging.info('Removing client {} from room {}'.format(
            client.id, self.id))
        self._last_active = max(self._last_active, client.last_seen)
        client.room = None
        self.clients.pop(client.id, None)
        logging.info('{} clients remaining in room {}'.format(
            len(self.clients), self.id))

    def get_clients(self):
        return self.clients.values()

    def broadcast(self, message):
        for client in self.get_clients():
            message.receiver = client.id
            client.send(message.json())

    async def shutdown(self):
        if self._timer is not None:
            self._timer.cancel()
            self._timer = None

        for client in self.clients.values():
            self.remove_client(client)
            await client.shutdown()
Beispiel #7
0
class ChatRoom(AsyncIOEventEmitter):
    """
    A class that tracks information for a specific room, including connected
    clients and room settings.
    """
    def __init__(self,
                 name,
                 password=None,
                 guest_limit=None,
                 admin_list=None,
                 is_public=False):
        super().__init__()

        self.name = name
        self.id = slugify(name)
        self.clients = {}
        self.password_hash = None if password is None else generate_password_hash(
            password)
        self.guest_limit = guest_limit
        self.admin_list = admin_list if admin_list is not None else []
        self.is_public = is_public
        self._last_active = time_ms()

        async def check_expire():
            """Check whether the room has expired.

            Rooms expire and are cleaned up after 60 minutes of inactivity.
            """

            now = time_ms() / 1000
            last_active = self.last_active / 1000

            if now - last_active > self._reap_timeout:
                logging.info('Room %s expired', self.id)
                self.emit('expire')
            else:
                new_timeout = last_active + self._reap_timeout - now
                self._timer = MTimer(new_timeout, check_expire)

        self._reap_timeout = 3600
        self._timer = MTimer(self._reap_timeout, check_expire)

        logging.info('Created room %s', self.id)

    @property
    def last_active(self):
        """A timestamp corresponding to when the room was last active."""

        last_seen = [client.last_seen for client in self.clients.values()]
        self._last_active = max([self._last_active, *last_seen])
        return self._last_active

    @property
    def active_ago(self):
        """The number of minutes ago that the room was last active."""
        return int((time_ms() - self.last_active) / 60000)

    @property
    def info(self):
        """
        Information about the room, consisting of the room ID and a list of
        connected clients.
        """

        clients = [{
            'id': client.id,
            'username': client.username
        } for client in self.get_clients()]

        return {'room_id': self.id, 'clients': clients}

    def authenticate(self, password=None):
        """Attempt to authenticate access to the room."""

        if password is None:
            return self.password_hash is None

        return check_password_hash(self.password_hash, password)

    def is_full(self):
        """Check whether the room's guest limit has been reached.

        Returns True if the guest limit has been reached, False otherwise.
        """

        return self.guest_limit is not None and len(
            self.clients) == self.guest_limit

    def add_client(self, client):
        """Add a client to the room.

        Raises a ChatException if the room is already full.
        """

        if self.is_full():
            raise ChatException('Guest limit already reached')

        self.clients[client.id] = client
        client.room = self

    def remove_client(self, client):
        """Remove a client from the room."""

        logging.info('Removing client {} from room {}'.format(
            client.id, self.id))
        self._last_active = max(self._last_active, client.last_seen)
        client.room = None
        self.clients.pop(client.id, None)
        logging.info('{} clients remaining in room {}'.format(
            len(self.clients), self.id))

    def get_clients(self):
        """Get the clients connected to the room."""
        return self.clients.values()

    def broadcast(self, message):
        """Send a message to all clients connected to the room."""

        for client in self.get_clients():
            message.receiver = client.id
            client.send(message.json())

    async def shutdown(self):
        """Shut down the room."""

        if self._timer is not None:
            self._timer.cancel()
            self._timer = None

        for client in self.clients.values():
            self.remove_client(client)
            await client.shutdown()