Exemplo n.º 1
0
 def prepare(self):
     self.id = str(uuid4())
     self.joined = False
     try:
         self.session_id = self.cookies["session"].value
         self.chat_id = int(self.path_args[0])
         self.user_id = int(redis.get("session:%s" % self.session_id))
     except (KeyError, TypeError, ValueError):
         self.send_error(400)
         return
     self.db = sm()
     try:
         self.chat_user, self.user, self.chat = self.get_chat_user()
     except NoResultFound:
         self.send_error(404)
         return
     # Remember the user number so typing notifications can refer to it
     # without reopening the database session.
     self.user_number = self.chat_user.number
     self.user.last_online = datetime.now()
     self.user.last_ip = self.request.headers["X-Forwarded-For"]
     if self.user.group == "banned":
         self.send_error(403)
         return
     try:
         authorize_joining(redis, self.db, self)
     except (UnauthorizedException, BannedException, TooManyPeopleException):
         self.send_error(403)
         return
Exemplo n.º 2
0
#!/usr/bin/python

import time

from redis import StrictRedis
from sqlalchemy import and_, func
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.exc import NoResultFound

from charat2.helpers.chat import disconnect, send_message, send_userlist
from charat2.model import sm, Message, ChatUser
from charat2.model.connections import redis_pool

if __name__ == "__main__":

    db = sm()

    print "Obtaining lock..."
    db.query(func.pg_advisory_lock(413, 1)).scalar()
    print "Lock obtained."

    redis = StrictRedis(connection_pool=redis_pool)

    while True:

        current_time = int(time.time())

        # Make sure a message is sent every 25 seconds so the long poll requests
        # don't time out.
        # XXX INCREASE THIS TO SEVERAL MINUTES
        for chat_id in redis.zrangebyscore("longpoll_timeout", 0, current_time):
Exemplo n.º 3
0
def run_matchmaker(
    lock_id, searchers_key, searcher_prefix, get_searcher_info,
    check_compatibility, ChatClass, get_character_info,
):

    # XXX get log level from stdin
    root = logging.getLogger()
    root.setLevel(logging.DEBUG)

    db = sm()

    print "Obtaining lock..."
    db.query(func.pg_advisory_lock(413, lock_id)).scalar()
    print "Lock obtained."

    redis = StrictRedis(connection_pool=redis_pool)

    searcher_ids = redis.smembers(searchers_key)

    while True:

        # Reset the searcher list for the next iteration.
        redis.delete(searchers_key)
        for searcher in searcher_ids:
            logging.debug("Waking unmatched searcher %s." % searcher)
            redis.publish("%s:%s" % (searcher_prefix, searcher), "{ \"status\": \"unmatched\" }")

        time.sleep(10)

        logging.info("Starting match loop.")

        searcher_ids = redis.smembers(searchers_key)

        # We can't do anything with less than 2 people, so don't bother.
        if len(searcher_ids) < 2:
            logging.info("Not enough searchers, skipping.")
            continue

        searchers = get_searcher_info(redis, searcher_ids)
        logging.debug("Searcher list: %s" % searchers)
        shuffle(searchers)

        already_matched = set()
        # Range hack so we don't check opposite pairs or against itself.
        for n in range(len(searchers)):
            s1 = searchers[n]

            for m in range(n + 1, len(searchers)):
                s2 = searchers[m]

                if s1["id"] in already_matched or s2["id"] in already_matched:
                    continue

                logging.debug("Comparing %s and %s." % (s1["id"], s2["id"]))

                match, options = check_compatibility(redis, s1, s2)
                if not match:
                    logging.debug("No match.")
                    continue

                blocked = (
                    db.query(func.count("*")).select_from(Block).filter(and_(
                        Block.blocking_user_id == s1["user_id"],
                        Block.blocked_user_id == s2["user_id"]
                    )).scalar() != 0
                    or db.query(func.count("*")).select_from(Block).filter(and_(
                        Block.blocking_user_id == s2["user_id"],
                        Block.blocked_user_id == s1["user_id"]
                    )).scalar() != 0
                )
                if blocked:
                    logging.debug("Blocked.")
                    continue

                new_url = str(uuid4()).replace("-", "")
                logging.info(
                    "Matched %s and %s, sending to %s."
                    % (s1["id"], s2["id"], new_url)
                )
                new_chat = ChatClass(url=new_url)
                db.add(new_chat)
                db.flush()

                s1_user = db.query(User).filter(User.id == s1["user_id"]).one()
                s2_user = db.query(User).filter(User.id == s2["user_id"]).one()
                db.add(ChatUser.from_user(s1_user, chat_id=new_chat.id, number=1, **get_character_info(db, s1)))
                db.add(ChatUser.from_user(s2_user, chat_id=new_chat.id, number=2, **get_character_info(db, s2)))

                if options:
                    db.add(Message(
                        chat_id=new_chat.id,
                        type="search_info",
                        text=" ".join(option_messages[_] for _ in options),
                    ))

                db.commit()

                already_matched.add(s1["id"])
                already_matched.add(s2["id"])

                match_message = json.dumps({ "status": "matched", "url": new_url })
                redis.publish("%s:%s" % (searcher_prefix, s1["id"]), match_message)
                redis.publish("%s:%s" % (searcher_prefix, s2["id"]), match_message)
                searcher_ids.remove(s1["id"])
                searcher_ids.remove(s2["id"])
Exemplo n.º 4
0
 def prepare(self):
     self.db = sm()
Exemplo n.º 5
0
def db_connect():
    if not hasattr(g, "db"):
        g.db = sm()