def reap_chat(chat_id): user_list = UserListStore(NewparpRedis(connection_pool=redis_chat_pool), chat_id) old_user_ids = user_list.user_ids_online() if not old_user_ids: return with session_scope() as db: chat = db.query(Chat).filter(Chat.id == chat_id).one() chat_users = { _.user_id: _ for _ in db.query(ChatUser).filter(and_( ChatUser.chat_id == chat_id, ChatUser.user_id.in_(old_user_ids), )) } for socket_id, user_id in user_list.inconsistent_entries(): chat_user = chat_users[user_id] dead = user_list.socket_disconnect(socket_id, chat_user.number) if dead: logger.debug("dead: %s" % chat_user) # TODO optimise this when reaping several people at once? if chat_user.computed_group == "silent" or chat.type in ("pm", "roulette"): send_userlist(user_list, db, chat) else: send_message(db, reap_chat.redis, Message( chat=chat, user_id=chat_user.user_id, type="timeout", name=chat_user.name, text="%s's connection timed out." % chat_user.name, ), user_list)
def reap_chat(chat_id): user_list = UserListStore(NewparpRedis(connection_pool=redis_chat_pool), chat_id) old_user_ids = user_list.user_ids_online() if not old_user_ids: return with session_scope() as db: chat = db.query(Chat).filter(Chat.id == chat_id).one() chat_users = { _.user_id: _ for _ in db.query(ChatUser).filter( and_( ChatUser.chat_id == chat_id, ChatUser.user_id.in_(old_user_ids), )) } for socket_id, user_id in user_list.inconsistent_entries(): chat_user = chat_users[user_id] dead = user_list.socket_disconnect(socket_id, chat_user.number) if dead: logger.debug("dead: %s" % chat_user) # TODO optimise this when reaping several people at once? if chat_user.computed_group == "silent" or chat.type in ( "pm", "roulette"): send_userlist(user_list, db, chat) else: send_message( db, reap_chat.redis, Message( chat=chat, user_id=chat_user.user_id, type="timeout", name=chat_user.name, text="%s's connection timed out." % chat_user.name, ), user_list)
def send_message(db, redis, message, user_list=None, force_userlist=False): db.add(message) db.flush() message_dict = message.to_dict() # Cache before sending. cache_key = "chat:%s" % message.chat_id redis.zadd(cache_key, message.id, json.dumps(message_dict)) redis.zremrangebyrank(cache_key, 0, -51) # Prepare pubsub message redis_message = { "messages": [message_dict], } # Reload userlist if necessary. if message.type in ( "join", "disconnect", "timeout", "user_info", "user_group", "user_action", ) or force_userlist: if user_list is None: user_list = UserListStore( NewparpRedis(connection_pool=redis_chat_pool), message.chat_id) redis_message["users"] = get_userlist(user_list, db) # Reload chat metadata if necessary. if message.type == "chat_meta": redis_message["chat"] = message.chat.to_dict() redis.publish("channel:%s" % message.chat_id, json.dumps(redis_message)) # Send notifications. if message.type in ("ic", "ooc", "me", "spamless"): # Queue an update for the last_online field. # TODO move the PM stuff here too redis.hset( "queue:lastonline", message.chat.id, time.mktime(message.posted.timetuple()) + float(message.posted.microsecond) / 1000000) if user_list is None: user_list = UserListStore( NewparpRedis(connection_pool=redis_chat_pool), message.chat_id) online_user_ids = user_list.user_ids_online() if message.chat.type == "pm": offline_chat_users = db.query(ChatUser).filter( and_( ~ChatUser.user_id.in_(online_user_ids), ChatUser.chat_id == message.chat.id, )) for chat_user in offline_chat_users: # Only send a notification if it's not already unread. if message.chat.last_message <= chat_user.last_online: redis.publish("channel:pm:%s" % chat_user.user_id, "{\"pm\":\"1\"}") # And send the message to spamless last. # 1 second delay to prevent the task from executing before we commit the message. celery.send_task("newparp.tasks.spamless.CheckSpamTask", args=(message.chat_id, redis_message), countdown=1)
def send_message(db, redis, message, user_list=None, force_userlist=False): db.add(message) db.flush() message_dict = message.to_dict() if user_list is None: redis_chat = NewparpRedis(connection_pool=redis_chat_pool) user_list = UserListStore(redis_chat, message.chat_id) else: redis_chat = user_list.redis # Cache before sending. cache_key = "chat:%s" % message.chat_id redis_chat.zadd(cache_key, message.id, json.dumps(message_dict)) redis_chat.zremrangebyrank(cache_key, 0, -51) redis_chat.expire(cache_key, 604800) # Prepare pubsub message redis_message = { "messages": [message_dict], } # Reload userlist if necessary. if message.type in ( "join", "disconnect", "timeout", "user_info", "user_group", "user_action", ) or force_userlist: redis_message["users"] = get_userlist(user_list, db) # Reload chat metadata if necessary. if message.type == "chat_meta": redis_message["chat"] = message.chat.to_dict() redis.publish("channel:%s" % message.chat_id, json.dumps(redis_message)) # Send notifications. if message.type in ("ic", "ooc", "me", "spamless"): # Queue an update for the last_online field. # TODO move the PM stuff here too redis.hset("queue:lastonline", message.chat.id, time.mktime(message.posted.timetuple()) + float(message.posted.microsecond) / 1000000) online_user_ids = user_list.user_ids_online() if message.chat.type == "pm": offline_chat_users = db.query(ChatUser).filter(and_( ~ChatUser.user_id.in_(online_user_ids), ChatUser.chat_id == message.chat.id, )) for chat_user in offline_chat_users: # Only send a notification if it's not already unread. if message.chat.last_message <= chat_user.last_online: redis.publish("channel:pm:%s" % chat_user.user_id, "{\"pm\":\"1\"}") # And send the message to spamless last. # 1 second delay to prevent the task from executing before we commit the message. celery.send_task("newparp.tasks.spamless.CheckSpamTask", args=(message.chat_id, redis_message), countdown=1)