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