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()
    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))
    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"
Esempio n. 4
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 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)
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
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
Esempio n. 9
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 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))
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()
Esempio n. 12
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
Esempio n. 13
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
Esempio n. 14
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
Esempio n. 15
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
    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 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_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)
    def post(self):
        "Route is protected by basic auth in nginx"
        args = {}
        if request.form:
            args.update(request.form.to_dict(flat=True))

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

        name_register_ids = request.form.getlist("name_register_id")
        if len(name_register_ids) == 0:
            abort(400)
        if not isinstance(name_register_ids, list):
            name_register_ids = [name_register_ids]

        name_register_users = request.form.getlist("name_register_user")
        if len(name_register_users) == 0:
            abort(400)
        if not isinstance(name_register_users, list):
            name_register_users = [name_register_users]

        cur = db.cursor()

        if action == "reject":

            def each(name_register_ids):
                for id in name_register_ids:
                    yield {"id": id}

            cur.executemany(
                fetch_query_string("reject-name-on-name-register-for-id.sql"),
                each(name_register_ids),
            )

        db.commit()
        cur.close()

        routes_to_purge = []
        for user in name_register_users:
            routes_to_purge.append(
                "/chill/site/internal/player-bit/{}/".format(user))
        purge_route_from_nginx_cache(
            "\n".join(routes_to_purge),
            current_app.config.get("PURGEURLLIST"),
        )

        return redirect("/chill/site/admin/name-register-review/")
Esempio n. 20
0
    def get(self, anonymous_login):
        "Set the user cookie if correct anon bit link."
        login = anonymous_login[:-13]
        password = anonymous_login[-13:]
        cur = db.cursor()

        response = make_response(redirect("/"))

        result = cur.execute(fetch_query_string("select-user-by-login.sql"), {
            "login": login
        }).fetchall()

        if not result:
            cur.close()
            return make_response("no user", 404)

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

        expires = datetime.datetime.utcnow() - datetime.timedelta(days=365)
        if crypt.crypt(password,
                       user_data["password"]) == user_data["password"]:
            current_app.secure_cookie.set("shareduser",
                                          "",
                                          response,
                                          expires=expires)
            current_app.secure_cookie.set("user",
                                          str(user_data["id"]),
                                          response,
                                          expires_days=365)
            cur.execute(
                fetch_query_string("extend-cookie_expires-for-user.sql"),
                {"id": user_data["id"]},
            )
            db.commit()
        else:
            # Invalid anon login; delete cookie just in case it's there
            current_app.secure_cookie.set("user",
                                          "",
                                          response,
                                          expires=expires)

        cur.close()

        return response
Esempio n. 21
0
def update_user_name_approved_for_approved_date_due():
    cur = db.cursor()
    try:
        result = cur.execute(
            fetch_query_string(
                "update-user-name-approved-for-approved_date-due.sql"), )
    except sqlite3.IntegrityError:
        err_msg = {
            "msg":
            "Database integrity error. update_user_name_approved_for_approved_date_due",
            "status_code": 400,
        }
        cur.close()
        return err_msg
    cur.close()
    db.commit()
    msg = {"rowcount": result.rowcount, "msg": "Executed", "status_code": 200}
    return msg
Esempio n. 22
0
    def get(self):
        "Return an object to be used by the generateBitLink js call"

        user = current_app.secure_cookie.get("user")
        if user is None:
            return make_response("no user", 403)
        user = int(user)

        (p_string, password) = generate_password()

        # Store encrypted password in db
        cur = db.cursor()
        try:
            result = cur.execute(
                fetch_query_string("select-login-from-user.sql"), {
                    "id": user
                }).fetchall()
        except IndexError:
            # user may have been added after a db rollback
            cur.close()
            return make_response("no user", 404)

        if not result:
            cur.close()
            return make_response("no user", 404)

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

        cur.execute(
            fetch_query_string("update-password-for-user.sql"),
            {
                "id": user,
                "password": password
            },
        )
        db.commit()

        cur.close()
        data = {
            "bit":
            "".join(["", "/puzzle-api/bit/", user_data["login"], p_string])
        }
        return make_response(json.jsonify(data), 200)
Esempio n. 23
0
    def register_new_user(self, user_id):
        """Update initial ip tracked user to now be cookie tracked with a password."""
        cur = db.cursor()

        login = generate_user_login()
        (p_string, password) = generate_password()

        cur.execute(
            fetch_query_string("set-initial-password-for-user.sql"),
            {
                "id": user_id,
                "password": password,
                "ip": request.headers.get("X-Real-IP"),
            },
        )
        # Other players on the same network that are tracked by shareduser
        # cookie will have it updated to a new value.
        db.commit()
        cur.close()
Esempio n. 24
0
def add_puzzle_file(puzzle_id, file_name, url, attribution=None):
    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"]

    if attribution:
        attribution_result = cur.execute(
            fetch_query_string("insert_attribution.sql"), attribution)
        attribution_id = attribution_result.lastrowid
        result = cur.execute(
            fetch_query_string("add-puzzle-file-with-attribution.sql"),
            {
                "puzzle": puzzle,
                "name": file_name,
                "url": url,
                "attribution": attribution_id,
            },
        )
    else:
        result = cur.execute(
            fetch_query_string("add-puzzle-file.sql"),
            {
                "puzzle": puzzle,
                "name": file_name,
                "url": url
            },
        )
    db.commit()
    cur.close()
    msg = {"rowcount": result.rowcount, "msg": "Inserted", "status_code": 200}
    return msg
Esempio n. 25
0
def update_points_to_minimum_for_all_users(minimum):
    cur = db.cursor()
    try:
        result = cur.execute(
            fetch_query_string("update_points_to_minimum_for_all_users.sql"),
            {"minimum": minimum},
        )
    except sqlite3.IntegrityError:
        err_msg = {
            "msg":
            "Database integrity error. update_points_to_minimum_for_all_users",
            "status_code": 400,
        }
        cur.close()
        return err_msg
    cur.close()
    db.commit()
    msg = {"rowcount": result.rowcount, "msg": "Executed", "status_code": 200}
    return msg
    def test_get_latest_version_based_on_migrate_scripts(self):
        "Get latest version based on 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 = [
                    "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",
                ]

                latest_version = get_latest_version_based_on_migrate_scripts(
                    script_files)

                assert latest_version == 902
    def test_next_migrate_script_for_initial_migration(self):
        "Get next migrate script to run for the initial migration"
        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 = [
                    "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_000.py"
Esempio n. 28
0
    def get(self):
        "Show a batch of available bit icon names"

        save_cookie = False
        offset_seconds = current_app.secure_cookie.get(u"ot")
        if not offset_seconds:
            save_cookie = True
            offset_seconds = str(randint(1, 900))
        offset_time = "{} seconds".format(int(offset_seconds))

        limit = request.args.get("limit")
        if not limit:
            limit = 7
        try:
            limit = int(limit)
        except ValueError:
            limit = 7
        if limit not in (48, 7):
            limit = 7

        cur = db.cursor()
        # List of bit icon names that are available
        result = cur.execute(
            fetch_query_string("select_random_bit_batch.sql"),
            {
                "offset_time": offset_time,
                "limit": limit
            },
        ).fetchall()
        (result, col_names) = rowify(result, cur.description)
        bits = [x["icon"] for x in result]

        response = make_response(encoder.encode({"data": bits}), 200)
        if save_cookie:
            current_app.secure_cookie.set(u"ot",
                                          str(offset_seconds),
                                          response,
                                          expires_days=1)

        cur.close()
        db.commit()
        return response
Esempio n. 29
0
def update_bit_icon_expiration(player):
    cur = db.cursor()
    try:
        result = cur.execute(
            fetch_query_string("update_bit_icon_expiration.sql"),
            {"user": player},
        )
    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
Esempio n. 30
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