def on_open(self, request): if self.session.session_id not in OperationNotifier.sessions: return False logging.debug('ChatConnection::on_open. session_id: %s' % unicode(self.session.session_id)) user, company, employee, client_cts = OperationNotifier.sessions[ self.session.session_id] if employee._id not in OperationNotifier.connections: OperationNotifier.connections[employee._id] = [self] OperationNotifier.on_employee_online(employee._id) self.notify_online(employee) else: OperationNotifier.connections[employee._id].append(self) mem_cache.set('on-%s' % str(employee._id), 1, 0) self.company = company self.employee = employee self.user = user self.client_cts = client_cts self.connection_date = datetime.now() self.tailable_cursor = Operation.objects.collection.find( { 'listeners': employee._id, 'is_service': False, 'timestamp': { '$gt': self.client_cts } }, tailable=True) op_list = self.get_missed_ops(self.client_cts) if len(op_list): server_cts = get_cts() self.client_cts = server_cts self.emit('operations', {'ops': op_list, 'new_cts': server_cts})
def on_open(self, request): if self.session.session_id not in OperationNotifier.sessions: return False logging.debug('ChatConnection::on_open. session_id: %s' % unicode(self.session.session_id)) user, company, employee, client_cts = OperationNotifier.sessions[self.session.session_id] if employee._id not in OperationNotifier.connections: OperationNotifier.connections[employee._id] = [self] OperationNotifier.on_employee_online(employee._id) self.notify_online(employee) else: OperationNotifier.connections[employee._id].append(self) mem_cache.set('on-%s' % str(employee._id), 1, 0) self.company = company self.employee = employee self.user = user self.client_cts = client_cts self.connection_date = datetime.now() self.tailable_cursor = Operation.objects.collection.find({'listeners' : employee._id, 'is_service' : False, 'timestamp' : {'$gt' : self.client_cts}}, tailable=True) op_list = self.get_missed_ops(self.client_cts) if len(op_list): server_cts = get_cts() self.client_cts = server_cts self.emit('operations', {'ops' : op_list, 'new_cts' : server_cts})
def test_first_mr(self): om1 = Operation({ 'owner': self.e2, 'operation_type': OperationTypeEnum.OT_NEW_MESSAGE, 'data': { 'dialog': ObjectId(), 'text': 'first', 'email': 'email1' }, 'listeners': [self.e1, self.e2] }) om1.save() oo1 = Operation({ 'owner': self.e1, 'operation_type': OperationTypeEnum.OT_STATUS_CHANGE, 'data': { 'online': True }, 'listeners': [self.e2, self.e3] }) oo1.save() task = UnreadDialogNotificationTask() task.make_employee_op_collection(get_cts() + 100000, 0) all_eo_items = mongodb_connection_manager.database[ 'chat_dialog_mr_udn'].find().sort([('value.ts', 1)]) items = [item for item in all_eo_items] self.assertEqual(all_eo_items.count(), 2) test_m1 = items[0] test_o1 = items[1] self.assertIn('_id', test_m1) self.assertIn('_id', test_o1) self.assertIn('value', test_m1) self.assertIn('value', test_o1) m1_key = test_m1['_id'] o1_key = test_o1['_id'] self.assertIn('owner', m1_key) self.assertIn('owner', o1_key) self.assertEqual(m1_key['owner'], self.e1) self.assertEqual(o1_key['owner'], self.e1) self.assertIn('op', m1_key) self.assertIn('op', o1_key) self.assertEqual(m1_key['op'], 2) self.assertEqual(o1_key['op'], 3) m1_value = test_m1['value'] o1_value = test_o1['value'] self.assertIn('ts', m1_value) self.assertIn('ts', o1_value)
def on_check_dialog_viewed(self, **data): my_employee = self.employee try: dialog_id = data.get('dialog_id') dialog = ChatDialog.objects.get_one({ '_id': ObjectId(dialog_id), 'parties': my_employee._id }) if not dialog: raise Exception('No such dialog') except Exception: self.emit('check_as_viewed', {'error': True}) return ChatDialog.objects.collection.update( {'_id': dialog._id}, {'$pull': { 'not_viewed_by_parties': my_employee._id }}) operation = Operation({ 'owner': my_employee._id, 'operation_type': OperationTypeEnum.OT_MARK_READ, 'data': { 'dialog': dialog_id }, 'listeners': [my_employee._id] }) operation.save() server_cts = get_cts() self.client_cts = server_cts OperationNotifier.notify(operation, self.client_cts)
def notify_status_change(self, employee, online = False): operation = Operation({'owner' : employee._id, 'operation_type' : OperationTypeEnum.OT_STATUS_CHANGE, 'data' : {'employee' : unicode(employee._id), 'online' : online}, 'listeners' : OperationNotifier.active_dialog_connections(employee._id)}) operation.save() server_cts = get_cts() self.client_cts = server_cts OperationNotifier.notify(operation, self.client_cts)
def on_add_dlg_msg(self, **data): my_employee = self.employee try: text = data.get('text').strip() dialog_id = data.get('dialog_id') if not len(text): raise Exception('Missing required parameter "text"') # todo: asyncmongo dialog = ChatDialog.objects.get_one({ '_id': ObjectId(dialog_id), 'parties': my_employee._id }) if not dialog: raise Exception('No such dialog') except Exception: self.emit('error', {'msg': u'Не удалось отправить сообщение'}) return new_message = DialogMessage({ 'dialog': dialog._id, 'text': text, 'creator': my_employee._id }) new_message.save() employee_tz = my_employee.get_tz() ChatDialog.objects.collection.update({'_id': dialog._id}, { '$set': { 'last_message_date': new_message.date, 'last_message_text': new_message.text[:200], 'last_message_party': self.employee._id, 'last_message_id': new_message._id, 'hidden_by_parties': [], 'not_viewed_by_parties': dialog.parties } }) operation = Operation({ 'owner': my_employee._id, 'operation_type': OperationTypeEnum.OT_NEW_MESSAGE, 'data': { 'dialog': dialog_id, 'text': new_message.text, 'date': new_message.date.astimezone(employee_tz).isoformat(), 'author': unicode(my_employee._id), 'message_id': unicode(new_message._id) }, 'listeners': dialog.parties }) operation.save() server_cts = get_cts() self.client_cts = server_cts OperationNotifier.notify(operation, self.client_cts)
def test_first_mr(self): om1 = Operation({'owner' : self.e2, 'operation_type' : OperationTypeEnum.OT_NEW_MESSAGE, 'data' : {'dialog' : ObjectId(), 'text' : 'first', 'email' : 'email1'}, 'listeners' : [self.e1, self.e2]}) om1.save() oo1 = Operation({'owner' : self.e1, 'operation_type' : OperationTypeEnum.OT_STATUS_CHANGE, 'data' : {'online' : True}, 'listeners' : [self.e2, self.e3]}) oo1.save() task = UnreadDialogNotificationTask() task.make_employee_op_collection(get_cts() + 100000, 0) all_eo_items = mongodb_connection_manager.database['chat_dialog_mr_udn'].find().sort([('value.ts', 1)]) items = [item for item in all_eo_items] self.assertEqual(all_eo_items.count(), 2) test_m1 = items[0] test_o1 = items[1] self.assertIn('_id', test_m1) self.assertIn('_id', test_o1) self.assertIn('value', test_m1) self.assertIn('value', test_o1) m1_key = test_m1['_id'] o1_key = test_o1['_id'] self.assertIn('owner', m1_key) self.assertIn('owner', o1_key) self.assertEqual(m1_key['owner'], self.e1) self.assertEqual(o1_key['owner'], self.e1) self.assertIn('op', m1_key) self.assertIn('op', o1_key) self.assertEqual(m1_key['op'], 2) self.assertEqual(o1_key['op'], 3) m1_value = test_m1['value'] o1_value = test_o1['value'] self.assertIn('ts', m1_value) self.assertIn('ts', o1_value)
def execute(self): print >> sys.stdout, '%s Executing UnreadDialogNotificationTask' % unicode(datetime.now()) search_ts = get_cts() - cts_from_timedelta(timedelta(hours = 3)) ts_min = search_ts - cts_from_timedelta(timedelta(days = 3)) result = self.make_employee_op_collection(search_ts, ts_min) if result['ok'] != 1: print >> sys.stderr, u'Failed to perform map_reduce during checking unread messages: %s' % repr(result) return result = self.make_employee_last_ops() if result['ok'] != 1: print >> sys.stderr, u'Failed to perform map_reduce step 2 during checking unread messages: %s' % repr(result) return unread_dialogs_cursor = self.find_unsent_messages() for unread_data in unread_dialogs_cursor: try: employee = unread_data['_id'] if self.is_online(employee): mark_as_sent = Operation({'owner' : employee, 'operation_type' : OperationTypeEnum.OT_EMAIL_SENT, 'data' : {'fake' : True}, 'listeners' : [employee], 'is_service' : True}) mark_as_sent.save() continue email = self.get_employee_email(employee) if not email or not is_valid_email(email): continue action = create_action_id(actions.UNREAD_DIALOGS, employee) subj = u'Непрочитанные сообщения в Реквизитке' data = {'SITE_DOMAIN_NAME' : settings.SITE_DOMAIN_NAME} text = render_to_string('mail/chat/unread_dialogs.txt', data) html = render_to_string('mail/chat/unread_dialogs.html', data) notification_manager.remove(action) notification_manager.add(action, email, subj, text, html, settings.UNREAD_MESSAGE_EMAIL_NOTIFY_TIMEOUT) mark_as_sent = Operation({'owner' : employee, 'operation_type' : OperationTypeEnum.OT_EMAIL_SENT, 'data' : {}, 'listeners' : [employee], 'is_service' : True}) mark_as_sent.save() except Exception: pass
def get(self, request): company = request.company employee = request.employee data = DialogListInitialsView.generate_data_obj(employee, company) data.update(portal.get_common_data_for_company(request, company)) module_init = mark_safe(simplejson.dumps(data)) response = render_to_response('apps/chat/dialoglist/templates/template.html', { 'chat_module_init' : module_init, 'sidebar_mode' : 'some_company', 'sidebar_initial_data' : company }, context_instance = RequestContext(request)) response.set_cookie('cts', get_cts(), max_age=3600) return response
def test_first_mr_after_ts(self): self.send_online(self.e1, [self.e2, self.e3]) self.send_message(self.e1, self.e2) self.send_online(self.e2, [self.e1, self.e3]) self.send_message(self.e2, self.e1) ts = self.send_message(self.e2, self.e1).timestamp self.send_message(self.e1, self.e2) self.send_message(self.e1, self.e3) self.send_online(self.e3, [self.e1, self.e2]) self.send_message(self.e3, self.e1) task = UnreadDialogNotificationTask() task.make_employee_op_collection(get_cts() + 100000, ts) all_eo_items = mongodb_connection_manager.database['chat_dialog_mr_udn'].find().sort([('value.ts', 1)]) self.assertEqual(all_eo_items.count(), 4)
def test_first_mr_after_ts(self): self.send_online(self.e1, [self.e2, self.e3]) self.send_message(self.e1, self.e2) self.send_online(self.e2, [self.e1, self.e3]) self.send_message(self.e2, self.e1) ts = self.send_message(self.e2, self.e1).timestamp self.send_message(self.e1, self.e2) self.send_message(self.e1, self.e3) self.send_online(self.e3, [self.e1, self.e2]) self.send_message(self.e3, self.e1) task = UnreadDialogNotificationTask() task.make_employee_op_collection(get_cts() + 100000, ts) all_eo_items = mongodb_connection_manager.database[ 'chat_dialog_mr_udn'].find().sort([('value.ts', 1)]) self.assertEqual(all_eo_items.count(), 4)
def notify_status_change(self, employee, online=False): operation = Operation({ 'owner': employee._id, 'operation_type': OperationTypeEnum.OT_STATUS_CHANGE, 'data': { 'employee': unicode(employee._id), 'online': online }, 'listeners': OperationNotifier.active_dialog_connections(employee._id) }) operation.save() server_cts = get_cts() self.client_cts = server_cts OperationNotifier.notify(operation, self.client_cts)
def on_add_dlg_msg(self, **data): my_employee = self.employee try: text = data.get('text').strip() dialog_id = data.get('dialog_id') if not len(text): raise Exception('Missing required parameter "text"') # todo: asyncmongo dialog = ChatDialog.objects.get_one({'_id' : ObjectId(dialog_id), 'parties' : my_employee._id}) if not dialog: raise Exception('No such dialog') except Exception: self.emit('error', {'msg' : u'Не удалось отправить сообщение'}) return new_message = DialogMessage({'dialog' : dialog._id, 'text' : text, 'creator' : my_employee._id}) new_message.save() employee_tz = my_employee.get_tz() ChatDialog.objects.collection.update({'_id' : dialog._id}, {'$set' : { 'last_message_date' : new_message.date, 'last_message_text' : new_message.text[:200], 'last_message_party' : self.employee._id, 'last_message_id' : new_message._id, 'hidden_by_parties' : [], 'not_viewed_by_parties' : dialog.parties }}) operation = Operation({'owner' : my_employee._id, 'operation_type' : OperationTypeEnum.OT_NEW_MESSAGE, 'data' : {'dialog' : dialog_id, 'text' : new_message.text, 'date' : new_message.date.astimezone(employee_tz).isoformat(), 'author' : unicode(my_employee._id), 'message_id' : unicode(new_message._id)}, 'listeners' : dialog.parties}) operation.save() server_cts = get_cts() self.client_cts = server_cts OperationNotifier.notify(operation, self.client_cts)
def on_refresh_connection(self, endpoint_name): logging.debug('* * * Refresh connection') data_list = self.get_missed_ops(self.client_cts) if len(data_list): logging.debug('* * * %i new operations:' % len(data_list)) for op in data_list: logging.debug(repr(op)) # dirty hack server_cts = get_cts() self.client_cts = server_cts msg = proto.event(endpoint_name, 'operations', None, {'ops' : data_list, 'new_cts' : server_cts}) self.session.send_queue.append(msg) return True cur_date = datetime.now() dt = cur_date - self.connection_date if dt.seconds / 3600.0 > 2: return False return True
def on_check_dialog_viewed(self, **data): my_employee = self.employee try: dialog_id = data.get('dialog_id') dialog = ChatDialog.objects.get_one({'_id' : ObjectId(dialog_id), 'parties' : my_employee._id}) if not dialog: raise Exception('No such dialog') except Exception: self.emit('check_as_viewed', {'error' : True}) return ChatDialog.objects.collection.update({'_id' : dialog._id}, {'$pull' : {'not_viewed_by_parties' : my_employee._id}}) operation = Operation({'owner' : my_employee._id, 'operation_type' : OperationTypeEnum.OT_MARK_READ, 'data' : {'dialog' : dialog_id}, 'listeners' : [my_employee._id]}) operation.save() server_cts = get_cts() self.client_cts = server_cts OperationNotifier.notify(operation, self.client_cts)
def on_refresh_connection(self, endpoint_name): logging.debug('* * * Refresh connection') data_list = self.get_missed_ops(self.client_cts) if len(data_list): logging.debug('* * * %i new operations:' % len(data_list)) for op in data_list: logging.debug(repr(op)) # dirty hack server_cts = get_cts() self.client_cts = server_cts msg = proto.event(endpoint_name, 'operations', None, { 'ops': data_list, 'new_cts': server_cts }) self.session.send_queue.append(msg) return True cur_date = datetime.now() dt = cur_date - self.connection_date if dt.seconds / 3600.0 > 2: return False return True
def get(self, request, dialog_id): employee = request.employee try: dialog = ChatDialog.objects.get_one({'_id' : ObjectId(dialog_id), 'hidden_by_parties' : {'$ne' : employee._id}, 'parties' : employee._id}) if not dialog: raise Exception() except Exception: raise Http404() company = request.company data = DialogInitialsView.generate_data_obj(dialog, employee, company) data.update(portal.get_common_data_for_company(request, company)) module_initials = mark_safe(simplejson.dumps(data)) response = render_to_response('apps/chat/dialog/templates/template.html', { 'chat_module_init' : module_initials, 'sidebar_mode' : 'some_company', 'sidebar_initial_data' : company }, context_instance = RequestContext(request)) response.set_cookie('cts', get_cts(), max_age=3600) return response
def save(self): self.timestamp = get_cts() return super(Operation, self).save()