| Total Complexity | 80 | 
| Total Lines | 384 | 
| Duplicated Lines | 3.91 % | 
| Changes | 1 | ||
| Bugs | 0 | Features | 0 | 
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like MessagesHandler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | import json  | 
            ||
| 38 | class MessagesHandler(MessagesCreator):  | 
            ||
| 39 | |||
| 40 | def __init__(self, *args, **kwargs):  | 
            ||
| 41 | self.closed_channels = None  | 
            ||
| 42 | self.parsable_prefix = 'p'  | 
            ||
| 43 | super(MessagesHandler, self).__init__()  | 
            ||
| 44 | 		self.webrtc_ids = {} | 
            ||
| 45 | self.id = None # child init  | 
            ||
| 46 | self.sex = None  | 
            ||
| 47 | self.sender_name = None  | 
            ||
| 48 | self.user_id = 0 # anonymous by default  | 
            ||
| 49 | self.ip = None  | 
            ||
| 50 | from chat import global_redis  | 
            ||
| 51 | self.async_redis_publisher = global_redis.async_redis_publisher  | 
            ||
| 52 | self.sync_redis = global_redis.sync_redis  | 
            ||
| 53 | self.channels = []  | 
            ||
| 54 | self._logger = None  | 
            ||
| 55 | self.async_redis = Client(host=REDIS_HOST, port=REDIS_PORT)  | 
            ||
| 56 | self.patch_tornadoredis()  | 
            ||
| 57 | 		self.pre_process_message = { | 
            ||
| 58 | Actions.GET_MESSAGES: self.process_get_messages,  | 
            ||
| 59 | Actions.SEND_MESSAGE: self.process_send_message,  | 
            ||
| 60 | Actions.CREATE_DIRECT_CHANNEL: self.create_user_channel,  | 
            ||
| 61 | Actions.DELETE_ROOM: self.delete_channel,  | 
            ||
| 62 | Actions.EDIT_MESSAGE: self.edit_message,  | 
            ||
| 63 | Actions.CREATE_ROOM_CHANNEL: self.create_new_room,  | 
            ||
| 64 | Actions.INVITE_USER: self.invite_user,  | 
            ||
| 65 | Actions.PING: self.respond_ping  | 
            ||
| 66 | }  | 
            ||
| 67 | 		self.post_process_message = { | 
            ||
| 68 | Actions.CREATE_DIRECT_CHANNEL: self.send_client_new_channel,  | 
            ||
| 69 | Actions.CREATE_ROOM_CHANNEL: self.send_client_new_channel,  | 
            ||
| 70 | Actions.DELETE_ROOM: self.send_client_delete_channel,  | 
            ||
| 71 | Actions.INVITE_USER: self.send_client_new_channel  | 
            ||
| 72 | }  | 
            ||
| 73 | |||
| 74 | def patch_tornadoredis(self): # TODO remove this  | 
            ||
| 75 | fabric = type(self.async_redis.connection.readline)  | 
            ||
| 76 | self.async_redis.connection.old_read = self.async_redis.connection.readline  | 
            ||
| 77 | |||
| 78 | def new_read(new_self, callback=None):  | 
            ||
| 79 | try:  | 
            ||
| 80 | return new_self.old_read(callback=callback)  | 
            ||
| 81 | except Exception as e:  | 
            ||
| 82 | return  | 
            ||
| 83 | current_online = self.get_online_from_redis(RedisPrefix.DEFAULT_CHANNEL)  | 
            ||
| 84 | self.logger.error(e)  | 
            ||
| 85 | self.logger.error(  | 
            ||
| 86 | "Exception info: "  | 
            ||
| 87 | "self.id: %s ;;; "  | 
            ||
| 88 | "self.connected = '%s';;; "  | 
            ||
| 89 | "Redis default channel online = '%s';;; "  | 
            ||
| 90 | "self.channels = '%s';;; "  | 
            ||
| 91 | "self.closed_channels = '%s';;;",  | 
            ||
| 92 | self.id, self.connected, current_online, self.channels, self.closed_channels  | 
            ||
| 93 | )  | 
            ||
| 94 | raise e  | 
            ||
| 95 | |||
| 96 | self.async_redis.connection.readline = fabric(new_read, self.async_redis.connection)  | 
            ||
| 97 | |||
| 98 | @property  | 
            ||
| 99 | def connected(self):  | 
            ||
| 100 | raise NotImplemented  | 
            ||
| 101 | |||
| 102 | @connected.setter  | 
            ||
| 103 | def connected(self, value):  | 
            ||
| 104 | raise NotImplemented  | 
            ||
| 105 | |||
| 106 | @property  | 
            ||
| 107 | def http_client(self):  | 
            ||
| 108 | raise NotImplemented  | 
            ||
| 109 | |||
| 110 | @engine  | 
            ||
| 111 | def listen(self, channels):  | 
            ||
| 112 | yield Task(  | 
            ||
| 113 | self.async_redis.subscribe, channels)  | 
            ||
| 114 | self.async_redis.listen(self.pub_sub_message)  | 
            ||
| 115 | |||
| 116 | @property  | 
            ||
| 117 | def logger(self):  | 
            ||
| 118 | return self._logger if self._logger else base_logger  | 
            ||
| 119 | |||
| 120 | @engine  | 
            ||
| 121 | def add_channel(self, channel):  | 
            ||
| 122 | self.channels.append(channel)  | 
            ||
| 123 | yield Task(self.async_redis.subscribe, (channel,))  | 
            ||
| 124 | |||
| 125 | def get_online_from_redis(self, channel):  | 
            ||
| 126 | return self.get_online_and_status_from_redis(channel)[1]  | 
            ||
| 127 | |||
| 128 | def get_online_and_status_from_redis(self, channel):  | 
            ||
| 129 | """  | 
            ||
| 130 | :rtype : (bool, list)  | 
            ||
| 131 | """  | 
            ||
| 132 | online = self.sync_redis.ssmembers(channel)  | 
            ||
| 133 | 		self.logger.debug('!! channel %s redis online: %s', channel, online) | 
            ||
| 134 | return self.parse_redis_online(online) if online else (False, [])  | 
            ||
| 135 | |||
| 136 | def parse_redis_online(self, online):  | 
            ||
| 137 | """  | 
            ||
| 138 | :rtype : (bool, list)  | 
            ||
| 139 | """  | 
            ||
| 140 | result = set()  | 
            ||
| 141 | user_is_online = False  | 
            ||
| 142 | for decoded in online: # py2 iteritems  | 
            ||
| 143 | # : char specified in cookies_middleware.py.create_id  | 
            ||
| 144 | 			user_id = int(decoded.split(':')[0]) | 
            ||
| 145 | if user_id == self.user_id and decoded != self.id:  | 
            ||
| 146 | user_is_online = True  | 
            ||
| 147 | result.add(user_id)  | 
            ||
| 148 | return user_is_online, list(result)  | 
            ||
| 149 | |||
| 150 | def add_online_user(self, room_id):  | 
            ||
| 151 | """  | 
            ||
| 152 | adds to redis  | 
            ||
| 153 | 		online_users = { connection_hash1 = stored_redis_user1, connection_hash_2 = stored_redis_user2 } | 
            ||
| 154 | :return: if user is online  | 
            ||
| 155 | """  | 
            ||
| 156 | self.async_redis_publisher.sadd(room_id, self.id)  | 
            ||
| 157 | # since we add user to online first, latest trigger will always show correct online  | 
            ||
| 158 | is_online, online = self.get_online_and_status_from_redis(room_id)  | 
            ||
| 159 | if is_online: # Send user names to self  | 
            ||
| 160 | online_user_names_mes = self.room_online(online, Actions.REFRESH_USER, room_id)  | 
            ||
| 161 | 			self.logger.info('!! Second tab, retrieving online for self') | 
            ||
| 162 | self.ws_write(online_user_names_mes)  | 
            ||
| 163 | else: # if a new tab has been opened  | 
            ||
| 164 | online.append(self.user_id)  | 
            ||
| 165 | online_user_names_mes = self.room_online(online, Actions.LOGIN, room_id)  | 
            ||
| 166 | 			self.logger.info('!! First tab, sending refresh online for all') | 
            ||
| 167 | self.publish(online_user_names_mes, room_id)  | 
            ||
| 168 | return is_online  | 
            ||
| 169 | |||
| 170 | def publish(self, message, channel, parsable=False):  | 
            ||
| 171 | jsoned_mess = json.dumps(message)  | 
            ||
| 172 | 		self.logger.debug('<%s> %s', channel, jsoned_mess) | 
            ||
| 173 | if parsable:  | 
            ||
| 174 | jsoned_mess = self.encode(jsoned_mess)  | 
            ||
| 175 | self.async_redis_publisher.publish(channel, jsoned_mess)  | 
            ||
| 176 | |||
| 177 | def encode(self, message):  | 
            ||
| 178 | """  | 
            ||
| 179 | Marks message with prefix to specify that  | 
            ||
| 180 | it should be decoded and proccesed before sending to client  | 
            ||
| 181 | @param message: message to mark  | 
            ||
| 182 | @return: marked message  | 
            ||
| 183 | """  | 
            ||
| 184 | return self.parsable_prefix + message  | 
            ||
| 185 | |||
| 186 | def remove_parsable_prefix(self, message):  | 
            ||
| 187 | if message.startswith(self.parsable_prefix):  | 
            ||
| 188 | return message[1:]  | 
            ||
| 189 | |||
| 190 | def pub_sub_message(self, message):  | 
            ||
| 191 | data = message.body  | 
            ||
| 192 | if isinstance(data, str_type): # subscribe event  | 
            ||
| 193 | prefixless_str = self.remove_parsable_prefix(data)  | 
            ||
| 194 | if prefixless_str:  | 
            ||
| 195 | dict_message = json.loads(prefixless_str)  | 
            ||
| 196 | res = self.post_process_message[dict_message[VarNames.EVENT]](dict_message)  | 
            ||
| 197 | if not res:  | 
            ||
| 198 | self.ws_write(prefixless_str)  | 
            ||
| 199 | else:  | 
            ||
| 200 | self.ws_write(data)  | 
            ||
| 201 | |||
| 202 | def ws_write(self, message):  | 
            ||
| 203 | 		raise NotImplementedError('WebSocketHandler implements') | 
            ||
| 204 | |||
| 205 | @asynchronous  | 
            ||
| 206 | def search_giphy(self, message, query, cb):  | 
            ||
| 207 | 		self.logger.debug("!! Asking giphy for: %s", query) | 
            ||
| 208 | def on_giphy_reply(response):  | 
            ||
| 209 | try:  | 
            ||
| 210 | 				self.logger.debug("!! Got giphy response: " + str(response.body)) | 
            ||
| 211 | res = json.loads(response.body)  | 
            ||
| 212 | giphy = res['data'][0]['images']['downsized_medium']['url']  | 
            ||
| 213 | except:  | 
            ||
| 214 | giphy = None  | 
            ||
| 215 | cb(message, giphy)  | 
            ||
| 216 | url = GIPHY_URL.format(GIPHY_API_KEY, quote(query, safe=''))  | 
            ||
| 217 | self.http_client.fetch(url, callback=on_giphy_reply)  | 
            ||
| 218 | |||
| 219 | def notify_offline(self, channel, message_id):  | 
            ||
| 220 | if FIREBASE_API_KEY is None:  | 
            ||
| 221 | return  | 
            ||
| 222 | online = self.get_online_from_redis(channel)  | 
            ||
| 223 | if channel == ALL_ROOM_ID:  | 
            ||
| 224 | return  | 
            ||
| 225 | 		offline_users = RoomUsers.objects.filter(room_id=channel, notifications=True).exclude(user_id__in=online).values_list('user_id') | 
            ||
| 226 | subscriptions = Subscription.objects.filter(user__in=offline_users, inactive=False)  | 
            ||
| 227 | if len(subscriptions) == 0:  | 
            ||
| 228 | return  | 
            ||
| 229 | new_sub_mess =[SubscriptionMessages(message_id=message_id, subscription_id=r.id) for r in subscriptions]  | 
            ||
| 230 | reg_ids =[r.registration_id for r in subscriptions]  | 
            ||
| 231 | SubscriptionMessages.objects.bulk_create(new_sub_mess)  | 
            ||
| 232 | self.post_firebase(list(reg_ids))  | 
            ||
| 233 | |||
| 234 | @asynchronous  | 
            ||
| 235 | def post_firebase(self, reg_ids):  | 
            ||
| 236 | def on_reply(response):  | 
            ||
| 237 | try:  | 
            ||
| 238 | 				self.logger.debug("!! FireBase response: " + str(response.body)) | 
            ||
| 239 | response_obj = json.loads(response.body)  | 
            ||
| 240 | delete = []  | 
            ||
| 241 | for index, elem in enumerate(response_obj['results']):  | 
            ||
| 242 | 					if elem.get('error') in ['NotRegistered', 'InvalidRegistration']: | 
            ||
| 243 | delete.append(reg_ids[index])  | 
            ||
| 244 | if len(delete) > 0:  | 
            ||
| 245 | 					self.logger.info("Deactivating subscriptions: %s", delete) | 
            ||
| 246 | Subscription.objects.filter(registration_id__in=delete).update(inactive=True)  | 
            ||
| 247 | except Exception as e:  | 
            ||
| 248 | 				self.logger.error("Unable to parse response" + str(e)) | 
            ||
| 249 | pass  | 
            ||
| 250 | |||
| 251 | 		headers = {"Content-Type": "application/json", "Authorization": "key=%s" % FIREBASE_API_KEY} | 
            ||
| 252 | 		body = json.dumps({"registration_ids": reg_ids}) | 
            ||
| 253 | 		self.logger.debug("!! post_fire_message %s", body) | 
            ||
| 254 | r = HTTPRequest(FIREBASE_URL, method="POST", headers=headers, body=body)  | 
            ||
| 255 | self.http_client.fetch(r, callback=on_reply)  | 
            ||
| 256 | |||
| 257 | def isGiphy(self, content):  | 
            ||
| 258 | if GIPHY_API_KEY is not None and content is not None:  | 
            ||
| 259 | giphy_match = re.search(GIPHY_REGEX, content)  | 
            ||
| 260 | return giphy_match.group(1) if giphy_match is not None else None  | 
            ||
| 261 | |||
| 262 | def process_send_message(self, message):  | 
            ||
| 263 | """  | 
            ||
| 264 | :type message: dict  | 
            ||
| 265 | """  | 
            ||
| 266 | content = message.get(VarNames.CONTENT)  | 
            ||
| 267 | giphy_match = self.isGiphy(content)  | 
            ||
| 268 | |||
| 269 | # @transaction.atomic mysql has gone away  | 
            ||
| 270 | def send_message(message, giphy=None):  | 
            ||
| 271 | files = UploadedFile.objects.filter(id__in=message.get(VarNames.FILES), user_id=self.user_id)  | 
            ||
| 272 | symbol = get_max_key(files)  | 
            ||
| 273 | channel = message[VarNames.CHANNEL]  | 
            ||
| 274 | js_id = message[VarNames.JS_MESSAGE_ID]  | 
            ||
| 275 | message_db = Message(  | 
            ||
| 276 | sender_id=self.user_id,  | 
            ||
| 277 | content=message[VarNames.CONTENT],  | 
            ||
| 278 | symbol=symbol,  | 
            ||
| 279 | giphy=giphy,  | 
            ||
| 280 | room_id=channel  | 
            ||
| 281 | )  | 
            ||
| 282 | res_files = []  | 
            ||
| 283 | do_db(message_db.save)  | 
            ||
| 284 | if files:  | 
            ||
| 285 | blk_save = [Image(symbol=f.symbol, message=message_db, img=f.file, type=f.type) for f in files]  | 
            ||
| 286 | images = Image.objects.bulk_create(blk_save)  | 
            ||
| 287 | res_files = MessagesCreator.prepare_img_video(images, message_db.id)  | 
            ||
| 288 | files.delete()  | 
            ||
| 289 | prepared_message = self.create_send_message(  | 
            ||
| 290 | message_db,  | 
            ||
| 291 | Actions.PRINT_MESSAGE,  | 
            ||
| 292 | res_files,  | 
            ||
| 293 | js_id  | 
            ||
| 294 | )  | 
            ||
| 295 | self.publish(prepared_message, channel)  | 
            ||
| 296 | self.notify_offline(channel, message_db.id)  | 
            ||
| 297 | if giphy_match is not None:  | 
            ||
| 298 | self.search_giphy(message, giphy_match, send_message)  | 
            ||
| 299 | else:  | 
            ||
| 300 | send_message(message)  | 
            ||
| 301 | |||
| 302 | def create_new_room(self, message):  | 
            ||
| 303 | room_name = message[VarNames.ROOM_NAME]  | 
            ||
| 304 | if not room_name or len(room_name) > 16:  | 
            ||
| 305 | 			raise ValidationError('Incorrect room name "{}"'.format(room_name)) | 
            ||
| 306 | room = Room(name=room_name)  | 
            ||
| 307 | do_db(room.save)  | 
            ||
| 308 | RoomUsers(room_id=room.id, user_id=self.user_id).save()  | 
            ||
| 309 | subscribe_message = self.subscribe_room_channel_message(room.id, room_name)  | 
            ||
| 310 | self.publish(subscribe_message, self.channel, True)  | 
            ||
| 311 | |||
| 312 | def invite_user(self, message):  | 
            ||
| 313 | room_id = message[VarNames.ROOM_ID]  | 
            ||
| 314 | user_id = message[VarNames.USER_ID]  | 
            ||
| 315 | room = get_or_create_room(self.channels, room_id, user_id)  | 
            ||
| 316 | 		users_in_room = { | 
            ||
| 317 | user.id: RedisPrefix.set_js_user_structure(user.username, user.sex)  | 
            ||
| 318 | for user in room.users.all()  | 
            ||
| 319 | }  | 
            ||
| 320 | self.publish(self.add_user_to_room(room_id, user_id, users_in_room[user_id]), room_id)  | 
            ||
| 321 | subscribe_message = self.invite_room_channel_message(room_id, user_id, room.name, users_in_room)  | 
            ||
| 322 | self.publish(subscribe_message, RedisPrefix.generate_user(user_id), True)  | 
            ||
| 323 | |||
| 324 | def respond_ping(self, message):  | 
            ||
| 325 | self.ws_write(self.responde_pong())  | 
            ||
| 326 | |||
| 327 | def create_user_channel(self, message):  | 
            ||
| 328 | user_id = message[VarNames.USER_ID]  | 
            ||
| 329 | room_id = create_room(self.user_id, user_id)  | 
            ||
| 330 | subscribe_message = self.subscribe_direct_channel_message(room_id, user_id, self.user_id != user_id)  | 
            ||
| 331 | self.publish(subscribe_message, self.channel, True)  | 
            ||
| 332 | other_channel = RedisPrefix.generate_user(user_id)  | 
            ||
| 333 | if self.channel != other_channel:  | 
            ||
| 334 | self.publish(subscribe_message, other_channel, True)  | 
            ||
| 335 | |||
| 336 | def delete_channel(self, message):  | 
            ||
| 337 | room_id = message[VarNames.ROOM_ID]  | 
            ||
| 338 | if room_id not in self.channels or room_id == ALL_ROOM_ID:  | 
            ||
| 339 | 			raise ValidationError('You are not allowed to exit this room') | 
            ||
| 340 | room = do_db(Room.objects.get, id=room_id)  | 
            ||
| 341 | if room.disabled:  | 
            ||
| 342 | 			raise ValidationError('Room is already deleted') | 
            ||
| 343 | if room.name is None: # if private then disable  | 
            ||
| 344 | room.disabled = True  | 
            ||
| 345 | else: # if public -> leave the room, delete the link  | 
            ||
| 346 | RoomUsers.objects.filter(room_id=room.id, user_id=self.user_id).delete()  | 
            ||
| 347 | online = self.get_online_from_redis(room_id)  | 
            ||
| 348 | online.remove(self.user_id)  | 
            ||
| 349 | self.publish(self.room_online(online, Actions.LOGOUT, room_id), room_id)  | 
            ||
| 350 | room.save()  | 
            ||
| 351 | message = self.unsubscribe_direct_message(room_id)  | 
            ||
| 352 | self.publish(message, room_id, True)  | 
            ||
| 353 | |||
| 354 | def edit_message(self, data):  | 
            ||
| 355 | js_id = data[VarNames.JS_MESSAGE_ID]  | 
            ||
| 356 | message = do_db(Message.objects.get, id=data[VarNames.MESSAGE_ID])  | 
            ||
| 357 | validate_edit_message(self.user_id, message)  | 
            ||
| 358 | message.content = data[VarNames.CONTENT]  | 
            ||
| 359 | MessageHistory(message=message, content=message.content, giphy=message.giphy).save()  | 
            ||
| 360 | message.edited_times += 1  | 
            ||
| 361 | View Code Duplication | giphy_match = self.isGiphy(data[VarNames.CONTENT])  | 
            |
| 
                                                                                                    
                         1 ignored issue 
                            –
                            show
                         | 
                |||
| 362 | if message.content is None:  | 
            ||
| 363 | Message.objects.filter(id=data[VarNames.MESSAGE_ID]).update(deleted=True, edited_times=message.edited_times)  | 
            ||
| 364 | self.publish(self.create_send_message(message, Actions.DELETE_MESSAGE, None, js_id), message.room_id)  | 
            ||
| 365 | elif giphy_match is not None:  | 
            ||
| 366 | self.edit_message_giphy(giphy_match, message, js_id)  | 
            ||
| 367 | else:  | 
            ||
| 368 | self.edit_message_edit(data, message, js_id)  | 
            ||
| 369 | |||
| 370 | def edit_message_giphy(self, giphy_match, message, js_id):  | 
            ||
| 371 | def edit_glyphy(message, giphy):  | 
            ||
| 372 | do_db(Message.objects.filter(id=message.id).update, content=message.content, symbol=message.symbol, giphy=giphy,  | 
            ||
| 373 | edited_times=message.edited_times)  | 
            ||
| 374 | message.giphy = giphy  | 
            ||
| 375 | self.publish(self.create_send_message(message, Actions.EDIT_MESSAGE, None, js_id), message.room_id)  | 
            ||
| 376 | |||
| 377 | self.search_giphy(message, giphy_match, edit_glyphy)  | 
            ||
| 378 | |||
| 379 | def edit_message_edit(self, data, message, js_id):  | 
            ||
| 380 | action = Actions.EDIT_MESSAGE  | 
            ||
| 381 | message.giphy = None  | 
            ||
| 382 | files = UploadedFile.objects.filter(id__in=data.get(VarNames.FILES), user_id=self.user_id)  | 
            ||
| 383 | if files:  | 
            ||
| 384 | update_symbols(files, message)  | 
            ||
| 385 | blk_save = [Image(symbol=f.symbol, message=message, img=f.file, type=f.type) for f in files]  | 
            ||
| 386 | Image.objects.bulk_create(blk_save)  | 
            ||
| 387 | files.delete()  | 
            ||
| 388 | if message.symbol: # fetch all, including that we just store  | 
            ||
| 389 | db_images = Image.objects.filter(message_id=message.id)  | 
            ||
| 390 | prep_files = MessagesCreator.prepare_img_video(db_images, message.id)  | 
            ||
| 391 | else:  | 
            ||
| 392 | prep_files = None  | 
            ||
| 393 | Message.objects.filter(id=message.id).update(content=message.content, symbol=message.symbol, giphy=None, edited_times=message.edited_times)  | 
            ||
| 394 | self.publish(self.create_send_message(message, action, prep_files, js_id), message.room_id)  | 
            ||
| 395 | |||
| 396 | def send_client_new_channel(self, message):  | 
            ||
| 397 | room_id = message[VarNames.ROOM_ID]  | 
            ||
| 398 | self.add_channel(room_id)  | 
            ||
| 399 | self.add_online_user(room_id)  | 
            ||
| 400 | |||
| 401 | def send_client_delete_channel(self, message):  | 
            ||
| 402 | room_id = message[VarNames.ROOM_ID]  | 
            ||
| 403 | self.async_redis.unsubscribe((room_id,))  | 
            ||
| 404 | self.async_redis_publisher.hdel(room_id, self.id)  | 
            ||
| 405 | self.channels.remove(room_id)  | 
            ||
| 406 | |||
| 407 | def process_get_messages(self, data):  | 
            ||
| 408 | """  | 
            ||
| 409 | :type data: dict  | 
            ||
| 410 | """  | 
            ||
| 411 | header_id = data.get(VarNames.GET_MESSAGES_HEADER_ID, None)  | 
            ||
| 412 | count = int(data.get(VarNames.GET_MESSAGES_COUNT, 10))  | 
            ||
| 413 | room_id = data[VarNames.CHANNEL]  | 
            ||
| 414 | 		self.logger.info('!! Fetching %d messages starting from %s', count, header_id) | 
            ||
| 415 | if header_id is None:  | 
            ||
| 416 | 			messages = Message.objects.filter(Q(room_id=room_id), Q(deleted=False)).order_by('-pk')[:count] | 
            ||
| 417 | else:  | 
            ||
| 418 | 			messages = Message.objects.filter(Q(id__lt=header_id), Q(room_id=room_id), Q(deleted=False)).order_by('-pk')[:count] | 
            ||
| 419 | imv = do_db(get_message_images_videos, messages)  | 
            ||
| 420 | response = self.get_messages(messages, room_id, imv, MessagesCreator.prepare_img_video)  | 
            ||
| 421 | self.ws_write(response)  | 
            ||
| 422 | |||
| 624 | self.publish(message, user)  |