Example #1
0
    def get(self):

        url_match = request.args.get("url_match", "/resources/%")

        cur = db.cursor()

        result = cur.execute(
            fetch_query_string(
                "select_rendered_puzzle_files_with_url_like.sql"),
            {
                "url_match": url_match
            },
        ).fetchall()
        if not result:
            puzzle_files = []
        else:
            (result, col_names) = rowify(result, cur.description)
            puzzle_files = result

        response = {
            "puzzle_files": puzzle_files,
        }

        cur.close()

        return make_response(json.jsonify(response), 200)
def migrate_s3_puzzle(puzzle):
    """
    Download the file from S3 and update the url in the puzzle file.
    """
    if not exists:
        logging.info("Bucket doesn't exist")
        return

    cur = db.cursor()

    puzzle_id = puzzle.get('puzzle_id')
    puzzle_dir = create_puzzle_dir(puzzle_id)
    url_components = urlparse(puzzle.get('url'))
    key = url_components.path[1:]
    file_name = os.path.basename(key)
    file_path = os.path.join(puzzle_dir, file_name)
    local_url = "/resources/{puzzle_id}/{file_name}".format(
        puzzle_id=puzzle_id, file_name=file_name)
    logging.info("Downloading {}".format(
        os.path.join(puzzle_dir, os.path.basename(key))))
    s3.download_file(BUCKET_NAME, key, file_path)

    cur.execute(
        query_update_puzzle_file_url, {
            'puzzle': puzzle.get('puzzle'),
            'name': puzzle.get('name'),
            'url': local_url
        })
    db.commit()
    cur.close()

    logging.info(
        "{puzzle} migrating s3 puzzle file {name} ({puzzle_id}): {url}".format(
            **puzzle))
Example #3
0
    def get_offset_of_adjacent_pieces(piece, mask_width, piece_width):
        cur = db.cursor()
        offsets = {}

        x = piece['x']
        y = piece['y']
        t = mask_width - piece_width
        sides = [
            {'side':{
                (360, 0):'top_path',
                },
              'other_side':{
                (360, 0):'bottom_path',
                },
              'x':x,
              'y':((y+t) - mask_width)},
             {'side':{
               (360, 0):'right_path',
               },
              'other_side':{
                (360, 0):'left_path',
                },
              'x':((x-t) + mask_width),
              'y':y},
             {'side':{
               (360, 0):'bottom_path',
               },
              'other_side':{
                (360, 0):'top_path',
                },
              'x':x,
              'y':((y-t) + mask_width)},
             {'side':{
               (360, 0):'left_path',
               },
              'other_side':{
                (360, 0):'right_path',
                },
              'x':((x+t) - mask_width),
              'y':(y)},
            ]
        piece_alignment = (360, 0)

        query = """select * from Piece where (id != :id) and (puzzle = :puzzle) and ((top_path = :bottom_path) or (bottom_path = :top_path) or (right_path = :left_path) or (left_path = :right_path))"""
        (d, col_names) = rowify(cur.execute(query, piece).fetchall(), cur.description)
        for adjacent_piece in d:
            for s in sides:
                try:
                    if adjacent_piece[s['other_side'][piece_alignment]] == piece[s['side'][piece_alignment]]: # always check if the sides match
                        offset = {
                            'x': int(math.ceil(piece_width)*FITS_MAPPING[s['side'][piece_alignment]]['x']),
                            'y': int(math.ceil(piece_width)*FITS_MAPPING[s['side'][piece_alignment]]['y'])
                            }
                        offsets[adjacent_piece['id']] = '{x},{y}'.format(**offset)
                        break
                except KeyError:
                    continue

        cur.close()
        return offsets
Example #4
0
    def post(self):
        args = {}
        xhr_data = request.get_json()
        if xhr_data:
            args.update(xhr_data)
        args.update(request.form.to_dict(flat=True))
        args.update(request.args.to_dict(flat=True))

        if len(args.keys()) == 0:
            abort(400)

        # Start db operations
        cur = db.cursor()

        llamas = 0
        result = cur.execute(fetch_query_string("get-llama-count.sql")).fetchall()
        if result:
            (result, col_names) = rowify(result, cur.description)
            llamas = result[0]["llamas"]

        # TODO: Process args for llamaness
        processed = {"llama-check": True, "count": llamas}

        db.commit()
        cur.close()

        return json.jsonify(processed)
    def post(self):
        args = {}
        if request.form:
            args.update(request.form.to_dict(flat=True))

        # Verify args
        action = args.get("action")
        if action not in SLOT_ACTIONS:
            abort(400)

        player = args.get("player")
        if not player:
            abort(400)

        cur = db.cursor()

        if action == "add":
            cur.execute(fetch_query_string("add-new-user-puzzle-slot.sql"),
                        {"player": player})
        elif action == "delete":
            cur.execute(fetch_query_string("delete-user-puzzle-slot.sql"),
                        {"player": player})

        cur.close()
        db.commit()

        return redirect(
            "/chill/site/admin/player/details/{player}/".format(player=player))
Example #6
0
def update_user_points_and_m_date(player, points, score):
    cur = db.cursor()
    try:
        result = cur.execute(
            fetch_query_string("update_user_points_and_m_date.sql"),
            {
                "id": player,
                "points": points,
                "score": score,
                "POINTS_CAP": current_app.config["POINTS_CAP"],
            },
        )
    except sqlite3.IntegrityError:
        err_msg = {
            "msg":
            "Database integrity error. Does the player ({}) exist?".format(
                player),
            "status_code":
            400,
        }
        cur.close()
        return err_msg
    cur.close()
    db.commit()
    msg = {"rowcount": result.rowcount, "msg": "Executed", "status_code": 200}
    return msg
def migrate_next_puzzle(puzzle):
    cur = db.cursor()
    logging.info("migrating puzzle {}".format(puzzle))

    # Update any original that have an empty url
    cur.execute(query_update_puzzle_file_original_null_url, {'puzzle': puzzle})

    # Update any original that have a '0' for url
    cur.execute(query_update_puzzle_file_original_s3_url, {'puzzle': puzzle})

    db.commit()

    result = cur.execute(query_select_puzzle_file_to_migrate_from_s3, {
        'puzzle': puzzle
    }).fetchall()
    if result:
        (result, col_names) = rowify(result, cur.description)
        for item in result:
            migrate_s3_puzzle(item)

    result = cur.execute(query_select_puzzle_file_to_migrate_from_unsplash, {
        'puzzle': puzzle,
    }).fetchall()
    if result:
        (result, col_names) = rowify(result, cur.description)
        for item in result:
            migrate_unsplash_puzzle(item)

    cur.close()
Example #8
0
    def do_task(self):
        super().do_task()

        cur = db.cursor()
        result = cur.execute(
            read_query_file(
                "select-user-name-waiting-to-be-approved.sql")).fetchall()
        if result:
            self.log_task()
            names = []
            (result, col_names) = rowify(result, cur.description)
            for item in result:
                names.append("{approved_date} - {display_name}".format(**item))

            message = "\n".join(names)

            # Send a notification email (silent fail if not configured)
            current_app.logger.debug(message)
            if not current_app.config.get("DEBUG", True):
                try:
                    send_message(
                        current_app.config.get("EMAIL_MODERATOR"),
                        "Puzzle Massive - new names",
                        message,
                        current_app.config,
                    )
                except Exception as err:
                    current_app.logger.warning(
                        "Failed to send notification message. {}".format(err))
                    pass

        cur.close()
Example #9
0
    def get(self, puzzle_id):
        ""
        ip = request.headers.get("X-Real-IP")
        user = int(
            current_app.secure_cookie.get(u"user") or user_id_from_ip(ip))
        cur = db.cursor()
        result = cur.execute(
            fetch_query_string("select_viewable_puzzle_id.sql"),
            {
                "puzzle_id": puzzle_id
            },
        ).fetchall()
        if not result:
            # 404 if puzzle does not exist
            abort(404)

        (result, col_names) = rowify(result, cur.description)
        puzzle = result[0].get("puzzle")
        status = result[0].get("status")
        now = int(time.time())

        count = (redis_connection.zcount(
            "timeline:{puzzle}".format(puzzle=puzzle), now - 5 * 60, "+inf")
                 or 0)

        player_active_count = {"now": now, "count": count}

        cur.close()
        return json.jsonify(player_active_count)
Example #10
0
    def post(self, puzzle_id):
        "Ping and record the time in milliseconds for this player."
        now_ms = int(time.time() * 1000)
        response = {"message": "", "name": ""}

        user = current_app.secure_cookie.get(u"user") or user_id_from_ip(
            request.headers.get("X-Real-IP"), skip_generate=True)

        if user == None:
            response["message"] = "Player not currently logged in."
            response["name"] = "error"
            return make_response(json.jsonify(response), 400)

        user = int(user)

        cur = db.cursor()

        # Validate the puzzle_id
        result = cur.execute(
            fetch_query_string("select_viewable_puzzle_id.sql"),
            {
                "puzzle_id": puzzle_id
            },
        ).fetchall()
        if not result:
            response["message"] = "Invalid puzzle id."
            response["name"] = "error"
            cur.close()
            db.commit()
            return make_response(json.jsonify(response), 400)
        else:
            (result, col_names) = rowify(result, cur.description)
            puzzle = result[0].get("puzzle")
            status = result[0].get("status")
            if status != ACTIVE:
                response["message"] = "Puzzle not active"
                response["name"] = "invalid"
                cur.close()
                db.commit()
                return make_response(json.jsonify(response), 200)

        # publish to the puzzle channel the ping with the user id.  This will
        # allow that player to determine their latency.
        token = uuid.uuid4().hex[:4]
        pingtoken_key = get_pingtoken_key(puzzle, user, token)
        redis_connection.setex(pingtoken_key, 60, now_ms)

        current_app.logger.debug(
            "publish ping {puzzle_id}".format(puzzle_id=puzzle_id))
        sse.publish(
            "{user}:{token}".format(user=user, token=token),
            type="ping",
            channel="puzzle:{puzzle_id}".format(puzzle_id=puzzle_id),
        )
        response["message"] = "ping accepted"
        response["name"] = "accepted"
        response = make_response(json.jsonify(response), 202)
        cur.close()
        db.commit()
        return response
Example #11
0
    def get(self):
        cur = db.cursor()

        response = make_response(redirect("/chill/site/admin/puzzle/"))

        # Delete the shareduser cookie if it exists
        expires = datetime.datetime.utcnow() - datetime.timedelta(days=365)
        current_app.secure_cookie.set("shareduser",
                                      "",
                                      response,
                                      expires=expires)

        current_app.secure_cookie.set("user",
                                      str(ADMIN_USER_ID),
                                      response,
                                      expires_days=365)
        cur.execute(
            fetch_query_string("extend-cookie_expires-for-user.sql"),
            {"id": ADMIN_USER_ID},
        )
        db.commit()

        cur.close()

        return response
    def test_next_migrate_script(self):
        "Get next migrate script to run"
        with self.app.app_context():
            with self.app.test_client():
                cur = db.cursor()
                cur.execute(read_query_file("create_table_puzzle_massive.sql"))
                cur.execute(
                    read_query_file("upsert_puzzle_massive.sql"), {
                        "key": "database_version",
                        "label": "Database Version",
                        "description": "something",
                        "intvalue": 1,
                        "textvalue": None,
                        "blobvalue": None
                    })
                db.commit()
                script_files = [
                    "some/path/to/migrate_puzzle_massive_database_version_021.py",
                    "some/path/to/migrate_puzzle_massive_database_version_901.py",
                    "some/path/to/migrate_puzzle_massive_database_version_001.py",
                    "some/path/to/migrate_puzzle_massive_database_version_000.py",
                    "some/path/to/migrate_puzzle_massive_database_version_002.py",
                ]

                migrate_script = get_next_migrate_script(script_files)

                # The initial one should be migrate_puzzle_massive_database_version_000.py
                assert migrate_script == "some/path/to/migrate_puzzle_massive_database_version_002.py"
    def test_next_migrate_script_when_a_gap_exists(self):
        "Get next migrate script to run when a gap in version numbers exist"
        with self.app.app_context():
            with self.app.test_client():
                cur = db.cursor()
                cur.execute(read_query_file("create_table_puzzle_massive.sql"))
                cur.execute(
                    read_query_file("upsert_puzzle_massive.sql"), {
                        "key": "database_version",
                        "label": "Database Version",
                        "description": "something",
                        "intvalue": 21,
                        "textvalue": None,
                        "blobvalue": None
                    })
                db.commit()
                script_files = [
                    "some/path/to/migrate_puzzle_massive_database_version_021.py",
                    "some/path/to/migrate_puzzle_massive_database_version_901.py",
                    "some/path/to/migrate_puzzle_massive_database_version_001.py",
                    "some/path/to/migrate_puzzle_massive_database_version_000.py",
                    "some/path/to/migrate_puzzle_massive_database_version_002.py",
                ]

                self.assertRaises(MigrateGapError, get_next_migrate_script,
                                  script_files)
Example #14
0
    def get(self, puzzle_id):
        ""
        cur = db.cursor()
        result = cur.execute(
            fetch_query_string("select_viewable_puzzle_id.sql"),
            {
                "puzzle_id": puzzle_id
            },
        ).fetchall()
        if not result:
            # 404 if puzzle does not exist
            abort(404)

        (result, col_names) = rowify(result, cur.description)
        puzzle = result[0].get("puzzle")
        status = result[0].get("status")
        now = int(time.time())

        count = (redis_connection.zcount(
            "timeline:{puzzle}".format(puzzle=puzzle), now - 5 * 60, "+inf")
                 or 0)

        player_active_count = {"now": now, "count": count}

        cur.close()
        return make_response(json.jsonify(player_active_count), 200)
Example #15
0
    def __init__(self, ip):
        self.ip = ip
        self.headers = {"X-Real-IP": ip}

        self.api_host = "http://localhost:{PORTAPI}".format(
            PORTAPI=current_app.config["PORTAPI"])
        self.publish_host = "http://localhost:{PORTPUBLISH}".format(
            PORTPUBLISH=current_app.config["PORTPUBLISH"])

        cur = db.cursor()
        result = cur.execute(
            read_query_file("select-user-id-by-ip-and-no-password.sql"), {
                "ip": ip
            }).fetchall()
        if result:
            (result, col_names) = rowify(result, cur.description)
            shareduser = result[0]["id"]
            redis_connection.zrem("bannedusers", shareduser)
        cur.close()

        # get test user
        current_user_id = requests.get("{0}/current-user-id/".format(
            self.api_host),
                                       headers=self.headers)
        # print('ip {} and {}'.format(ip, current_user_id.cookies))
        self.shareduser_cookie = current_user_id.cookies["shareduser"]
        self.shareduser = int(current_user_id.content)
Example #16
0
def delete_puzzle_timeline(puzzle_id):
    ""
    cur = db.cursor()
    result = cur.execute(
        fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"),
        {
            "puzzle_id": puzzle_id
        },
    ).fetchall()
    if not result:
        err_msg = {"msg": "No puzzle found", "status_code": 400}
        cur.close()
        return err_msg

    (result, col_names) = rowify(result, cur.description)
    puzzle_data = result[0]
    puzzle = puzzle_data["id"]

    result = cur.execute(fetch_query_string("delete_puzzle_timeline.sql"),
                         {"puzzle": puzzle})
    cur.close()
    db.commit()

    redis_connection.delete("timeline:{puzzle}".format(puzzle=puzzle))
    redis_connection.delete("score:{puzzle}".format(puzzle=puzzle))

    msg = {"rowcount": result.rowcount, "msg": "Deleted", "status_code": 200}
    return msg
Example #17
0
def reward_player_for_score_threshold(player):
    cur = db.cursor()
    try:
        result = cur.execute(
            fetch_query_string(
                "reward_player_for_score_threshold--puzzle-instance-slot.sql"),
            {
                "player":
                player,
                "score_threshold":
                int(
                    current_app.config.get(
                        "REWARD_INSTANCE_SLOT_SCORE_THRESHOLD", '0'))
            },
        )

    except sqlite3.IntegrityError:
        err_msg = {
            "msg":
            "Database integrity error. Does the player ({}) exist?".format(
                player),
            "status_code":
            400,
        }
        cur.close()
        return err_msg
    cur.close()
    db.commit()
    msg = {"rowcount": result.rowcount, "msg": "Executed", "status_code": 200}
    return msg
def set_lost_unsplash_photo(puzzle):
    """
    remove the link
    the unsplash license is irrevocable: https://unsplash.com/license
    create a new preview photo from the original?
    """
    logging.info(
        "{puzzle} unsplash puzzle file {name} not found: {url}".format(
            **puzzle))

    cur = db.cursor()
    description = "{} / originally found on Unsplash".format(
        puzzle['description'])

    cur.execute(
        """update Puzzle set
    link = :link,
    description = :description,
    permission = -1 -- NOT PUBLIC
    where puzzle_id = :puzzle_id;
    """, {
            'puzzle_id': puzzle['puzzle_id'],
            'link': None,
            'description': description
        })

    insert_file = "update PuzzleFile set url = :url where puzzle = :puzzle and name = :name;"
    cur.execute(insert_file, {
        'puzzle': puzzle['puzzle'],
        'name': 'preview_full',
        'url': ''
    })

    db.commit()
    cur.close()
 def test_connection(self):
     "Connection to db"
     with self.app.app_context():
         with self.app.test_client():
             cursor = db.cursor()
             result = cursor.execute("select 'test' as test")
             (result, col_names) = rowify(result, cursor.description)
             assert result[0]["test"] == "test"
Example #20
0
    def get(self, puzzle_id):
        """
        deletePenalty: number;
        canFreeze: boolean;
        canDelete: boolean;
        canReset: boolean;
        hasActions: boolean;
        deleteDisabledMessage: string; //Not enough dots to delete this puzzle
        isFrozen: boolean;
        status: number;
        """
        ip = request.headers.get("X-Real-IP")
        user = int(current_app.secure_cookie.get("user") or user_id_from_ip(ip))

        cur = db.cursor()

        # validate the puzzle_id
        result = cur.execute(
            fetch_query_string("select-puzzle-details-for-puzzle_id.sql"),
            {"puzzle_id": puzzle_id},
        ).fetchall()
        if not result:
            # 400 if puzzle does not exist
            err_msg = {
                "msg": "No puzzle found",
            }
            cur.close()
            return make_response(json.jsonify(err_msg), 400)
        (result, col_names) = rowify(result, cur.description)
        puzzleData = result[0]

        (delete_penalty, can_delete, delete_disabled_message) = self.get_delete_prereq(
            puzzleData
        )
        response = {
            "canDelete": can_delete,
            "canFreeze": puzzleData.get("status") in (FROZEN, BUGGY_UNLISTED, ACTIVE),
            "canReset": puzzleData.get("permission") == PRIVATE
            and not puzzleData.get("is_original")
            and puzzleData.get("status") in (FROZEN, BUGGY_UNLISTED, ACTIVE, COMPLETED),
            "hasActions": puzzleData.get("status")
            in (
                FROZEN,
                ACTIVE,
                COMPLETED,
                BUGGY_UNLISTED,
                RENDERING_FAILED,
                REBUILD,
                IN_RENDER_QUEUE,
                MAINTENANCE,
            ),
            "deleteDisabledMessage": delete_disabled_message,
            "deletePenalty": delete_penalty,
            "isFrozen": puzzleData.get("status") == FROZEN,
            "status": puzzleData.get("status", -99),
        }
        cur.close()
        return make_response(json.jsonify(response), 200)
Example #21
0
def user_id_from_ip(ip, skip_generate=True):
    cur = db.cursor()

    shareduser = current_app.secure_cookie.get(u"shareduser")
    if shareduser != None:
        # Check if this shareduser is still valid and another user hasn't chosen
        # a bit icon.
        result = cur.execute(
            fetch_query_string("select-user-by-id-and-no-password.sql"),
            {
                "id": shareduser
            },
        ).fetchall()
        if result:
            cur.close()
            return int(shareduser)

    # Handle players that had a cookie in their browser, but then deleted it.
    # Or new players that are from the same ip that existing players are on.
    # These players are shown the new-player page.
    result = cur.execute(
        fetch_query_string("select-user-id-by-ip-and-no-password.sql"), {
            "ip": ip
        }).fetchall()
    user_id = ANONYMOUS_USER_ID

    # No ip in db so create it except if the skip_generate flag is set
    if not result:
        if skip_generate:
            cur.close()
            return None
        login = generate_user_login()
        cur.execute(
            fetch_query_string("add-new-user-for-ip.sql"),
            {
                "ip": ip,
                "login": login,
                "points": current_app.config["NEW_USER_STARTING_POINTS"],
            },
        )
        db.commit()

        result = cur.execute(
            fetch_query_string("select-user-id-by-ip-and-login.sql"),
            {
                "ip": ip,
                "login": login
            },
        ).fetchall()
        (result, col_names) = rowify(result, cur.description)
        user_id = result[0]["id"]
    else:
        (result, col_names) = rowify(result, cur.description)
        user_id = result[0]["id"]

    cur.close()
    return user_id
Example #22
0
def delete_puzzle_file(puzzle_id, file_name):
    ""

    cur = db.cursor()
    result = cur.execute(
        fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"),
        {
            "puzzle_id": puzzle_id
        },
    ).fetchall()
    if not result:
        err_msg = {"msg": "No puzzle found", "status_code": 400}
        cur.close()
        return err_msg

    (result, col_names) = rowify(result, cur.description)
    puzzle_data = result[0]
    puzzle = puzzle_data["id"]

    result = cur.execute(
        fetch_query_string("select_puzzle_file_with_attribution.sql"),
        {
            "puzzle": puzzle,
            "name": file_name
        },
    ).fetchall()
    if result:
        (result, col_names) = rowify(result, cur.description)
        puzzle_file_with_attribution_data = result[0]

        # Delete previous attribution if it exists
        if puzzle_file_with_attribution_data["attribution_id"]:
            result = cur.execute(
                fetch_query_string("delete_attribution_from_puzzle_file.sql"),
                {"id": puzzle_file_with_attribution_data["puzzle_file_id"]},
            )
            result = cur.execute(
                fetch_query_string("delete_attribution.sql"),
                {
                    "attribution":
                    puzzle_file_with_attribution_data["attribution_id"]
                },
            )

    result = cur.execute(
        fetch_query_string("delete_puzzle_file_with_name_for_puzzle.sql"),
        {
            "puzzle": puzzle,
            "name": file_name
        },
    )
    db.commit()
    cur.close()

    msg = {"rowcount": result.rowcount, "msg": "Deleted", "status_code": 200}
    return msg
Example #23
0
def add_to_timeline(puzzle_id, player, points=0, timestamp=None, message=""):
    ""

    if timestamp is None:
        _timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
    else:
        # TODO: Should verify timestamp is in ISO format.
        _timestamp = timestamp

    if not isinstance(points, int):
        err_msg = {"msg": "points needs to be an integer", "status_code": 400}
        return err_msg

    cur = db.cursor()
    result = cur.execute(
        fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"),
        {
            "puzzle_id": puzzle_id
        },
    ).fetchall()
    if not result:
        err_msg = {"msg": "No puzzle found", "status_code": 400}
        cur.close()
        return err_msg

    (result, col_names) = rowify(result, cur.description)
    puzzle_data = result[0]
    puzzle = puzzle_data["id"]

    # TODO: The message is not added to the Timeline DB table for now since that
    # information is not currently being used.
    try:
        result = cur.execute(
            fetch_query_string("insert_batchpoints_to_timeline.sql"),
            {
                "puzzle": puzzle,
                "player": player,
                "points": points,
                "timestamp": _timestamp,
            },
        )
    except sqlite3.IntegrityError:
        err_msg = {
            "msg":
            "Database integrity error. Does the player ({}) exist?".format(
                player),
            "status_code":
            400,
        }
        cur.close()
        return err_msg

    cur.close()
    db.commit()
    msg = {"rowcount": result.rowcount, "msg": "Inserted", "status_code": 200}
    return msg
Example #24
0
    def get(self):
        ""
        ip = request.headers.get("X-Real-IP")
        user = current_app.secure_cookie.get(u"user") or user_id_from_ip(ip)
        if user != None:
            user = int(user)
        args = {}
        if request.args:
            args.update(request.args.to_dict(flat=True))
        count = args.get("count")
        if count == None:
            return make_response(
                encoder.encode({"msg": "missing count param"}), 400)

        count = int(count)
        if count > 45:
            return make_response(
                encoder.encode({"msg": "Count arg is too high"}), 400)

        cur = db.cursor()
        now = int(time.time())
        active_players = frozenset(
            map(
                int,
                redis_connection.zrevrangebyscore("timeline", "+inf",
                                                  now - ACTIVE_RANGE),
            ))

        rank_slice = redis_connection.zrevrange("rank", 0, -1, withscores=True)

        ranks = []
        has_user_in_ranks = False
        user_in_ranks_index = -1
        for index, item in enumerate(rank_slice):
            (player, score) = map(int, item)
            if not has_user_in_ranks and player == user:
                has_user_in_ranks = True
                user_in_ranks_index = len(ranks)
            if player in active_players or player == user:
                ranks.append({
                    "id": player,
                    "score": score,
                })

        ranks_near_user = []
        if has_user_in_ranks:
            start = max(0, user_in_ranks_index - int(count / 2))
            end = min(len(ranks), user_in_ranks_index + int(count / 2))
            ranks_near_user = ranks[start:end]

        player_ranks = {
            "rank_slice": ranks_near_user,
        }

        cur.close()
        return encoder.encode(player_ranks)
Example #25
0
    def post(self):
        """Update shareduser to user"""

        # Prevent creating a new user if no support for cookies. Player should
        # have 'ot' already set by viewing the page.
        uses_cookies = current_app.secure_cookie.get(u"ot")
        if not uses_cookies:
            abort(400)

        cur = db.cursor()

        response = make_response("", 200)

        user = user_id_from_ip(request.headers.get("X-Real-IP"))
        if user == None:
            abort(400)
        user = int(user)

        # Only set new user if enough dots
        result = cur.execute(
            fetch_query_string("select-minimum-points-for-user.sql"),
            {
                "user":
                user,
                "points":
                current_app.config["NEW_USER_STARTING_POINTS"] +
                current_app.config["POINT_COST_FOR_CHANGING_BIT"],
            },
        ).fetchone()
        if result:
            self.register_new_user(user)
            # Save as a cookie
            current_app.secure_cookie.set(u"user",
                                          str(user),
                                          response,
                                          expires_days=365)
            # Remove shareduser
            expires = datetime.datetime.utcnow() - datetime.timedelta(days=365)
            current_app.secure_cookie.set(u"shareduser",
                                          "",
                                          response,
                                          expires=expires)

            cur.execute(
                fetch_query_string("decrease-user-points.sql"),
                {
                    "user": user,
                    "points":
                    current_app.config["POINT_COST_FOR_CHANGING_BIT"],
                },
            )

        cur.close()
        db.commit()
        return response
Example #26
0
def reset_puzzle_pieces_and_handle_errors(puzzle):
    cur = db.cursor()
    result = cur.execute(
        fetch_query_string("select_all_from_puzzle_for_id.sql"),
        {
            "id": puzzle
        },
    ).fetchall()
    if not result:
        cur.close()
        raise DataError("No puzzle found with that id.")

    (result, col_names) = rowify(result, cur.description)
    puzzle_data = result[0]
    cur.close()

    try:
        reset_puzzle_pieces(puzzle)
    # TODO: Fix handling of errors on puzzle reset pieces
    except Error as err:
        # Update puzzle status to RENDERING_FAILED
        r = requests.patch(
            "http://{HOSTAPI}:{PORTAPI}/internal/puzzle/{puzzle_id}/details/".
            format(
                HOSTAPI=current_app.config["HOSTAPI"],
                PORTAPI=current_app.config["PORTAPI"],
                puzzle_id=puzzle_data["puzzle_id"],
            ),
            json={"status": RENDERING_FAILED},
        )
        sse.publish(
            "status:{}".format(RENDERING_FAILED),
            channel="puzzle:{puzzle_id}".format(
                puzzle_id=puzzle_data["puzzle_id"]),
        )
        if r.status_code != 200:
            raise Exception("Puzzle details api error")

    # Update puzzle status to ACTIVE and sse publish
    r = requests.patch(
        "http://{HOSTAPI}:{PORTAPI}/internal/puzzle/{puzzle_id}/details/".
        format(
            HOSTAPI=current_app.config["HOSTAPI"],
            PORTAPI=current_app.config["PORTAPI"],
            puzzle_id=puzzle_data["puzzle_id"],
        ),
        json={"status": ACTIVE},
    )
    sse.publish(
        "status:{}".format(ACTIVE),
        channel="puzzle:{puzzle_id}".format(
            puzzle_id=puzzle_data["puzzle_id"]),
    )
    if r.status_code != 200:
        raise Exception("Puzzle details api error")
def migrate(config):
    "Migrate the sqlite3 database from the current database_version."
    cur = db.cursor()

    for filename in [
            "create_user_puzzle_index.sql",
    ]:
        cur.execute(read_query_file(filename))
        db.commit()

    cur.close()
    def test_next_migrate_script_when_none_are_found(self):
        "Get next migrate script when none are found"
        with self.app.app_context():
            with self.app.test_client():
                cur = db.cursor()
                cur.execute(read_query_file("create_table_puzzle_massive.sql"))
                db.commit()
                script_files = []

                self.assertRaises(MigrateError, get_next_migrate_script,
                                  script_files)
    def test_get_latest_version_when_no_migrate_scripts(self):
        "Get latest version when no migrate scripts"
        with self.app.app_context():
            with self.app.test_client():
                cur = db.cursor()
                cur.execute(read_query_file("create_table_puzzle_massive.sql"))
                db.commit()
                script_files = []

                self.assertRaises(Exception,
                                  get_latest_version_based_on_migrate_scripts,
                                  script_files)
Example #30
0
 def __init__(self, puzzle_id, ip):
     self.puzzle_id = puzzle_id
     self.ip = ip
     cur = db.cursor()
     result = cur.execute(
         "select id, table_width, table_height from Puzzle where puzzle_id = :puzzle_id;",
         {
             "puzzle_id": self.puzzle_id
         },
     ).fetchall()
     (result, col_names) = rowify(result, cur.description)
     self.puzzle_details = result[0]
     cur.close()