Exemple #1
0
    def __init__(self):
        """
        Defines dictionary attibutes sorted by room_id
        For each room:
        - new_message_events contains gevent.Event objects used by message
          handlers to pause/restart execution and implement long polling
        - messages stores the queue of the latest 50 messages
        - counters contains iterators to pick up message identifiers
        - connected_users is a dictionary holding the usernames of connected
          users sorted by the time of their latest request
        - new_connected_user_event contains gevent.Event objects used
          by self.notify_users_list and self.get_users_list methods to
          implement long polling

        """
        self.handler = MessageHandlerFactory()
        self.new_message_events = {}
        self.messages = {}
        self.counters = {}
        self.connected_users = {}
        self.new_connected_user_event = {}
        rooms = Room.objects.all()
        for room in rooms:
            self.new_message_events[room.id] = Event()
            self.messages[room.id] = deque(maxlen=50)
            self.counters[room.id] = itertools.count(1)
            self.connected_users[room.id] = {}
            self.new_connected_user_event[room.id] = Event()
Exemple #2
0
    def __init__(self):
        """
        Defines dictionary attibutes sorted by room_id
        For each room:
        - new_message_events contains gevent.Event objects used by message
          handlers to pause/restart execution and implement long polling
        - messages stores the queue of the latest 50 messages
        - counters contains iterators to pick up message identifiers
        - connected_users is a dictionary holding the usernames of connected
          users sorted by the time of their latest request
        - new_connected_user_event contains gevent.Event objects used
          by self.notify_users_list and self.get_users_list methods to
          implement long polling

        """
        self.handler = MessageHandlerFactory()
        self.new_message_events = {}
        self.messages = {}
        self.counters = {}
        self.connected_users = {}
        self.new_connected_user_event = {}
        rooms = Room.objects.all()
        for room in rooms:
            self.new_message_events[room.id] = Event()
            self.messages[room.id] = deque(maxlen=50)
            self.counters[room.id] = itertools.count(1)
            self.connected_users[room.id] = {}
            self.new_connected_user_event[room.id] = Event()
Exemple #3
0
class ChatView(object):
    """Returns a singleton of ChatView
    Methods dispatch all the ajax requests from chat

    """
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            self = super(ChatView, cls).__new__(cls, *args, **kwargs)
            ChatView.__init__(self, *args, **kwargs)
            cls._instance = self
        return cls._instance

    def __init__(self):
        """
        Defines dictionary attibutes sorted by room_id
        For each room:
        - new_message_events contains gevent.Event objects used by message
          handlers to pause/restart execution and implement long polling
        - messages stores the queue of the latest 50 messages
        - counters contains iterators to pick up message identifiers
        - connected_users is a dictionary holding the usernames of connected
          users sorted by the time of their latest request
        - new_connected_user_event contains gevent.Event objects used
          by self.notify_users_list and self.get_users_list methods to
          implement long polling

        """
        self.handler = MessageHandlerFactory()
        self.new_message_events = {}
        self.messages = {}
        self.counters = {}
        self.connected_users = {}
        self.new_connected_user_event = {}
        rooms = Room.objects.all()
        for room in rooms:
            self.new_message_events[room.id] = Event()
            self.messages[room.id] = deque(maxlen=50)
            self.counters[room.id] = itertools.count(1)
            self.connected_users[room.id] = {}
            self.new_connected_user_event[room.id] = Event()

    def get_username(self, request):
        """Returns username if user is authenticated, guest name otherwise """
        if request.user.is_authenticated():
            username = request.user.username
        else:
            guestname = request.session.get('guest_name')
            username = '******' % guestname
        return username

    def signal_new_message_event(self, room_id):
        """Signals new_message_event given a room_id """
        self.new_message_events[room_id].set()
        self.new_message_events[room_id].clear()

    def wait_for_new_message(self, room_id, timeout=TIMEOUT):
        """Waits for new_message_event given a room_id """
        self.new_message_events[room_id].wait(timeout)

    def get_messages_queue(self, room_id):
        """Returns the message queue given a room_id """
        return self.messages[room_id]

    def get_next_message_id(self, room_id):
        """Returns the next message identifier given a room_id """
        return self.counters[room_id].next()

    def get_connected_users(self, room_id):
        """Returns the connected users given a room_id"""
        return self.connected_users[room_id]

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def get_messages(self, request):
        """Handles ajax requests for messages
        Requests must contain room_id and latest_id
        Delegates MessageHandler.retrieve_message method to return the list
        of messages

        """
        try:
            room_id = int(request.GET['room_id'])
            latest_msg_id = int(request.GET['latest_message_id'])
        except:
            return HttpResponseBadRequest(
            "Parameters missing or bad parameters. "
            "Expected a GET request with 'room_id' and 'latest_message_id' "
            "parameters")

        messages = self.handler.retrieve_messages(
                        self, room_id, latest_msg_id)

        to_jsonify = [
            {"message_id": msg_id,
             "username": message.username,
             "date": message.date.strftime(TIME_FORMAT),
             "content": message.content}
            for msg_id, message in messages
            if msg_id > latest_msg_id
        ]
        return HttpResponse(json.dumps(to_jsonify),
                            mimetype="application/json")

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def send_message(self, request):
        """Gets room_id and message from request and sends a
        chat_message_received signal

        """
        try:
            room_id = int(request.POST['room_id'])
            message = request.POST['message']
            date = datetime.now()
        except:
            return HttpResponseBadRequest(
            "Parameters missing or bad parameters"
            "Expected a POST request with 'room_id' and 'message' parameters")
        user = request.user
        username = self.get_username(request)
        chat_message_received.send(
            sender=self,
            room_id=room_id,
            username=username,
            message=message,
            date=date,
            user=user if user.is_authenticated() else None)

        return HttpResponse(json.dumps({
                 'timestamp': date.strftime(TIME_FORMAT), }
        ))

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def notify_users_list(self, request):
        """Updates user time into connected users dictionary """
        try:
            room_id = int(request.POST['room_id'])
        except:
            return HttpResponseBadRequest(
            "Parameters missing or bad parameters"
            "Expected a POST request with 'room_id'")
        username = self.get_username(request)
        date = datetime.today()
        self.connected_users[room_id].update({username: date})
        self.new_connected_user_event[room_id].set()
        self.new_connected_user_event[room_id].clear()
        return HttpResponse('Connected')

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def get_users_list(self, request):
        """Dumps the list of connected users """
        REFRESH_TIME = 8
        try:
            room_id = int(request.GET['room_id'])
        except:
            return HttpResponseBadRequest(
            "Parameters missing or bad parameters"
            "Expected a POST request with 'room_id'")
        username = self.get_username(request)
        self.connected_users[room_id].update({
                                username: datetime.today()
                            })
        self.new_connected_user_event[room_id].wait(REFRESH_TIME)

        # clean connected_users dictionary of disconnected users
        self._clean_connected_users(room_id)
        json_users = [
            {"username": _user,
             "date": _date.strftime(TIME_FORMAT)}
            for _user, _date in self.connected_users[room_id].iteritems()
        ]
        json_response = {
            "now": datetime.today().strftime(TIME_FORMAT),
            "users": json_users,
            "refresh": str(REFRESH_TIME),
        }
        return HttpResponse(json.dumps(json_response),
                            mimetype='application/json')

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def get_latest_message_id(self, request):
        """Dumps the id of the latest message sent """
        try:
            room_id = int(request.GET['room_id'])
        except:
            return HttpResponseBadRequest()
        latest_msg_id = self.handler.get_latest_message_id(self, room_id)
        response = {"id": latest_msg_id}
        return HttpResponse(json.dumps(response), mimetype="application/json")

    def _clean_connected_users(self, room_id, seconds=60):
        """Remove from connected users dictionary users not seen
        for seconds

        """
        now = datetime.today()
        for usr, date in self.connected_users[room_id].items():
            if (now - timedelta(seconds=seconds)) > date:
                self.connected_users[room_id].pop(usr)
from utils.handlers import MessageHandlerFactory
from django.dispatch import Signal

chat_message_received = Signal(providing_args=[
    "room_id",
    "username",
    "message",
    "date",
])

handler = MessageHandlerFactory()

chat_message_received.connect(handler.handle_received_message)
Exemple #5
0
class ChatView(object):
    """Returns a singleton of ChatView
    Methods dispatch all the ajax requests from chat

    """
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            self = super(ChatView, cls).__new__(cls, *args, **kwargs)
            ChatView.__init__(self, *args, **kwargs)
            cls._instance = self
        return cls._instance

    def __init__(self):
        """
        Defines dictionary attibutes sorted by room_id
        For each room:
        - new_message_events contains gevent.Event objects used by message
          handlers to pause/restart execution and implement long polling
        - messages stores the queue of the latest 50 messages
        - counters contains iterators to pick up message identifiers
        - connected_users is a dictionary holding the usernames of connected
          users sorted by the time of their latest request
        - new_connected_user_event contains gevent.Event objects used
          by self.notify_users_list and self.get_users_list methods to
          implement long polling

        """
        self.handler = MessageHandlerFactory()
        self.new_message_events = {}
        self.messages = {}
        self.counters = {}
        self.connected_users = {}
        self.new_connected_user_event = {}
        rooms = Room.objects.all()
        for room in rooms:
            self.new_message_events[room.id] = Event()
            self.messages[room.id] = deque(maxlen=50)
            self.counters[room.id] = itertools.count(1)
            self.connected_users[room.id] = {}
            self.new_connected_user_event[room.id] = Event()

    def get_username(self, request):
        """Returns username if user is authenticated, guest name otherwise """
        if request.user.is_authenticated():
            username = request.user.username
        else:
            guestname = request.session.get('guest_name')
            username = '******' % guestname
        return username

    def signal_new_message_event(self, room_id):
        """Signals new_message_event given a room_id """
        self.new_message_events[room_id].set()
        self.new_message_events[room_id].clear()

    def wait_for_new_message(self, room_id, timeout=TIMEOUT):
        """Waits for new_message_event given a room_id """
        self.new_message_events[room_id].wait(timeout)

    def get_messages_queue(self, room_id):
        """Returns the message queue given a room_id """
        return self.messages[room_id]

    def get_next_message_id(self, room_id):
        """Returns the next message identifier given a room_id """
        return self.counters[room_id].next()

    def get_connected_users(self, room_id):
        """Returns the connected users given a room_id"""
        return self.connected_users[room_id]

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def get_messages(self, request):
        """Handles ajax requests for messages
        Requests must contain room_id and latest_id
        Delegates MessageHandler.retrieve_message method to return the list
        of messages

        """
        try:
            room_id = int(request.GET['room_id'])
            latest_msg_id = int(request.GET['latest_message_id'])
        except:
            return HttpResponseBadRequest(
                "Parameters missing or bad parameters. "
                "Expected a GET request with 'room_id' and 'latest_message_id' "
                "parameters")

        messages = self.handler.retrieve_messages(self, room_id, latest_msg_id)

        to_jsonify = [{
            "message_id": msg_id,
            "username": message.username,
            "date": message.date.strftime(TIME_FORMAT),
            "content": message.content
        } for msg_id, message in messages if msg_id > latest_msg_id]
        return HttpResponse(json.dumps(to_jsonify),
                            mimetype="application/json")

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def send_message(self, request):
        """Gets room_id and message from request and sends a
        chat_message_received signal

        """
        try:
            room_id = int(request.POST['room_id'])
            message = request.POST['message']
            date = datetime.now()
        except:
            return HttpResponseBadRequest(
                "Parameters missing or bad parameters"
                "Expected a POST request with 'room_id' and 'message' parameters"
            )
        user = request.user
        username = self.get_username(request)
        chat_message_received.send(
            sender=self,
            room_id=room_id,
            username=username,
            message=message,
            date=date,
            user=user if user.is_authenticated() else None)

        return HttpResponse(
            json.dumps({
                'timestamp': date.strftime(TIME_FORMAT),
            }))

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def notify_users_list(self, request):
        """Updates user time into connected users dictionary """
        try:
            room_id = int(request.POST['room_id'])
        except:
            return HttpResponseBadRequest(
                "Parameters missing or bad parameters"
                "Expected a POST request with 'room_id'")
        username = self.get_username(request)
        date = datetime.today()
        self.connected_users[room_id].update({username: date})
        self.new_connected_user_event[room_id].set()
        self.new_connected_user_event[room_id].clear()
        return HttpResponse('Connected')

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def get_users_list(self, request):
        """Dumps the list of connected users """
        REFRESH_TIME = 8
        try:
            room_id = int(request.GET['room_id'])
        except:
            return HttpResponseBadRequest(
                "Parameters missing or bad parameters"
                "Expected a POST request with 'room_id'")
        username = self.get_username(request)
        self.connected_users[room_id].update({username: datetime.today()})
        self.new_connected_user_event[room_id].wait(REFRESH_TIME)

        # clean connected_users dictionary of disconnected users
        self._clean_connected_users(room_id)
        json_users = [{
            "username": _user,
            "date": _date.strftime(TIME_FORMAT)
        } for _user, _date in self.connected_users[room_id].iteritems()]
        json_response = {
            "now": datetime.today().strftime(TIME_FORMAT),
            "users": json_users,
            "refresh": str(REFRESH_TIME),
        }
        return HttpResponse(json.dumps(json_response),
                            mimetype='application/json')

    @method_decorator(ajax_room_login_required)
    @method_decorator(ajax_user_passes_test_or_403(check_user_passes_test))
    def get_latest_message_id(self, request):
        """Dumps the id of the latest message sent """
        try:
            room_id = int(request.GET['room_id'])
        except:
            return HttpResponseBadRequest()
        latest_msg_id = self.handler.get_latest_message_id(self, room_id)
        response = {"id": latest_msg_id}
        return HttpResponse(json.dumps(response), mimetype="application/json")

    def _clean_connected_users(self, room_id, seconds=60):
        """Remove from connected users dictionary users not seen
        for seconds

        """
        now = datetime.today()
        for usr, date in self.connected_users[room_id].items():
            if (now - timedelta(seconds=seconds)) > date:
                self.connected_users[room_id].pop(usr)