Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 77 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ async def update_homepage_cache() -> None:
SELECT COUNT(*) AS cnt
FROM users
WHERE privileges & 1
"""
""",
)
await redis.set("akatsuki:registered_users", str(user_count["cnt"]))

Expand All @@ -499,7 +499,7 @@ async def update_homepage_cache() -> None:
SELECT COUNT(*) AS cnt
FROM beatmaps
WHERE ranked IN (2, 3)
"""
""",
)
await redis.set("akatsuki:ranked_beatmaps", str(beatmap_count["cnt"]))

Expand All @@ -509,7 +509,7 @@ async def update_homepage_cache() -> None:
FROM user_stats
INNER JOIN users ON users.id = user_stats.user_id
WHERE users.privileges & 1
"""
""",
)
years = int(playtime["total_playtime"]) // (60 * 60 * 24 * 365)
await redis.set("akatsuki:total_playtime_years", str(years))
Expand All @@ -531,6 +531,79 @@ async def update_homepage_cache() -> None:
print(f"Updated homepage cache in {time.time() - start_time:.2f} seconds")


CHAMPION_BADGE_ID = 67
FORMER_CHAMPION_BADGE_ID = 66


async def update_champion_badges() -> None:
for rx in (0, 1, 2):
if rx == 0:
redis_board = "leaderboard"
modes = ("std", "taiko", "ctb", "mania")
elif rx == 1:
redis_board = "relaxboard"
modes = ("std", "taiko", "ctb")
else: # rx == 2:
redis_board = "autoboard"
modes = ("std",)

for mode in modes:
mode_int = mode + (4 * rx)
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type error: attempting to concatenate string and integer. The variable mode is a string (e.g., "std", "taiko", "ctb", "mania") but the code attempts to add it to an integer. Based on line 100 in the codebase, this should be mode_int = STR_TO_INT_MODE[mode] + (4 * rx) to correctly calculate the mode integer value.

Suggested change
mode_int = mode + (4 * rx)
mode_int = STR_TO_INT_MODE[mode] + (4 * rx)

Copilot uses AI. Check for mistakes.
rank_key = f"ripple:{redis_board}:{mode}"

# this is updated in a cron so we need to also check current rank one
users_who_peaked_at_rank_one = list(
Comment thread
cmyui marked this conversation as resolved.
await db.fetchall(
"SELECT DISTINCT user_id FROM user_profile_history WHERE mode = %s AND `rank` = 1",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you check how many users are going to receive a badge that don't currently have it, from the switch from manual -> auto based on user_profile_history data?

Copy link
Copy Markdown
Member

@cmyui cmyui Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a bit to consider here re. cases where someone cheated their way to #1 then got banned/unbanned -- I think this system would grant them the "former champion" badge in that case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a bit to consider here re. cases where someone cheated their way to #1 then got banned/unbanned

if we're not wiping this table when wiping a user for an unban then that's an issue in it's own way - that would mean their peak rank on their profile would already appear as whatever they peaked while cheating 😳

[mode_int],
),
)

current_rank_one_user_id = await redis.zrevrange(rank_key, 0, 0)
users_who_peaked_at_rank_one.append({"user_id": current_rank_one_user_id})
Copy link
Copy Markdown
Member

@cmyui cmyui Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this fetched separately to guard against the case where the #1 is not yet inserted into user_profile_history? (iirc the job runs nightly?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the API endpoint that the website uses to fetch peak rank does similar functionality (fetches peak from database and also current, takes whichever is lower)

Comment on lines +562 to +563
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The zrevrange command returns a list, but the code treats it as a single value. This should extract the first element from the returned list (if it exists) before appending. Consider using: current_rank_one_users = await redis.zrevrange(rank_key, 0, 0) followed by conditional logic to append only if the list is not empty, extracting the first element: if current_rank_one_users: users_who_peaked_at_rank_one.append({"user_id": current_rank_one_users[0]}).

Suggested change
current_rank_one_user_id = await redis.zrevrange(rank_key, 0, 0)
users_who_peaked_at_rank_one.append({"user_id": current_rank_one_user_id})
current_rank_one_users = await redis.zrevrange(rank_key, 0, 0)
if current_rank_one_users:
users_who_peaked_at_rank_one.append({"user_id": current_rank_one_users[0]})

Copilot uses AI. Check for mistakes.

for user in users_who_peaked_at_rank_one:
redis_rank = await redis.zrevrank(rank_key, user["user_id"])
current_rank = redis_rank + 1 if redis_rank is not None else None

if current_rank == 1:
await db.execute(
"DELETE FROM user_badges WHERE user = %s AND badge = %s",
[user["user_id"], FORMER_CHAMPION_BADGE_ID],
)

# user_badges has no unique key on (user, badge) so we have to check manually :(
existing_champion_badge = await db.fetch(
"SELECT 1 FROM user_badges WHERE user = %s AND badge = %s",
[user["user_id"], CHAMPION_BADGE_ID],
)

if not existing_champion_badge:
await db.execute(
"INSERT INTO user_badges (user, badge) (%s, %s)"[
user["user_id"], CHAMPION_BADGE_ID,
],
Comment on lines +583 to +585
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid SQL syntax using bracket notation instead of VALUES clause, and parameters should be passed as a separate argument to db.execute(). The correct format should be: "INSERT INTO user_badges (user, badge) VALUES (%s, %s)", [user["user_id"], CHAMPION_BADGE_ID] where the SQL query and parameters are separate arguments to db.execute().

Copilot uses AI. Check for mistakes.
)
else:
await db.execute(
"DELETE FROM user_badges WHERE user = %s AND badge = %s",
[user["user_id"], CHAMPION_BADGE_ID],
)

# user_badges has no unique key on (user, badge) so we have to check manually :(
existing_former_champion_badge = await db.fetch(
"SELECT 1 FROM user_badges WHERE user = %s AND badge = %s",
[user["user_id"], FORMER_CHAMPION_BADGE_ID],
)

if not existing_former_champion_badge:
await db.execute(
"INSERT INTO user_badges (user, badge) (%s, %s)"[
user["user_id"], FORMER_CHAMPION_BADGE_ID,
],
)


Comment on lines +601 to +606
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid SQL syntax using bracket notation instead of VALUES clause, and parameters should be passed as a separate argument to db.execute(). The correct format should be: "INSERT INTO user_badges (user, badge) VALUES (%s, %s)", [user["user_id"], FORMER_CHAMPION_BADGE_ID] where the SQL query and parameters are separate arguments to db.execute().

Suggested change
"INSERT INTO user_badges (user, badge) (%s, %s)"[
user["user_id"], FORMER_CHAMPION_BADGE_ID,
],
)
"INSERT INTO user_badges (user, badge) VALUES (%s, %s)",
[user["user_id"], FORMER_CHAMPION_BADGE_ID],
)

Copilot uses AI. Check for mistakes.
async def main() -> None:
print("Starting Akatsuki cron")

Expand All @@ -543,6 +616,7 @@ async def main() -> None:
await fix_supporter_badges()
await update_total_submitted_score_counts()
await freeze_expired_freeze_timers()
await update_champion_badges()
await update_top_plays()
await update_homepage_cache()

Expand Down
Loading