ajout de match régulier pour les équipes et de pratiques

Ajout d'un profil public cliquable pour les utilisateurs
déplacement du profil
This commit is contained in:
cedrick2711
2026-07-28 12:39:53 -04:00
parent 69b6e217ae
commit b982cd0318
20 changed files with 2132 additions and 225 deletions
+99 -19
View File
@@ -176,10 +176,32 @@ class TeamTryoutsBot(commands.Bot):
async def _send_schedule_notification(self, user_id: int, event_type: str,
event_title: str, event_date: str,
event_time: str, reference_id: int) -> int:
"""Send a schedule addition notification to a player."""
"""Send a schedule addition notification to a player.
Args:
user_id: Database primary key of the User (NOT Discord user ID).
event_type: 'match' or 'tryout'.
event_title: Title of the event.
event_date: Date string.
event_time: Time string.
reference_id: ID of the MatchParticipant or TryoutRegistration record.
"""
try:
user = await self.fetch_user(user_id)
# Look up the DB user to get their Discord user ID
from models import User as DBUser
db_user = DBUser.query.get(user_id)
if not db_user:
logger.warning(f"DB user {user_id} not found for schedule notification")
return None
if not db_user.discord_user_id:
logger.warning(f"User {db_user.username} has no Discord user ID, cannot send DM")
return None
discord_uid = int(db_user.discord_user_id)
user = await self.fetch_user(discord_uid)
if not user:
logger.warning(f"Could not fetch Discord user {discord_uid}")
return None
event_name = "Match" if event_type == 'match' else "Tryout"
@@ -202,7 +224,7 @@ class TeamTryoutsBot(commands.Bot):
# Track this pending request
self.pending_requests[msg.id] = {'type': 'schedule_addition', 'id': reference_id, 'event_type': event_type}
logger.info(f"Sent {event_type} schedule notification, message_id={msg.id}")
logger.info(f"Sent {event_type} schedule notification to {db_user.username}, message_id={msg.id}")
return msg.id
except Exception as e:
@@ -226,15 +248,28 @@ class TeamTryoutsBot(commands.Bot):
await original_message.channel.send("⚠️ You are not the intended recipient.")
return
# Capture data before commit (to avoid expired session issues)
player = request.player
coach_obj = request.coach
player_full_name = player.full_name
player_discord_id = player.discord_user_id
request.status = 'approved'
request.responded_at = datetime.utcnow()
db.session.commit()
await original_message.channel.send(
f"✅ You have **approved** the One on One session with {request.player.full_name}."
f"✅ You have **approved** the One on One session with {player_full_name}."
)
await self.notify_player_about_one_on_one(request, approved=True)
# Pass the pre-fetched data to avoid session expiration issues
await self.notify_player_about_one_on_one_direct(
player_discord_id=player_discord_id,
player_full_name=player_full_name,
coach_full_name=coach_obj.full_name,
request=request,
approved=True
)
del self.pending_requests[message_id]
except Exception as e:
@@ -257,6 +292,12 @@ class TeamTryoutsBot(commands.Bot):
await original_message.channel.send("⚠️ You are not the intended recipient.")
return
# Capture data before commit (to avoid expired session issues)
player = request.player
coach_obj = request.coach
player_full_name = player.full_name
player_discord_id = player.discord_user_id
refusal_note = None
try:
async for reply in original_message.channel.history(limit=20):
@@ -272,14 +313,21 @@ class TeamTryoutsBot(commands.Bot):
request.coach_rejection_message = refusal_note
db.session.commit()
rejection_msg = f"❌ You have **rejected** the One on One session with {request.player.full_name}."
rejection_msg = f"❌ You have **rejected** the One on One session with {player_full_name}."
if refusal_note:
rejection_msg += f"\n**Reason:** {refusal_note}"
else:
rejection_msg += "\n\n️ The player has been notified that you are not available."
await original_message.channel.send(rejection_msg)
await self.notify_player_about_one_on_one(request, approved=False, refusal_note=refusal_note)
await self.notify_player_about_one_on_one_direct(
player_discord_id=player_discord_id,
player_full_name=player_full_name,
coach_full_name=coach_obj.full_name,
request=request,
approved=False,
refusal_note=refusal_note
)
del self.pending_requests[message_id]
except Exception as e:
@@ -336,32 +384,64 @@ class TeamTryoutsBot(commands.Bot):
logger.error(f"Error handling attendance decline: {e}")
async def notify_player_about_one_on_one(self, request, approved=True, refusal_note=None):
"""Send confirmation to player about One on One response."""
"""Send confirmation to player about One on One response.
This is the legacy method kept for backward compatibility with any
callers that pass a fully-loaded request object.
"""
try:
# Ensure player and coach relationships are loaded
player = request.player
coach = request.coach
if not player:
logger.warning(f"Player not found for request {request.id}")
if not player or not player.discord_user_id:
logger.warning(f"Player has no Discord user ID for request {request.id}")
return
if not coach:
logger.warning(f"Coach not found for request {request.id}")
return
if not player.discord_user_id:
await self.notify_player_about_one_on_one_direct(
player_discord_id=player.discord_user_id,
player_full_name=player.full_name,
coach_full_name=coach.full_name,
request=request,
approved=approved,
refusal_note=refusal_note
)
except Exception as e:
logger.error(f"Error notifying player about One on One: {e}")
async def notify_player_about_one_on_one_direct(self, player_discord_id, player_full_name,
coach_full_name, request,
approved=True, refusal_note=None):
"""Send confirmation to player about One on One response using pre-fetched data.
This method avoids session expiration issues by using data captured before
the database commit.
Args:
player_discord_id: The player's Discord user ID string.
player_full_name: The player's full name.
coach_full_name: The coach's full name.
request: The OneOnOneRequest object (for date/time/points data only).
approved: Whether the session was approved.
refusal_note: Optional coach refusal reason.
"""
try:
if not player_discord_id:
logger.warning(f"Player has no Discord user ID for request {request.id}")
return
player_user = await self.fetch_user(int(player.discord_user_id))
player_user = await self.fetch_user(int(player_discord_id))
if not player_user:
logger.warning(f"Could not fetch Discord user for player {player.id}")
logger.warning(f"Could not fetch Discord user {player_discord_id}")
return
if approved:
message = (
"🎉 **One on One Session Confirmed!**\n\n"
f"Your coach **{coach.full_name}** has approved your request:\n"
f"Your coach **{coach_full_name}** has approved your request:\n"
f"**Date:** {request.date.strftime('%A, %B %d, %Y')}\n"
f"**Time:** {request.start_time.strftime('%I:%M %p')} - {request.end_time.strftime('%I:%M %p')}\n"
f"**Discussion Points:** {request.points or 'No specific points provided'}\n\n"
@@ -371,22 +451,22 @@ class TeamTryoutsBot(commands.Bot):
if refusal_note:
message = (
"😞 **One on One Session Rejected**\n\n"
f"Your coach **{coach.full_name}** has declined:\n"
f"Your coach **{coach_full_name}** has declined:\n"
f"**Reason:** {refusal_note}\n\n"
"Please try selecting a different time slot."
)
else:
message = (
"😞 **One on One Session Unavailable**\n\n"
f"Your coach **{coach.full_name}** is not available.\n\n"
f"Your coach **{coach_full_name}** is not available.\n\n"
"Please try selecting a different time slot."
)
await player_user.send(message)
logger.info(f"Sent One on One notification to player {player.full_name} (request {request.id})")
logger.info(f"Sent One on One notification to player {player_full_name} (request {request.id})")
except Exception as e:
logger.error(f"Error notifying player about One on One: {e}")
logger.error(f"Error in direct One on One notification: {e}")
async def send_daily_reminders(self):
"""Send daily reminders at 18:00 EDT for events in 24-48 hours."""