Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
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)