Files
Momentum/commands.py

309 lines
8.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import discord
from discord import app_commands
from db import get_db
from constants import VALORANT_RANKS, WORKOUTS, WORKOUT_CALORIES
from helpers import apply_rr
import random
def register(tree: app_commands.CommandTree):
# -------------------
# /create
# -------------------
@tree.command(name="create", description="Link your Valorant account")
@app_commands.describe(
val_tag="VALUSERNAME#TAG",
rank="Your current Valorant rank",
rr="Current RR (0-99)"
)
@app_commands.choices(
rank=[app_commands.Choice(name=r, value=r) for r in VALORANT_RANKS]
)
async def create(
interaction: discord.Interaction,
val_tag: str,
rank: str,
rr: int
):
db = get_db()
cur = db.cursor()
cur.execute("""
INSERT INTO users (discord_id, val_tag, rank, rr)
VALUES (%s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
val_tag=VALUES(val_tag),
rank=VALUES(rank),
rr=VALUES(rr)
""", (str(interaction.user.id), val_tag, rank, rr))
cur.close()
db.close()
await interaction.response.send_message("✅ Account linked", ephemeral=True)
# -------------------
# /match
# -------------------
from constants import ENABLED_WORKOUTS
enabled_workouts = [
app_commands.Choice(name=name, value=name)
for name in ENABLED_WORKOUTS.keys()
]
@tree.command(name="match", description="Log a Valorant match")
@app_commands.describe(
result="Match result",
rr_change="RR gained or lost",
kd="Kills/Deaths (e.g. 20/15)",
workout="Workout assigned for deaths"
)
@app_commands.choices(
result=[
app_commands.Choice(name="WIN", value="WIN"),
app_commands.Choice(name="LOSS", value="LOSS")
],
workout=enabled_workouts
)
async def match(
interaction: discord.Interaction,
result: str,
rr_change: int,
kd: str,
workout: str
):
try:
kills, deaths = map(int, kd.split("/"))
except ValueError:
await interaction.response.send_message(
"❌ K/D must be in format `kills/deaths` (e.g. 20/15)",
ephemeral=True
)
return
db = get_db()
cur = db.cursor(dictionary=True)
cur.execute(
"SELECT * FROM users WHERE discord_id=%s",
(str(interaction.user.id),)
)
user = cur.fetchone()
if not user:
await interaction.response.send_message(
"❌ You must run `/create` first",
ephemeral=True
)
return
# Enforce RR direction based on result
rr_delta = abs(rr_change)
if result == "LOSS":
rr_delta *= -1
new_rank, new_rr = apply_rr(
user["rank"],
user["rr"],
rr_delta
)
per_death = ENABLED_WORKOUTS.get(workout, 0)
if per_death == 0:
await interaction.response.send_message(
"❌ That workout is currently disabled.",
ephemeral=True
)
return
# Base workout calculation
workout_total = deaths * per_death
# Loss penalty
if result == "LOSS":
workout_total += 10
bonus_text = " (+10 loss penalty)" if result == "LOSS" else ""
# Calculate calories burned
cal_per_rep = WORKOUT_CALORIES.get(workout, 0)
calories_burned = round(workout_total * cal_per_rep, 2)
await interaction.response.send_message(
f"🏆 Match logged\n"
f"**Result:** {result}\n"
f"**Rank:** {new_rank} ({new_rr} RR)\n"
f"**Workout:** {workout} × {workout_total}{bonus_text}\n"
f"**Calories:** {calories_burned:.1f} Cal"
)
cur.execute("""
UPDATE users
SET
kills = kills + %s,
deaths = deaths + %s,
rank = %s,
rr = %s,
calories_burned = calories_burned + %s
WHERE discord_id = %s
""", (kills, deaths, new_rank, new_rr, float(calories_burned), str(interaction.user.id)))
cur.execute("""
INSERT INTO workouts (discord_id, workout, amount)
VALUES (%s, %s, %s)
ON DUPLICATE KEY UPDATE amount = amount + %s
""", (str(interaction.user.id), workout, workout_total, workout_total))
cur.close()
db.close()
await interaction.response.send_message(
f"🏆 Match logged\n"
f"**Rank:** {new_rank} ({new_rr} RR)\n"
f"**Workout:** {workout} × {workout_total}"
)
# -------------------
# /stats
# -------------------
@tree.command(name="stats", description="Show Momentum stats")
async def stats(
interaction: discord.Interaction,
user: discord.User | None = None
):
target = user or interaction.user
db = get_db()
cur = db.cursor(dictionary=True)
cur.execute(
"SELECT * FROM users WHERE discord_id=%s",
(str(target.id),)
)
u = cur.fetchone()
if not u:
await interaction.response.send_message(
"❌ User not found",
ephemeral=True
)
return
cur.execute(
"SELECT workout, amount FROM workouts WHERE discord_id=%s",
(str(target.id),)
)
workout_rows = cur.fetchall()
embed = discord.Embed(
title=f"{target.display_name}'s Momentum Stats",
color=discord.Color.red()
)
embed.add_field(
name="Rank",
value=f"{u['rank']} ({u['rr']} RR)",
inline=False
)
embed.add_field(
name="Valorant",
value=u["val_tag"],
inline=False
)
embed.add_field(
name="Kills / Deaths",
value=f"{u['kills']} / {u['deaths']}",
inline=False
)
embed.add_field(
name="Calories Burned",
value=f"{u.get('calories_burned', 0):.1f} Cal",
inline=False
)
workout_text = (
"\n".join(f"{w['workout']}: {w['amount']}" for w in workout_rows)
if workout_rows else "None"
)
embed.add_field(
name="Workouts Completed",
value=workout_text,
inline=False
)
cur.close()
db.close()
await interaction.response.send_message(embed=embed)
# -------------------
# /workout
# -------------------
@tree.command(name="workout", description="Get a random workout")
async def workout(interaction: discord.Interaction):
enabled = [w for w, v in WORKOUTS.items() if v > 0]
choice = random.SystemRandom().choice(enabled)
await interaction.response.send_message(
f"💪 **{choice}**\n"
f"{WORKOUTS[choice]} per death"
)
# -------------------
# /edit (admin)
# -------------------
@tree.command(name="edit", description="Edit a user's stats (Admin)")
@app_commands.choices(
rank=[app_commands.Choice(name=r, value=r) for r in VALORANT_RANKS]
)
async def edit(
interaction: discord.Interaction,
user: discord.User,
rank: str | None = None,
rr: int | None = None,
val_tag: str | None = None
):
if not interaction.user.guild_permissions.administrator:
await interaction.response.send_message(
"❌ Admins only",
ephemeral=True
)
return
fields = []
values = []
if rank:
fields.append("rank=%s")
values.append(rank)
if rr is not None:
fields.append("rr=%s")
values.append(rr)
if val_tag:
fields.append("val_tag=%s")
values.append(val_tag)
if not fields:
await interaction.response.send_message(
"Nothing to update",
ephemeral=True
)
return
values.append(str(user.id))
db = get_db()
cur = db.cursor()
cur.execute(
f"UPDATE users SET {', '.join(fields)} WHERE discord_id=%s",
values
)
cur.close()
db.close()
await interaction.response.send_message("✏️ User updated")