Skip to content

Automate (former) champion badges#11

Open
tsunyoku wants to merge 4 commits into
mainfrom
automate-champion-badges
Open

Automate (former) champion badges#11
tsunyoku wants to merge 4 commits into
mainfrom
automate-champion-badges

Conversation

@tsunyoku
Copy link
Copy Markdown
Contributor

@tsunyoku tsunyoku commented Dec 7, 2024

One day I'd love for score submission to be split into components and be able to do this event-based, but this is still better than manual for now.

This will be a requirement for full-stack automation of the badge as I'd like to automate the Discord roles as well via the new Discord linking functionality.

Comment thread main.py
Comment thread main.py Outdated
)

# user_badges has no unique key on (user, badge) so we have to check manually :(
existing_former_champion_badge = await db.fetch(
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.

var is named former_champion but it's checking against CHAMPION_BADGE_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.

nit: it's probably best to use INSERT INTO ... IF NOT EXISTS ... ELSE UPDATE or w/e to make it one query, if possible

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.

not possible due to the lack of unique constraint since that's how it decides if it "exists" or would conflict etc. - needs to be resolved on the table layer first

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.

var is named former_champion but it's checking against CHAMPION_BADGE_ID?

note to self: don't trust F2

Comment thread main.py
)

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 thread main.py
# this is updated in a cron so we need to also check current rank one
users_who_peaked_at_rank_one = list(
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 😳

@cmyui
Copy link
Copy Markdown
Member

cmyui commented Jan 16, 2026

@claude what are your thoughts on this change? could you clone and take a look around the osuAkatsuki organization's other repo's code (e.g. score service) and see if it'll do as we desire? any other review?

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR automates the assignment and removal of champion badges (badge ID 67) and former champion badges (badge ID 66) based on leaderboard rankings. The automation checks users who have ever reached rank #1 across all game modes and assigns the appropriate badge based on their current rank.

Changes:

  • Added update_champion_badges() function to automatically manage champion and former champion badges
  • Added trailing commas to SQL queries for consistency
  • Integrated badge automation into the main cron job execution

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread main.py
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.
Comment thread main.py
Comment on lines +583 to +585
"INSERT INTO user_badges (user, badge) (%s, %s)"[
user["user_id"], CHAMPION_BADGE_ID,
],
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.
Comment thread main.py
Comment on lines +601 to +606
"INSERT INTO user_badges (user, badge) (%s, %s)"[
user["user_id"], FORMER_CHAMPION_BADGE_ID,
],
)


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.
Comment thread main.py
Comment on lines +562 to +563
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

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants