Пример #1
0
    def on_close(self):
        # Unsubscribe here and let the exit callback handle disconnecting.
        if hasattr(self, "redis_task"):
            self.redis_task.cancel()

        if hasattr(self, "redis_client"):
            self.redis_client.close()

        if hasattr(self, "close_code") and self.close_code in (1000, 1001):
            message_type = "disconnect"
        else:
            message_type = "timeout"

        if self.joined and self.user_list.socket_disconnect(self.id, self.user_number):
            try:
                send_quit_message(self.user_list, self.db, *self.get_chat_user(), type=message_type)
            except NoResultFound:
                send_userlist(self.user_list, self.db, self.chat)
            self.db.commit()

        # Delete the database connection here and on_finish just to be sure.
        if hasattr(self, "_db"):
            self._db.close()
            del self._db

        if DEBUG:
            print("socket closed: %s" % self.id)

        try:
            sockets.remove(self)
        except KeyError:
            pass
Пример #2
0
    def on_close(self):
        # Unsubscribe here and let the exit callback handle disconnecting.
        if hasattr(self, "redis_task"):
            self.redis_task.cancel()

        if hasattr(self, "redis_client"):
            self.redis_client.close()

        if hasattr(self, "close_code") and self.close_code in (1000, 1001):
            message_type = "disconnect"
        else:
            message_type = "timeout"

        if self.joined and self.user_list.socket_disconnect(self.id, self.user_number):
            try:
                send_quit_message(self.user_list, self.db, *self.get_chat_user(), type=message_type)
            except NoResultFound:
                send_userlist(self.user_list, self.db, self.chat)
            self.db.commit()

        # Delete the database connection here and on_finish just to be sure.
        if hasattr(self, "_db"):
            self._db.close()
            del self._db

        if DEBUG:
            print("socket closed: %s" % self.id)

        try:
            sockets.remove(self)
        except KeyError:
            pass
Пример #3
0
def reap():
    redis = reap.redis
    with session_scope() as db:
        current_time = int(time.time())
        disconnected_users = set()

        # Long poll sessions.
        for dead in redis.zrangebyscore("chats_alive", 0, current_time):
            logger.info("Reaping %s" % dead)
            chat_id, session_id = dead.split('/')
            user_id = redis.hget("chat:%s:online" % chat_id, session_id)
            disconnected = disconnect(redis, chat_id, session_id)
            # Only send a timeout message if they were already online.
            if not disconnected:
                logger.info("Not sending timeout message.")
                continue
            disconnected_users.add((chat_id, user_id, False))

        # Sockets.
        for dead in redis.zrangebyscore("sockets_alive", 0, current_time):
            logger.info("Reaping %s" % dead)
            chat_id, session_id, socket_id = dead.split('/')
            user_id = redis.hget("chat:%s:online" % chat_id, socket_id)
            disconnected = disconnect(redis, chat_id, socket_id)
            redis.srem("chat:%s:sockets:%s" % (chat_id, session_id), socket_id)
            redis.zrem("sockets_alive", "%s/%s/%s" % (chat_id, session_id, socket_id))
            # Only send a timeout message if they were already online.
            if not disconnected:
                logger.info("Not sending timeout message.")
                continue
            disconnected_users.add((chat_id, user_id, True))

        for chat_id, user_id, reaped_socket in disconnected_users:
            try:
                dead_chat_user = db.query(ChatUser).filter(and_(
                    ChatUser.user_id == user_id,
                    ChatUser.chat_id == chat_id,
                )).options(joinedload(ChatUser.chat), joinedload(ChatUser.user)).one()
            except NoResultFound:
                logger.error("Unable to find ChatUser (chat %s, user %s)." % (chat_id, user_id))
                continue

            if reaped_socket:
                typing_key = "chat:%s:typing" % chat_id
                if redis.srem(typing_key, dead_chat_user.number):
                    redis.publish("channel:%s:typing" % chat_id, json.dumps({
                        "typing": list(int(_) for _ in redis.smembers(typing_key)),
                    }))

            if dead_chat_user.computed_group == "silent" or dead_chat_user.chat.type in ("pm", "roulette"):
                send_userlist(db, redis, dead_chat_user.chat)
            else:
                send_message(db, redis, Message(
                    chat_id=chat_id,
                    user_id=dead_chat_user.user_id,
                    type="timeout",
                    name=dead_chat_user.name,
                    text="%s's connection timed out." % dead_chat_user.name,
                ))
            logger.info("Sent timeout message for ChatUser (chat %s, user %s)." % (chat_id, user_id))
Пример #4
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)
Пример #5
0
def save_from_character():

    try:
        character = g.db.query(Character).filter(
            and_(
                Character.id == request.form["character_id"],
                Character.user_id == g.user.id,
            )).order_by(Character.title).one()
    except NoResultFound:
        abort(404)

    # Remember old values so we can check if they've changed later.
    old_name = g.chat_user.name
    old_acronym = g.chat_user.acronym

    # Send a message if name, acronym or color has changed.
    changed = (g.chat_user.name != character.name
               or g.chat_user.acronym != character.acronym
               or g.chat_user.color != character.color)

    g.chat_user.name = character.name
    g.chat_user.acronym = character.acronym
    g.chat_user.color = character.color
    g.chat_user.quirk_prefix = character.quirk_prefix
    g.chat_user.quirk_suffix = character.quirk_suffix
    g.chat_user.case = character.case
    g.chat_user.replacements = character.replacements
    g.chat_user.regexes = character.regexes

    if changed:
        if g.chat_user.computed_group == "silent":
            send_userlist(g.user_list, g.db, g.chat)
        else:
            send_message(
                g.db, g.redis,
                Message(
                    chat_id=g.chat.id,
                    user_id=g.user.id,
                    type="user_info",
                    name=g.chat_user.name,
                    text="%s [%s] is now %s [%s]." % (
                        old_name,
                        old_acronym,
                        g.chat_user.name,
                        g.chat_user.acronym,
                    ),
                ), g.user_list)

    return jsonify(g.chat_user.to_dict(include_options=True))
Пример #6
0
def save_from_character():

    try:
        character = g.db.query(Character).filter(and_(
            Character.id == request.form["character_id"],
            Character.user_id == g.user.id,
        )).order_by(Character.title).one()
    except NoResultFound:
        abort(404)

    # Remember old values so we can check if they've changed later.
    old_name = g.chat_user.name
    old_acronym = g.chat_user.acronym

    # Send a message if name, acronym or color has changed.
    changed = (
        g.chat_user.name != character.name
        or g.chat_user.acronym != character.acronym
        or g.chat_user.color != character.color
    )

    g.chat_user.name = character.name
    g.chat_user.acronym = character.acronym
    g.chat_user.color = character.color
    g.chat_user.quirk_prefix = character.quirk_prefix
    g.chat_user.quirk_suffix = character.quirk_suffix
    g.chat_user.case = character.case
    g.chat_user.replacements = character.replacements
    g.chat_user.regexes = character.regexes

    if changed:
        if g.chat_user.computed_group == "silent":
            send_userlist(g.user_list, g.db, g.chat)
        else:
            send_message(g.db, g.redis, Message(
                chat_id=g.chat.id,
                user_id=g.user.id,
                type="user_info",
                name=g.chat_user.name,
                text="%s [%s] is now %s [%s]." % (
                    old_name, old_acronym,
                    g.chat_user.name, g.chat_user.acronym,
                ),
            ), g.user_list)

    return jsonify(g.chat_user.to_dict(include_options=True))
Пример #7
0
def save():

    # Remember old values so we can check if they've changed later.
    old_name = g.chat_user.name
    old_acronym = g.chat_user.acronym
    old_color = g.chat_user.color

    new_details = validate_character_form(request.form)
    g.chat_user.search_character_id = new_details["search_character_id"]
    g.chat_user.name = new_details["name"]
    g.chat_user.acronym = new_details["acronym"]
    g.chat_user.color = new_details["color"]
    g.chat_user.quirk_prefix = new_details["quirk_prefix"]
    g.chat_user.quirk_suffix = new_details["quirk_suffix"]
    g.chat_user.case = new_details["case"]
    g.chat_user.replacements = new_details["replacements"]
    g.chat_user.regexes = new_details["regexes"]

    # Send a message if name or acronym has changed.
    if g.chat_user.name != old_name or g.chat_user.acronym != old_acronym:
        if g.chat_user.computed_group == "silent":
            send_userlist(g.user_list, g.db, g.chat)
        else:
            send_message(
                g.db, g.redis,
                Message(
                    chat_id=g.chat.id,
                    user_id=g.user.id,
                    type="user_info",
                    name=g.chat_user.name,
                    text=("%s [%s] is now %s [%s].") % (
                        old_name,
                        old_acronym,
                        g.chat_user.name,
                        g.chat_user.acronym,
                    ),
                ), g.user_list)
    # Just refresh the user list if the color has changed.
    elif g.chat_user.color != old_color:
        send_userlist(g.user_list, g.db, g.chat)

    return jsonify(g.chat_user.to_dict(include_options=True))
Пример #8
0
def save():

    # Remember old values so we can check if they've changed later.
    old_name = g.chat_user.name
    old_acronym = g.chat_user.acronym
    old_color = g.chat_user.color

    new_details = validate_character_form(request.form)
    g.chat_user.search_character_id = new_details["search_character_id"]
    g.chat_user.name = new_details["name"]
    g.chat_user.acronym = new_details["acronym"]
    g.chat_user.color = new_details["color"]
    g.chat_user.quirk_prefix = new_details["quirk_prefix"]
    g.chat_user.quirk_suffix = new_details["quirk_suffix"]
    g.chat_user.case = new_details["case"]
    g.chat_user.replacements = new_details["replacements"]
    g.chat_user.regexes = new_details["regexes"]

    # Send a message if name or acronym has changed.
    if g.chat_user.name != old_name or g.chat_user.acronym != old_acronym:
        if g.chat_user.computed_group == "silent":
            send_userlist(g.db, g.redis, g.chat)
        else:
            send_message(g.db, g.redis, Message(
                chat_id=g.chat.id,
                user_id=g.user.id,
                type="user_info",
                name=g.chat_user.name,
                text=("%s [%s] is now %s [%s].") % (
                    old_name, old_acronym,
                    g.chat_user.name, g.chat_user.acronym,
                ),
            ))
    # Just refresh the user list if the color has changed.
    elif g.chat_user.color != old_color:
        send_userlist(g.db, g.redis, g.chat)

    return jsonify(g.chat_user.to_dict(include_options=True))
Пример #9
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)