paper-dynasty-discord/cogs/economy_new/scouting.py
Cal Corum 33260fd5fa feat: add buy-scout-token option when daily limit exceeded
When a user exceeds their 2/day scout token limit, they are now offered
a button to purchase an extra token for 200₼ instead of being blocked.
Updates /scout-tokens message to mention the purchase option.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:12:35 -05:00

97 lines
3.0 KiB
Python

"""
Scouting Cog — Scout token management and expired opportunity cleanup.
"""
import datetime
import logging
import discord
from discord import app_commands
from discord.ext import commands, tasks
from api_calls import db_get
from helpers.scouting import (
SCOUT_TOKEN_COST,
SCOUT_TOKENS_PER_DAY,
get_scout_tokens_used,
)
from helpers.utils import int_timestamp
from helpers.discord_utils import get_team_embed
from helpers.main import get_team_by_owner
logger = logging.getLogger("discord_app")
class Scouting(commands.Cog):
"""Scout token tracking and expired opportunity cleanup."""
def __init__(self, bot):
self.bot = bot
self.cleanup_expired.start()
async def cog_unload(self):
self.cleanup_expired.cancel()
@app_commands.command(
name="scout-tokens",
description="Check how many scout tokens you have left today",
)
async def scout_tokens_command(self, interaction: discord.Interaction):
await interaction.response.defer(ephemeral=True)
team = await get_team_by_owner(interaction.user.id)
if not team:
await interaction.followup.send(
"You need a Paper Dynasty team first!",
ephemeral=True,
)
return
tokens_used = await get_scout_tokens_used(team["id"])
tokens_remaining = max(0, SCOUT_TOKENS_PER_DAY - tokens_used)
embed = get_team_embed(title="Scout Tokens", team=team)
embed.description = (
f"**{tokens_remaining}** of **{SCOUT_TOKENS_PER_DAY}** tokens remaining today.\n\n"
f"Tokens reset at midnight Central."
)
if tokens_remaining == 0:
embed.description += (
f"\n\nYou've used all your free tokens! "
f"You can still scout by purchasing a token for **{SCOUT_TOKEN_COST}₼**."
)
await interaction.followup.send(embed=embed, ephemeral=True)
@tasks.loop(minutes=15)
async def cleanup_expired(self):
"""Log expired unclaimed scout opportunities.
This is a safety net — the ScoutView's on_timeout handles the UI side.
If the bot restarted mid-scout, those views are lost; this just logs it.
"""
try:
now = int_timestamp(datetime.datetime.now())
expired = await db_get(
"scout_opportunities",
params=[
("claimed", False),
("expired_before", now),
],
)
if expired and expired.get("count", 0) > 0:
logger.info(
f"Found {expired['count']} expired unclaimed scout opportunities"
)
except Exception as e:
logger.debug(f"Scout cleanup check failed (API may not be ready): {e}")
@cleanup_expired.before_loop
async def before_cleanup(self):
await self.bot.wait_until_ready()
async def setup(bot):
await bot.add_cog(Scouting(bot))