def decorated_function(*args, **kwargs): g.joining = False g.chat_id = int(request.form["chat_id"]) # Don't bother with any of this if we have a socket open, because the # request is probably from that window. if g.redis.scard("chat:%s:sockets:%s" % (g.chat_id, g.session_id)) != 0: return f(*args, **kwargs) session_online = g.redis.hexists("chat:%s:online" % g.chat_id, g.session_id) if not session_online: g.joining = True # Make sure we're connected to the database. db_connect() # Get ChatUser if we haven't got it already. if not hasattr(g, "chat_user"): get_chat_user() try: authorize_joining(g.redis, g.db, g) except (UnauthorizedException, BannedException, TooManyPeopleException): abort(403) try: kick_check(g.redis, g) except KickedException: return jsonify({"exit": "kick"}) join(g.redis, g.db, g) g.redis.zadd( "chats_alive", time.time() + 60, "%s/%s" % (g.chat_id, g.session_id), ) return f(*args, **kwargs)
def quit(): # Only send a message if we were already online. if g.user_id is None or "chat_id" not in request.form: abort(400) try: g.chat_id = int(request.form["chat_id"]) except ValueError: abort(400) if disconnect(g.redis, g.chat_id, g.session_id): db_connect() get_chat_user() send_quit_message(g.db, g.redis, g.chat_user, g.user, g.chat) return "", 204
def messages(): try: after = int(request.form["after"]) except (KeyError, ValueError): after = 0 # Look for stored messages first, and only subscribe if there aren't any. messages = g.redis.zrangebyscore("chat:%s" % g.chat_id, "(%s" % after, "+inf") if "joining" in request.form or g.joining: db_connect() get_chat_user() return jsonify({ "users": get_userlist(g.db, g.redis, g.chat), "chat": g.chat.to_dict(), "messages": [json.loads(_) for _ in messages], }) elif len(messages) != 0: message_dict = { "messages": [json.loads(_) for _ in messages] } return jsonify(message_dict) pubsub = g.redis.pubsub() # Channel for general chat messages. pubsub.subscribe("channel:%s" % g.chat_id) # Channel for messages aimed specifically at you - kicks, bans etc. pubsub.subscribe("channel:%s:%s" % (g.chat_id, g.user_id)) # Get rid of the database connection here so we're not hanging onto it # while waiting for the redis message. db_commit() db_disconnect() for msg in pubsub.listen(): if msg["type"] == "message": # The pubsub channel sends us a JSON string, so we return that # instead of using jsonify. resp = make_response(msg["data"]) resp.headers["Content-type"] = "application/json" pubsub.close() return resp