def get_room_or_error(room_id, user):
    """
    Tries to fetch a room for the user, checking permissions along the way.
    """
    # Check if the user is logged in
    # if not user.is_authenticated:
    #     raise ClientError("USER_HAS_TO_LOGIN", "You must login.")
    # Find the room they requested (by ID)
    try:
        room = PrivateChatRoom.objects.get(pk=room_id)
    except PrivateChatRoom.DoesNotExist:
        raise ClientError("ROOM_INVALID", "Invalid room.")
    # Check permissions

    # Is this user allowed in the room? (must be user1 or user2)
    if user != room.user1 and user != room.user2:
        raise ClientError("ROOM_ACCESS_DENIED",
                          "You do not have permission to join this room.")

    # Are the users in this room friends?
    friend_list = FriendList.objects.get(user=user).friends.all()
    if not room.user1 in friend_list:
        if not room.user2 in friend_list:
            raise ClientError("ROOM_ACCESS_DENIED",
                              "You must be friends to chat.")
    return room
    async def receive_json(self, content):
        """
        Called when we get a text frame. Channels will JSON-decode the payload
        for us and pass it as the first argument.
        """
        # Messages will have a "command" key we can switch on
        print("ChatConsumer: receive_json")
        command = content.get("command", None)
        try:
            if command == "join":
                # Make them join the room
                await self.join_room(content["room"])

            elif command == "leave":
                # Leave the room
                await self.leave_room(content["room"])

            elif command == "send":
                if len(content["message"].lstrip()) == 0:
                    raise ClientError(422, "You can't send an empty message.")
                await self.send_room(content["room"], content["message"])

            elif command == "get_room_chat_messages":
                await self.display_progress_bar(True)
                room = await get_room_or_error(content['room_id'],
                                               self.scope["user"])
                payload = await get_room_chat_messages(room,
                                                       content['page_number'])
                if payload != None:
                    payload = json.loads(payload)
                    await self.send_messages_payload(
                        payload['messages'], payload['new_page_number'])
                else:
                    raise ClientError(
                        204,
                        "Something went wrong retrieving the chatroom messages."
                    )
                await self.display_progress_bar(False)

            elif command == "get_user_info":
                room = await get_room_or_error(content['room_id'],
                                               self.scope["user"])
                payload = get_user_info(room, self.scope["user"])
                if payload != None:
                    payload = json.loads(payload)
                    await self.send_user_info_payload(payload['user_info'])
                else:
                    raise ClientError(
                        204,
                        "Something went wrong retrieving the other users account details."
                    )

        except ClientError as e:
            await self.display_progress_bar(False)
            # Catch any errors and send it back
            errorData = {}
            errorData['error'] = e.code
            if e.message:
                errorData['message'] = e.message
            await self.send_json(errorData)
Exemplo n.º 3
0
    async def send_room(self, room_id, message):
        """
        Called by receive_json when someone sends a message to a room.
        """
        print("ChatConsumer: send_room")

        # Check they are in this room
        if self.room_id != None:
            if str(room_id) != str(self.room_id):
                raise ClientError("ROOM_ACCESS_DENIED", "Room access denied")
        else:
            raise ClientError("ROOM_ACCESS_DENIED", "Room access denied")
        
        # Get the room and send to the group about it
        room = await get_room_or_error(room_id, self.scope["user"])

        # get list of connected_users
        connected_users = room.connected_users.all()

        # Execute these functions asychronously
        await asyncio.gather(*[
            append_unread_msg_if_not_connected(room, room.user1, connected_users, message), 
            append_unread_msg_if_not_connected(room, room.user2, connected_users, message),
            create_room_chat_message(room, self.scope["user"], message)
        ])
        await self.channel_layer.group_send(
            room.group_name,
            {
                "type": "chat.message",
                "profile_image": self.scope["user"].profile_image.url,
                "username": self.scope["user"].username,
                "user_id": self.scope["user"].id,
                "message": message,
            }
        )
Exemplo n.º 4
0
    async def send_room(self, room_id, message):
        """
        Called by receive_json when someone sends a message to a room.
        """
        # Check they are in this room
        print("PublicChatConsumer: send_room")
        if self.room_id != None:
            if str(room_id) != str(self.room_id):
                raise ClientError("ROOM_ACCESS_DENIED", "Room access denied")
            if not is_authenticated(self.scope["user"]):
                raise ClientError("AUTH_ERROR",
                                  "You must be authenticated to chat.")
        else:
            raise ClientError("ROOM_ACCESS_DENIED", "Room access denied")

        # Get the room and send to the group about it
        room = await get_room_or_error(room_id)

        await create_public_room_chat_message(room, self.scope["user"],
                                              message)
        await self.channel_layer.group_send(
            room.group_name, {
                "type": "chat.message",
                "profile_image": self.scope["user"].profile_image.url,
                "username": self.scope["user"].username,
                "user_id": self.scope["user"].id,
                "message": message,
            })
Exemplo n.º 5
0
def get_treatment_or_error(treatment_id, user):
    if not user.is_authenticated:
        raise ClientError("USER_HAS_TO_LOGIN")
    try:
        treatment = Treatment.objects.get(id=treatment_id)
    except Treatment.DoesNotExist:
        raise ClientError("TREATMENT_INVALID")

    has_perm = user.is_superuser or user.has_perm('monitor.offer_treatment')
    if not has_perm:
        raise ClientError("TREATMENT_ACCESS_DENIED")

    return treatment
Exemplo n.º 6
0
def _treatment_follow(message, treatment):
    if treatment.is_closed or treatment.user is None:
        raise ClientError("TREATMENT_ACCESS_DENIED")

    if not has_permission_to_user(message.user, treatment.user.id):
        raise ClientError("TREATMENT_ACCESS_DENIED")

    if treatment.id not in message.channel_session['treatments']:
        treatment.websocket_group.add(message.reply_channel)
        message.channel_session['treatments'].append(treatment.id)

    message.reply_channel.send({"text": json.dumps({"action": "following", "volunteer": treatment.user.first_name})})
    _send_treatment_messages(message.reply_channel, treatment)
Exemplo n.º 7
0
def new_message(room_id, user, message):
    """
    Add new message to db.
    """
    # Check if the user is logged in
    if not user.is_authenticated:
        raise ClientError("USER_HAS_TO_LOGIN")
    try:
        #add message to log
        msg_room = Room.objects.filter(pk=room_id).first()
        msg = Message(dialog=msg_room, user=user, message=message)
        msg.save()
    except:
        raise ClientError("NEW MESSAGE DB ERROR")
    return msg
Exemplo n.º 8
0
def get_room_or_error(room_id, user):
    """
    Tries to fetch a room for the user, checking permissions along the way.
    """
    # Check if the user is logged in
    if not user.is_authenticated:
        raise ClientError("USER_HAS_TO_LOGIN")
    # Find the room they requested (by ID)
    try:
        room = Room.objects.get(pk=room_id)
    except Room.DoesNotExist:
        raise ClientError("ROOM_INVALID")
    if room.user1 != user and room.user2 != user:
        raise ClientError("ROOM_NOT_FOR_YOU")
    return room
Exemplo n.º 9
0
def get_room_or_error(room_id: int, user: User):
    """
    Tries to fetch a room for the user, checking permissions along the way.
    """
    # Check if the user is logged in
    if not user.is_authenticated:
        raise ClientError("USER_HAS_TO_LOGIN")
    # Find the room they requested (by ID)
    try:
        room = Room.objects.get(pk=room_id)
    except Room.DoesNotExist:
        raise ClientError("ROOM_INVALID")
    # Check permissions
    if room.staff_only and not user.is_staff:
        raise ClientError("ROOM_ACCESS_DENIED")
    return room
Exemplo n.º 10
0
    async def send_room(self, room_id, message):
        """
        Called by receive_json when someone sends a message to a room.
        """
        # Check they are in this room
        print("ChatConsumer: send_room")
        if room_id not in self.rooms:
            raise ClientError("ROOM_ACCESS_DENIED", "Room access denied")
        # Get the room and send to the group about it
        room = await get_room_or_error(room_id, self.scope["user"])

        # get list of connected_users
        connected_users = room.connected_users.all()
        await self.append_unread_msg_if_not_connected(room, room.user1,
                                                      connected_users, message)
        await self.append_unread_msg_if_not_connected(room, room.user2,
                                                      connected_users, message)

        await self.create_room_chat_message(room, self.scope["user"], message)
        await self.channel_layer.group_send(
            room.group_name, {
                "type": "chat.message",
                "room_id": room_id,
                "profile_image": self.scope["user"].profile_image.url,
                "username": self.scope["user"].username,
                "user_id": self.scope["user"].id,
                "message": message,
            })
Exemplo n.º 11
0
def get_chat_notifications(user, page_number):
    """
	Get Chat Notifications with Pagination (next page of results).
	This is for appending to the bottom of the notifications list.
	Chat Notifications are:
	1. UnreadChatRoomMessages
	"""
    if user.is_authenticated:
        chatmessage_ct = ContentType.objects.get_for_model(
            UnreadChatRoomMessages)
        notifications = Notification.objects.filter(
            target=user, content_type=chatmessage_ct).order_by('-timestamp')
        p = Paginator(notifications, DEFAULT_NOTIFICATION_PAGE_SIZE)

        # sleep 1s for testing
        # sleep(1)
        print("PAGES: " + str(p.num_pages))
        payload = {}
        if len(notifications) > 0:
            if int(page_number) <= p.num_pages:
                s = LazyNotificationEncoder()
                serialized_notifications = s.serialize(
                    p.page(page_number).object_list)
                payload['notifications'] = serialized_notifications
                new_page_number = int(page_number) + 1
                payload['new_page_number'] = new_page_number
                return json.dumps(payload)
        else:
            return None
    else:
        raise ClientError("AUTH_ERROR",
                          "User must be authenticated to get notifications.")
    return None
Exemplo n.º 12
0
def decline_friend_request(user, notification_id):
    """
	Decline a friend request
	"""
    payload = {}
    if user.is_authenticated:
        try:
            notification = Notification.objects.get(pk=notification_id)
            friend_request = notification.content_object
            # confirm this is the correct user
            if friend_request.receiver == user:
                # accept the request and get the updated notification
                updated_notification = friend_request.decline()

                # return the notification associated with this FriendRequest
                s = LazyNotificationEncoder()
                payload['notification'] = s.serialize([updated_notification
                                                       ])[0]
                return json.dumps(payload)
        except Notification.DoesNotExist:
            raise ClientError(
                "AUTH_ERROR",
                "An error occurred with that notification. Try refreshing the browser."
            )
    return None
Exemplo n.º 13
0
def refresh_general_notifications(user, oldest_timestamp, newest_timestamp):
    """
	Retrieve the general notifications newer than the oldest one on the screen and younger than the newest one the screen.
	The result will be: Notifications currently visible will be updated
	"""
    payload = {}
    if user.is_authenticated:
        oldest_ts = oldest_timestamp[0:oldest_timestamp.find(
            "+")]  # remove timezone because who cares
        oldest_ts = datetime.strptime(oldest_ts, '%Y-%m-%d %H:%M:%S.%f')
        newest_ts = newest_timestamp[0:newest_timestamp.find(
            "+")]  # remove timezone because who cares
        newest_ts = datetime.strptime(newest_ts, '%Y-%m-%d %H:%M:%S.%f')
        friend_request_ct = ContentType.objects.get_for_model(FriendRequest)
        friend_list_ct = ContentType.objects.get_for_model(FriendList)
        notifications = Notification.objects.filter(
            target=user,
            content_type__in=[friend_request_ct, friend_list_ct],
            timestamp__gte=oldest_ts,
            timestamp__lte=newest_ts).order_by('-timestamp')

        s = LazyNotificationEncoder()
        payload['notifications'] = s.serialize(notifications)
    else:
        raise ClientError("AUTH_ERROR",
                          "User must be authenticated to get notifications.")

    return json.dumps(payload)
Exemplo n.º 14
0
def _treatment_begin(message, treatment):
    lock_id = "consumers.treatment-begin"

    acquire_lock = lambda: cache.add(lock_id, "true", LOCK_EXPIRE)
    release_lock = lambda: cache.delete(lock_id)

    if acquire_lock():
        try:
            if treatment is not None and (treatment.is_closed or (treatment.user is not None and treatment.user != message.user)):
                raise ClientError("TREATMENT_ACCESS_DENIED")

            try:
                current_treatment = Treatment.objects.get(user=message.user,is_closed=False)
            except:
                current_treatment = None

            if current_treatment:
                treatment = current_treatment
            else:
                treatment.user = message.user
                treatment.treatment_at = datetime.now()
                treatment.save()

            treatment.websocket_group.add(message.reply_channel)

            ChannelGroup("treatment-waiting").discard(message.reply_channel)

            message.channel_session['treatments'] = list(set(message.channel_session['treatments']).union([treatment.id]))
            message.reply_channel.send({"text": json.dumps({"action": "treating", "treatment": treatment.id})})

            _send_treatment_messages(message.reply_channel, treatment)
        finally:
            release_lock()
Exemplo n.º 15
0
def get_general_notifications(user, page_number):
    """
	Get General Notifications with Pagination (next page of results).
	This is for appending to the bottom of the notifications list.
	General Notifications are:
	1. FriendRequest
	2. FriendList
	"""
    if user.is_authenticated:
        friend_request_ct = ContentType.objects.get_for_model(FriendRequest)
        friend_list_ct = ContentType.objects.get_for_model(FriendList)
        notifications = Notification.objects.filter(target=user,
                                                    content_type__in=[
                                                        friend_request_ct,
                                                        friend_list_ct
                                                    ]).order_by('-timestamp')
        p = Paginator(notifications, DEFAULT_NOTIFICATION_PAGE_SIZE)

        payload = {}
        if len(notifications) > 0:
            if int(page_number) <= p.num_pages:
                s = LazyNotificationEncoder()
                serialized_notifications = s.serialize(
                    p.page(page_number).object_list)
                payload['notifications'] = serialized_notifications
                new_page_number = int(page_number) + 1
                payload['new_page_number'] = new_page_number
        else:
            return None
    else:
        raise ClientError("AUTH_ERROR",
                          "User must be authenticated to get notifications.")

    return json.dumps(payload)
Exemplo n.º 16
0
def _treatment_wake(message, treatment):
    if not (treatment.is_closed and treatment.user is None):
        raise ClientError("TREATMENT_ACCESS_DENIED")

    treatment.is_closed = False
    treatment.closed_at = None
    treatment.save()

    message.reply_channel.send({"text": json.dumps({"action": "waked"})})
Exemplo n.º 17
0
def get_room_or_error(room_id):
    """
	Tries to fetch a room for the user
	"""
    try:
        room = PublicChatRoom.objects.get(pk=room_id)
    except PublicChatRoom.DoesNotExist:
        raise ClientError("ROOM_INVALID", "Invalid room.")
    return room
Exemplo n.º 18
0
def _treatment_send(message, treatment):
    if message.user != treatment.user:
        raise ClientError("TREATMENT_ACCESS_DENIED")

    new_message = Message()
    new_message.treatment = treatment
    new_message.created_at = datetime.now()
    new_message.text = str(message["message"])
    new_message.msg_type = 'S'
    new_message.save()
Exemplo n.º 19
0
def _treatment_view(message, treatment):
    if not (treatment.is_closed and treatment.user is None):
        raise ClientError("TREATMENT_ACCESS_DENIED")

    if treatment.id not in message.channel_session['treatments']:
        treatment.websocket_group.add(message.reply_channel)
        message.channel_session['treatments'].append(treatment.id)

    message.reply_channel.send({"text": json.dumps({"action": "viewing"})})
    _send_treatment_messages(message.reply_channel, treatment)
Exemplo n.º 20
0
	async def receive_json(self, content):
		"""
		Called when we get a text frame. Channles will JSON-decode the payload fro us and pass it as the first argument.
		"""
		command = content.get("command", None)
		# message = content.get("message", None)	# can use this to see what message is 
		print("PublicChatConsumer: receive_json: " + str(command))
		# print("PublicChatConsumer: receive_json: " + str(message))
		# in order to get the send from command you can either use 
		# content.get("command", None) or you can use content['message']
		try:
			if command == "send":
				if len(content['message'].lstrip()) == 0:
					# raise Exception("nothing here")
					raise ClientError(422, "you can't send an empty message")
					# MDN web docs 422 Unproccessable entity
				# await self.send_json({
				# 	"message": content['message']
				# })
				# await self.send_message(content['room_id'], content['message'])

				# now using send_room instead of send_message.
				await self.send_room(content['room_id'], content['message'])
			elif command == "join":
				# mitch uses room inside of the addeventlistener (home.html)
				await self.join_room(content['room_id']) 
			elif command == "leave":
				# same as above
				await self.leave_room(content['room_id']) 
			elif command == "get_room_chat_messages":
				await self.display_progress_bar(True)
				room = await get_room_or_error(content['room_id'])
				payload = await get_room_chat_messages(room, content['page_number'])
				if payload != None:
					payload = json.loads(payload)
					await self.send_messages_payload(payload['messages'], payload['new_page_number'])
				else: 
					raise ClientError(204, "Something went wrong retrieving chatroom messages.")
				await self.display_progress_bar(False)
		except ClientError as e:
			await self.display_progress_bar(False)
			await self.handle_client_error(e)
Exemplo n.º 21
0
def get_history_json(room, start=0, offset=20):
    """
    Get history
    """
    try:
        history = Message.objects.filter(
            dialog=room.pk).order_by('-id')[start:start + offset][::-1]
        history = serializers.serialize('json', history)
    except:
        raise ClientError("CANT GET HISTORY")
    return history
Exemplo n.º 22
0
def get_room_or_error(room_id, user):
    """
    Tries to fetch a room for the user, checking permissions along the way.
    """
    try:
        room = PrivateChatRoom.objects.get(pk=room_id)
    except PrivateChatRoom.DoesNotExist:
        raise ClientError("ROOM_INVALID", "Invalid room.")

    # Is this user allowed in the room? (must be user1 or user2)
    if user != room.user1 and user != room.user2:
        raise ClientError("ROOM_ACCESS_DENIED",
                          "You do not have permission to join this room.")

    # Are the users in this room friends?
    # friend_list = FriendList.objects.get(user=user).friends.all()
    # if not room.user1 in friend_list:
    #    if not room.user2 in friend_list:
    #        raise ClientError("ROOM_ACCESS_DENIED", "You must be friends to chat.")
    return room
Exemplo n.º 23
0
    async def send_room(self, room_id, message):
        """
		Called by receive_json when someone sends a message to a room.
		"""
        print("ChatConsumer: send_room")
        if self.room_id != None:
            if str(room_id) != str(self.room_id):
                raise ClientError("ROOM_ACCESS_DENIED", "Room access denied")
        else:
            raise ClientError("ROOM_ACCESS_DENIED", "Room access denied")
        room = await get_room_or_error(room_id, self.scope['user'])

        # get list of connected_users
        connected_users = room.connected_users.all()
        """
		Finally using an async to fire these three all at the same time.
		"""
        await asyncio.gather(*[
            append_unread_msg_if_not_connected(room, room.user1,
                                               connected_users, message),
            append_unread_msg_if_not_connected(room, room.user2,
                                               connected_users, message),
            create_room_chat_message(room, self.scope['user'], message)
        ])

        # await append_unread_msg_if_not_connected(room, room.user1, connected_users, message)

        # await append_unread_msg_if_not_connected(room, room.user2, connected_users, message)

        # await create_room_chat_message(room, self.scope['user'], message)

        await self.channel_layer.group_send(
            room.group_name,
            {
                "type": "chat.message",  # executes chat_message
                "profile_image": self.scope['user'].profile_image.url,
                "username": self.scope['user'].username,
                "user_id": self.scope['user'].id,
                "message": message,
            })
Exemplo n.º 24
0
def get_unread_chat_notification_count(user):
	payload = {}
	if user.is_authenticated:
		chatmessage_ct = ContentType.objects.get_for_model(UnreadChatRoomMessages)
		notifications = Notification.objects.filter(target=user, content_type__in=[chatmessage_ct])
		unread_count = 0
		if notifications:
			unread_count = len(notifications.all())
			payload['count'] = unread_count
			return json.dumps(payload)
	else:
		ClientError("AUTH_ERROR", "User must be authenticated to get notifications.")
	return None
Exemplo n.º 25
0
 async def send_room(self, room_id: int, message: str):
     """Called by receive_json when someone sends a message to a room."""
     # Check they are in this room
     if room_id not in self.rooms:
         raise ClientError("ROOM_ACCESS_DENIED")
     # Get the room and send to the group about it
     room: Room = await get_room_or_error(room_id, self.scope["user"])
     user: User = self.scope['user']
     await self.channel_layer.group_send(
         room.group_name, {
             "type": "chat.message",
             "room_id": room_id,
             "username": user.username,
             "message": message,
         })
     await cache_or_update_room_presence(room_id, user)
Exemplo n.º 26
0
def get_room_or_error(id=None, event=None):
    """
    Tries to get the requested a room
    """
    if id is None and event is None:
        raise ValueError("id and event cannot both be None!")

    try:
        if id is not None:
            room = Room.objects.get(id=id)
        else:
            room = Room.objects.get(event=event)
    except Room.DoesNotExist:
        raise ClientError("Room not found.")

    return room
Exemplo n.º 27
0
def get_new_general_notifications(user, newest_timestamp):
	"""
	Retrieve any notifications newer than the newest_timestamp on the screen.
	"""
	payload = {}
	if user.is_authenticated:
		timestamp = newest_timestamp[0:newest_timestamp.find("+")]
		timestamp = datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S.%f")
		friend_request_ct = ContentType.objects.get_for_model(FriendRequest)
		friend_list_ct = ContentType.objects.get_for_model(FriendList)

		notifications = Notification.objects.filter(target=user, content_type__in=[friend_request_ct, friend_list_ct], timestamp__gt=timestamp, read=False).order_by("-timestamp")
		s = LazyNotificationEncoder()
		payload['notifications'] = s.serialize(notifications)
	else:
		raise ClientError("AUTH_ERROR", "User must be authenticated to get notifications")
	return json.dumps(payload)
Exemplo n.º 28
0
def get_new_chat_notifications(user, newest_timestamp):
	"""
	Retrieve any notifications newer than the newest_timestamp on the screen.
	"""
	payload = {}
	if user.is_authenticated:
		timestamp = newest_timestamp[0:newest_timestamp.find("+")]
		timestamp = datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S.%f")
		chatmessage_ct = ContentType.objects.get_for_model(UnreadChatRoomMessages)
		# content_type=chatmessage_ct or use what we used below. this is how we make a list but we don't really need a list just for reference.
		notifications = Notification.objects.filter(target=user, content_type__in=[chatmessage_ct], timestamp__gt=timestamp).order_by("-timestamp")
		s = LazyNotificationEncoder()
		payload['notifications'] = s.serialize(notifications)
		return json.dumps(payload)
	else:
		ClientError("AUTH_ERROR", "User must be authenticated to get notifications.")
	return None
Exemplo n.º 29
0
def _treatment_end(message, treatment):
    if treatment.is_closed or treatment.user != message.user:
        raise ClientError("TREATMENT_ACCESS_DENIED")

    treatment.is_closed = True
    treatment.closed_at = datetime.now()
    treatment.save()

    message = Message()
    message.treatment = treatment
    message.created_at = datetime.now()
    message.text = config.PLEASE_TREATMENT_CLODED_MESSAGE % web.utils.get_now_as_str()
    message.msg_type = 'S'
    message.save()

    treatment.websocket_group.send({"text": json.dumps({"action": "closed"})})
    message.channel_session['treatments'] = list(set(message.channel_session['treatments']).difference([treatment.id]))
Exemplo n.º 30
0
def get_unread_general_notifications_count(user):
	payload = {}
	if user.is_authenticated:
		friend_request_ct = ContentType.objects.get_for_model(FriendRequest)
		friend_list_ct = ContentType.objects.get_for_model(FriendList)

		notifications = Notification.objects.filter(target=user, content_type__in=[friend_request_ct, friend_list_ct], read=False)
		unread_count = 0
		if notifications:
			for notification in notifications.all():
				if not notification.read:
					unread_count = unread_count + 1
		payload['count'] = unread_count
		return json.dumps(payload)
	else:
		raise ClientError("AUTH_ERROR", "User must be authenticated to get notifications.")
	return None