Ejemplo n.º 1
0
 def send_message(message, giphy=None):
     if message[VarNames.TIME_DIFF] < 0:
         raise ValidationError("Back to the future?")
     files = UploadedFile.objects.filter(id__in=message.get(
         VarNames.FILES),
                                         user_id=self.user_id)
     symbol = get_max_key(files)
     channel = message[VarNames.ROOM_ID]
     js_id = message[VarNames.JS_MESSAGE_ID]
     message_db = Message(sender_id=self.user_id,
                          content=message[VarNames.CONTENT],
                          symbol=symbol,
                          giphy=giphy,
                          room_id=channel)
     message_db.time -= message[VarNames.TIME_DIFF]
     res_files = []
     do_db(message_db.save)
     if files:
         images = up_files_to_img(files, message_db.id)
         res_files = MessagesCreator.prepare_img_video(
             images, message_db.id)
     prepared_message = self.create_send_message(
         message_db, Actions.PRINT_MESSAGE, res_files, js_id)
     self.publish(prepared_message, channel)
     self.notify_offline(channel, message_db.id)
Ejemplo n.º 2
0
 def edit_glyphy(message, giphy):
     do_db(Message.objects.filter(id=message.id).update,
           content=message.content,
           symbol=message.symbol,
           giphy=giphy,
           edited_times=message.edited_times)
     message.giphy = giphy
     self.publish(
         self.create_send_message(message, Actions.EDIT_MESSAGE, None,
                                  js_id), message.room_id)
Ejemplo n.º 3
0
 def create_new_room(self, message):
     room_name = message[VarNames.ROOM_NAME]
     if not room_name or len(room_name) > 16:
         raise ValidationError('Incorrect room name "{}"'.format(room_name))
     room = Room(name=room_name)
     do_db(room.save)
     RoomUsers(room_id=room.id, user_id=self.user_id).save()
     subscribe_message = self.subscribe_room_channel_message(
         room.id, room_name)
     self.publish(subscribe_message, self.channel, True)
Ejemplo n.º 4
0
    def auth(self, username, password):
        """
		Logs in into system.
		"""
        try:
            if '@' in username:
                user = do_db(UserProfile.objects.get, email=username)
            else:
                user = do_db(UserProfile.objects.get, username=username)
            if not user.check_password(password):
                raise ValidationError("Invalid password")
        except User.DoesNotExist:
            raise ValidationError("User {} doesn't exist".format(username))

        return self.__generate_session__(user.id)
Ejemplo n.º 5
0
    def save_ip(self):
        """
		This code is not used anymore
		"""
        if not do_db(
                UserJoinedInfo.objects.filter(
                    Q(ip__ip=self.ip) & Q(user_id=self.user_id)).exists):
            res = get_or_create_ip_wrapper(self.ip, self.logger,
                                           self.fetch_and_save_ip_http)
            if res is not None:
                UserJoinedInfo.objects.create(ip=res, user_id=self.user_id)
Ejemplo n.º 6
0
 def open(self):
     session_key = self.get_cookie(settings.SESSION_COOKIE_NAME)
     if sessionStore.exists(session_key):
         self.ip = self.get_client_ip()
         session = SessionStore(session_key)
         self.user_id = int(session["_auth_user_id"])
         self.generate_self_id()
         log_params = {'id': self.id, 'ip': self.ip}
         self._logger = logging.LoggerAdapter(parent_logger, log_params)
         cookies = [
             "{}={}".format(k, self.request.cookies[k].value)
             for k in self.request.cookies
         ]
         self.logger.debug(
             "!! Incoming connection, session %s, thread hash %s, cookies: %s",
             session_key, self.id, ";".join(cookies))
         self.async_redis.connect()
         user_db = do_db(User.objects.get, id=self.user_id)
         self.sender_name = user_db.username
         self.sex = user_db.sex_str
         user_rooms = get_users_in_current_user_rooms(self.user_id)
         # get all missed messages
         self.channels = []  # py2 doesn't support clear()
         self.channels.append(self.channel)
         self.channels.append(self.id)
         rooms_online = {}
         was_online = False
         for room_id in user_rooms:
             self.channels.append(room_id)
             rooms_online[room_id] = self.get_is_online(room_id)
             was_online = was_online or rooms_online[room_id][0]
         self.listen(self.channels)
         off_messages, history = self.get_offline_messages(
             user_rooms, was_online, self.get_argument('history', False))
         for room_id in user_rooms:
             user_rooms[room_id][
                 VarNames.LOAD_MESSAGES_HISTORY] = history.get(room_id)
             user_rooms[room_id][
                 VarNames.LOAD_MESSAGES_OFFLINE] = off_messages.get(room_id)
         self.ws_write(self.set_room(user_rooms))
         for room_id in user_rooms:
             self.async_redis_publisher.sadd(room_id, self.id)
             self.add_online_user(room_id, rooms_online[room_id][0],
                                  rooms_online[room_id][1])
         self.logger.info("!! User %s subscribes for %s", self.sender_name,
                          self.channels)
         self.connected = True
         # self.save_ip()
     else:
         self.logger.warning('!! Session key %s has been rejected',
                             str(session_key))
         self.close(403, "Session key %s has been rejected" % session_key)
Ejemplo n.º 7
0
 def on_close(self):
     if self.async_redis.subscribed:
         self.logger.info("Close event, unsubscribing from %s",
                          self.channels)
         self.async_redis.unsubscribe(self.channels)
     else:
         self.logger.info("Close event, not subscribed, channels: %s",
                          self.channels)
     self.async_redis_publisher.srem(RedisPrefix.ONLINE_VAR, self.id)
     is_online, online = self.get_online_and_status_from_redis()
     if self.connected:
         if not is_online:
             message = self.room_online_logout(online)
             self.publish(message, settings.ALL_ROOM_ID)
         res = do_db(execute_query, settings.UPDATE_LAST_READ_MESSAGE, [
             self.user_id,
         ])
         self.logger.info("Updated %s last read message", res)
     self.disconnect()
Ejemplo n.º 8
0
 def delete_channel(self, message):
     room_id = message[VarNames.ROOM_ID]
     if room_id not in self.channels or room_id == ALL_ROOM_ID:
         raise ValidationError('You are not allowed to exit this room')
     room = do_db(Room.objects.get, id=room_id)
     if room.disabled:
         raise ValidationError('Room is already deleted')
     if room.name is None:  # if private then disable
         room.disabled = True
     else:  # if public -> leave the room, delete the link
         RoomUsers.objects.filter(room_id=room.id,
                                  user_id=self.user_id).delete()
         online = self.get_online_from_redis(room_id)
         online.remove(self.user_id)
         self.publish(self.room_online(online, Actions.LOGOUT, room_id),
                      room_id)
     room.save()
     message = self.unsubscribe_direct_message(room_id)
     self.publish(message, room_id, True)
Ejemplo n.º 9
0
 def edit_message(self, data):
     js_id = data[VarNames.JS_MESSAGE_ID]
     message = do_db(Message.objects.get, id=data[VarNames.MESSAGE_ID])
     validate_edit_message(self.user_id, message)
     message.content = data[VarNames.CONTENT]
     MessageHistory(message=message,
                    content=message.content,
                    giphy=message.giphy).save()
     message.edited_times += 1
     giphy_match = self.isGiphy(data[VarNames.CONTENT])
     if message.content is None:
         Message.objects.filter(id=data[VarNames.MESSAGE_ID]).update(
             deleted=True, edited_times=message.edited_times, content=None)
         self.publish(
             self.create_send_message(message, Actions.DELETE_MESSAGE, None,
                                      js_id), message.room_id)
     elif giphy_match is not None:
         self.edit_message_giphy(giphy_match, message, js_id)
     else:
         self.edit_message_edit(data, message, js_id)
Ejemplo n.º 10
0
 def delete_channel(self, message):
     room_id = message[VarNames.ROOM_ID]
     js_id = message[VarNames.JS_MESSAGE_ID]
     if room_id not in self.channels or room_id == ALL_ROOM_ID:
         raise ValidationError('You are not allowed to exit this room')
     room = do_db(Room.objects.get, id=room_id)
     if room.disabled:
         raise ValidationError('Room is already deleted')
     if room.name is None:  # if private then disable
         room.disabled = True
         room.save()
     else:  # if public -> leave the room, delete the link
         RoomUsers.objects.filter(room_id=room.id,
                                  user_id=self.user_id).delete()
     ru = list(
         RoomUsers.objects.filter(room_id=room.id).values_list('user_id',
                                                               flat=True))
     message = self.unsubscribe_direct_message(room_id, js_id, self.id, ru,
                                               room.name)
     self.publish(message, room_id, True)
Ejemplo n.º 11
0
    def process_get_messages(self, data):
        """
		:type data: dict
		"""
        header_id = data.get(VarNames.GET_MESSAGES_HEADER_ID, None)
        count = int(data.get(VarNames.GET_MESSAGES_COUNT, 10))
        room_id = data[VarNames.CHANNEL]
        self.logger.info('!! Fetching %d messages starting from %s', count,
                         header_id)
        if header_id is None:
            messages = Message.objects.filter(
                room_id=room_id).order_by('-pk')[:count]
        else:
            messages = Message.objects.filter(
                Q(id__lt=header_id),
                Q(room_id=room_id)).order_by('-pk')[:count]
        imv = do_db(get_message_images_videos, messages)
        response = self.get_messages(messages, room_id, imv,
                                     MessagesCreator.prepare_img_video)
        self.ws_write(response)
Ejemplo n.º 12
0
 def on_close(self):
     if self.async_redis.subscribed:
         self.logger.info("Close event, unsubscribing from %s",
                          self.channels)
         self.async_redis.unsubscribe(self.channels)
     else:
         self.logger.info("Close event, not subscribed, channels: %s",
                          self.channels)
     log_data = {}
     for channel in self.channels:
         if not isinstance(channel, Number):
             continue
         self.sync_redis.srem(channel, self.id)
         if self.connected:
             self.publish_logout(channel, log_data)
     if self.connected:
         res = do_db(execute_query, settings.UPDATE_LAST_READ_MESSAGE, [
             self.user_id,
         ])
         self.logger.info("Updated %s last read message", res)
     self.disconnect(json.dumps(log_data))
Ejemplo n.º 13
0
    def invite_user(self, message):
        room_id = message[VarNames.ROOM_ID]
        if room_id not in self.channels:
            raise ValidationError(
                "Access denied, only allowed for channels {}".format(
                    self.channels))
        room = do_db(Room.objects.get, id=room_id)
        if room.is_private:
            raise ValidationError(
                "You can't add users to direct room, create a new room instead"
            )
        users = message.get(VarNames.ROOM_USERS)
        users_in_room = list(
            RoomUsers.objects.filter(room_id=room_id).values_list('user_id',
                                                                  flat=True))
        intersect = set(users_in_room) & set(users)
        if bool(intersect):
            raise ValidationError("Users %s are already in the room",
                                  intersect)
        users_in_room.extend(users)

        max_id = Message.objects.filter(room_id=room_id).aggregate(
            Max('id'))['id__max']
        if not max_id:
            max_id = Message.objects.all().aggregate(Max('id'))['id__max']
        ru = [
            RoomUsers(user_id=user_id,
                      room_id=room_id,
                      last_read_message_id=max_id,
                      volume=1,
                      notifications=False) for user_id in users
        ]
        RoomUsers.objects.bulk_create(ru)

        add_invitee = {
            VarNames.EVENT: Actions.ADD_INVITE,
            VarNames.ROOM_ID: room_id,
            VarNames.ROOM_USERS: users_in_room,
            VarNames.ROOM_NAME: room.name,
            VarNames.INVITEE_USER_ID: users,
            VarNames.INVITER_USER_ID: self.user_id,
            VarNames.HANDLER_NAME: HandlerNames.CHANNELS,
            VarNames.TIME: get_milliseconds(),
            VarNames.VOLUME: 1,
            VarNames.NOTIFICATIONS: False,
        }
        add_invitee_dumped = encode_message(add_invitee, True)
        for user in users:
            self.raw_publish(add_invitee_dumped,
                             RedisPrefix.generate_user(user))

        invite = {
            VarNames.EVENT: Actions.INVITE_USER,
            VarNames.ROOM_ID: room_id,
            VarNames.INVITEE_USER_ID: users,
            VarNames.INVITER_USER_ID: self.user_id,
            VarNames.HANDLER_NAME: HandlerNames.CHANNELS,
            VarNames.ROOM_USERS: users_in_room,
            VarNames.TIME: get_milliseconds(),
            VarNames.CB_BY_SENDER: self.id,
            VarNames.JS_MESSAGE_ID: message[VarNames.JS_MESSAGE_ID]
        }
        self.publish(invite, room_id, True)
Ejemplo n.º 14
0
    def create_new_room(self, message):
        room_name = message.get(VarNames.ROOM_NAME)
        users = message.get(VarNames.ROOM_USERS)
        users.append(self.user_id)
        users = list(set(users))
        if room_name and len(room_name) > 16:
            raise ValidationError('Incorrect room name "{}"'.format(room_name))
        create_user_rooms = True
        if not room_name and len(users) == 2:
            user_rooms = evaluate(
                Room.users.through.objects.filter(
                    user_id=self.user_id,
                    room__name__isnull=True).values('room_id'))
            user_id = users[0] if users[1] == self.user_id else users[1]
            try:
                room = RoomUsers.objects.filter(user_id=user_id,
                                                room__in=user_rooms).values(
                                                    'room__id',
                                                    'room__disabled').get()
                room_id = room['room__id']
                if room['room__disabled']:
                    Room.objects.filter(id=room_id).update(disabled=False)
                else:
                    raise ValidationError('This room already exist')
                create_user_rooms = False
            except RoomUsers.DoesNotExist:
                pass
        elif not room_name:
            raise ValidationError(
                'At least one user should be selected, or room should be public'
            )
        if create_user_rooms:
            room = Room(name=room_name)
            do_db(room.save)
            room_id = room.id
            max_id = Message.objects.all().aggregate(Max('id'))['id__max']
            ru = [
                RoomUsers(user_id=user_id,
                          room_id=room_id,
                          last_read_message_id=max_id,
                          volume=message[VarNames.VOLUME],
                          notifications=message[VarNames.NOTIFICATIONS])
                for user_id in users
            ]
            RoomUsers.objects.bulk_create(ru)

        m = {
            VarNames.EVENT: Actions.CREATE_ROOM_CHANNEL,
            VarNames.ROOM_ID: room_id,
            VarNames.ROOM_USERS: users,
            VarNames.CB_BY_SENDER: self.id,
            VarNames.INVITER_USER_ID: self.user_id,
            VarNames.HANDLER_NAME: HandlerNames.CHANNELS,
            VarNames.VOLUME: message[VarNames.VOLUME],
            VarNames.NOTIFICATIONS: message[VarNames.NOTIFICATIONS],
            VarNames.ROOM_NAME: room_name,
            VarNames.TIME: get_milliseconds(),
            VarNames.JS_MESSAGE_ID: message[VarNames.JS_MESSAGE_ID],
        }
        jsoned_mess = encode_message(m, True)
        for user in users:
            self.raw_publish(jsoned_mess, RedisPrefix.generate_user(user))
Ejemplo n.º 15
0
    def open(self):
        session_key = self.get_argument('sessionId', None)
        try:
            if session_key is None:
                raise Error401()
            session = SessionStore(session_key)
            try:
                self.user_id = int(session["_auth_user_id"])
            except:
                raise Error401()
            self.ip = self.get_client_ip()
            user_db = do_db(UserProfile.objects.get, id=self.user_id)
            self.generate_self_id()
            self._logger = logging.LoggerAdapter(parent_logger, {
                'id': self.id,
                'ip': self.ip
            })
            cookies = [
                "{}={}".format(k, self.request.cookies[k].value)
                for k in self.request.cookies
            ]
            self.logger.debug(
                "!! Incoming connection, session %s, thread hash %s, cookies: %s",
                session_key, self.id, ";".join(cookies))
            self.async_redis.connect()
            self.async_redis_publisher.sadd(RedisPrefix.ONLINE_VAR, self.id)
            # since we add user to online first, latest trigger will always show correct online
            was_online, online = self.get_online_and_status_from_redis()
            user_rooms_query = Room.objects.filter(users__id=self.user_id, disabled=False) \
             .values('id', 'name', 'roomusers__notifications', 'roomusers__volume')
            room_users = [{
                VarNames.ROOM_ID:
                room['id'],
                VarNames.ROOM_NAME:
                room['name'],
                VarNames.NOTIFICATIONS:
                room['roomusers__notifications'],
                VarNames.VOLUME:
                room['roomusers__volume'],
                VarNames.ROOM_USERS: []
            } for room in user_rooms_query]
            user_rooms_dict = {
                room[VarNames.ROOM_ID]: room
                for room in room_users
            }
            room_ids = [room_id[VarNames.ROOM_ID] for room_id in room_users]
            rooms_users = RoomUsers.objects.filter(
                room_id__in=room_ids).values('user_id', 'room_id')
            for ru in rooms_users:
                user_rooms_dict[ru['room_id']][VarNames.ROOM_USERS].append(
                    ru['user_id'])
            # get all missed messages
            self.channels = room_ids  # py2 doesn't support clear()
            self.channels.append(self.channel)
            self.channels.append(self.id)
            self.listen(self.channels)
            off_messages, history = self.get_offline_messages(
                room_users, was_online, self.get_argument('history', False))
            for room in room_users:
                room_id = room[VarNames.ROOM_ID]
                h = history.get(room_id)
                o = off_messages.get(room_id)
                if h:
                    room[VarNames.LOAD_MESSAGES_HISTORY] = h
                if o:
                    room[VarNames.LOAD_MESSAGES_OFFLINE] = o

            if settings.SHOW_COUNTRY_CODE:
                fetched_users = User.objects.annotate(
                    user_c=Count('id')).values(
                        'id', 'username', 'sex',
                        'userjoinedinfo__ip__country_code',
                        'userjoinedinfo__ip__country',
                        'userjoinedinfo__ip__region',
                        'userjoinedinfo__ip__city')
                user_dict = [
                    RedisPrefix.set_js_user_structure_flag(
                        user['id'], user['username'], user['sex'],
                        user['userjoinedinfo__ip__country_code'],
                        user['userjoinedinfo__ip__country'],
                        user['userjoinedinfo__ip__region'],
                        user['userjoinedinfo__ip__city'])
                    for user in fetched_users
                ]
            else:
                fetched_users = User.objects.values('id', 'username', 'sex')
                user_dict = [
                    RedisPrefix.set_js_user_structure(user['id'],
                                                      user['username'],
                                                      user['sex'])
                    for user in fetched_users
                ]
            if self.user_id not in online:
                online.append(self.user_id)

            self.ws_write(self.set_room(room_users, user_dict, online,
                                        user_db))
            if not was_online:  # if a new tab has been opened
                online_user_names_mes = self.room_online_login(
                    online, user_db.username, user_db.sex_str)
                self.logger.info(
                    '!! First tab, sending refresh online for all')
                self.publish(online_user_names_mes, settings.ALL_ROOM_ID)
            self.logger.info("!! User %s subscribes for %s", self.user_id,
                             self.channels)
            self.connected = True
        except Error401:
            self.logger.warning('!! Session key %s has been rejected' %
                                session_key)
            self.close(403, "Session key %s has been rejected" % session_key)