modified: app.py
This commit is contained in:
106
app.py
106
app.py
@@ -136,6 +136,81 @@ TEAM_EMOTE_OVERRIDES: Dict[str, str] = {
|
||||
"default": "<:neutrality:1432391681059197102>",
|
||||
}
|
||||
|
||||
# Role mapping for ELO tiers (IDs provided by user)
|
||||
# Assumption: Top tier is >= 900 ELO rather than strictly >900,
|
||||
# to avoid leaving 900 unassigned. Adjust if you want 900 handled differently.
|
||||
STANDARD_ELO_ROLE_IDS = {
|
||||
"gte_900": 1432368177014374497,
|
||||
"851_899": 1432368177014374496,
|
||||
"801_850": 1432368177014374495,
|
||||
"eq_800": 1432368177014374494,
|
||||
"751_799": 1432368177014374493,
|
||||
"701_750": 1432368177014374492,
|
||||
"lt_700": 1432368177014374491,
|
||||
}
|
||||
|
||||
COMPETITIVE_ELO_ROLE_IDS = {
|
||||
"gte_900": 1432368177030893672,
|
||||
"851_899": 1432368177030893671,
|
||||
"801_850": 1432368177030893670,
|
||||
"eq_800": 1432368177030893669,
|
||||
"751_799": 1432368177030893668,
|
||||
"701_750": 1432368177014374499,
|
||||
"lt_700": 1432368177014374498,
|
||||
}
|
||||
|
||||
def _role_id_for_elo(elo: int, category: str) -> Optional[int]:
|
||||
"""Return the role ID for the given ELO and category ('standard'|'competitive')."""
|
||||
ids = STANDARD_ELO_ROLE_IDS if category == "standard" else COMPETITIVE_ELO_ROLE_IDS
|
||||
if elo >= 900:
|
||||
return ids["gte_900"]
|
||||
if 851 <= elo <= 899:
|
||||
return ids["851_899"]
|
||||
if 801 <= elo <= 850:
|
||||
return ids["801_850"]
|
||||
if elo == 800:
|
||||
return ids["eq_800"]
|
||||
if 751 <= elo <= 799:
|
||||
return ids["751_799"]
|
||||
if 701 <= elo <= 750:
|
||||
return ids["701_750"]
|
||||
# < 700
|
||||
return ids["lt_700"]
|
||||
|
||||
def _category_role_ids(category: str) -> List[int]:
|
||||
ids = STANDARD_ELO_ROLE_IDS if category == "standard" else COMPETITIVE_ELO_ROLE_IDS
|
||||
return list(ids.values())
|
||||
|
||||
async def update_member_elo_role(member: discord.Member, elo: int, category: str, reason: Optional[str] = None):
|
||||
"""Ensure the member has exactly one rank role for the given category matching their ELO.
|
||||
- category: 'standard' or 'competitive'
|
||||
"""
|
||||
if member is None or member.guild is None:
|
||||
return
|
||||
try:
|
||||
guild = member.guild
|
||||
target_role_id = _role_id_for_elo(elo, category)
|
||||
if not target_role_id:
|
||||
return
|
||||
target_role = guild.get_role(int(target_role_id))
|
||||
if not target_role:
|
||||
return # Role not found in this guild
|
||||
|
||||
# Remove any other roles from the same category
|
||||
category_ids = set(_category_role_ids(category))
|
||||
roles_to_remove = [r for r in member.roles if r.id in category_ids and r.id != target_role.id]
|
||||
if roles_to_remove:
|
||||
await member.remove_roles(*roles_to_remove, reason=reason)
|
||||
|
||||
# Add the target role if missing
|
||||
if target_role not in member.roles:
|
||||
await member.add_roles(target_role, reason=reason)
|
||||
except discord.Forbidden:
|
||||
# Missing permissions or role hierarchy issue
|
||||
logging.warning(f"Insufficient permissions to modify roles for {member} in category {category}")
|
||||
except discord.HTTPException as e:
|
||||
logging.warning(f"Failed to update roles for {member}: {e}")
|
||||
|
||||
# Emoji and formatting helpers
|
||||
def _all_accessible_emojis(ctx: commands.Context) -> List[discord.Emoji]:
|
||||
"""Return emojis from current guild plus all guilds the bot is in."""
|
||||
@@ -777,6 +852,27 @@ async def hoi4end(ctx, game_name: str, winner_team: str):
|
||||
"UPDATE games SET status = 'finished', winner_team = %s, finished_at = CURRENT_TIMESTAMP WHERE id = %s",
|
||||
(final_result, game['id'])
|
||||
)
|
||||
|
||||
# After DB updates, try to sync Discord roles for affected players (only for this game's category)
|
||||
try:
|
||||
guild = ctx.guild
|
||||
if guild:
|
||||
for change in elo_changes:
|
||||
member = guild.get_member(change['discord_id'])
|
||||
if member is None:
|
||||
try:
|
||||
member = await guild.fetch_member(change['discord_id'])
|
||||
except Exception:
|
||||
member = None
|
||||
if member:
|
||||
await update_member_elo_role(
|
||||
member,
|
||||
change['new_elo'],
|
||||
game['game_type'],
|
||||
reason=f"HOI4 {game['game_type']} ELO updated in '{game_name}'"
|
||||
)
|
||||
except Exception as e:
|
||||
logging.warning(f"Role sync after game end failed: {e}")
|
||||
|
||||
# Create result embed
|
||||
if is_draw:
|
||||
@@ -963,6 +1059,16 @@ async def hoi4stats(ctx, user: Optional[discord.Member] = None):
|
||||
)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
# Try to keep user's roles in sync for both categories when stats are viewed
|
||||
try:
|
||||
if ctx.guild and isinstance(target_user, discord.Member):
|
||||
await update_member_elo_role(
|
||||
target_user, player['standard_elo'], 'standard', reason='HOI4 stats viewed: role sync')
|
||||
await update_member_elo_role(
|
||||
target_user, player['competitive_elo'], 'competitive', reason='HOI4 stats viewed: role sync')
|
||||
except Exception as e:
|
||||
logging.warning(f"Role sync on stats failed: {e}")
|
||||
|
||||
except Exception as e:
|
||||
await ctx.send(f"❌ Error getting stats: {str(e)}")
|
||||
|
||||
Reference in New Issue
Block a user