Fixed discord oauth2 integration, it was giving a 500 error on the first attempt. It should work properly now.

This commit is contained in:
Jamon 2024-08-12 11:23:34 +12:00
parent 0c74366e4a
commit 67a80cdca1
2 changed files with 83 additions and 18 deletions

View File

@ -52,6 +52,24 @@ async def on_member_join(member):
logger.error(f"Failed to add Member role to {member.name}: {str(e)}")
else:
logger.error(f"'Member' role not found in the server")
# Send a welcome DM to the new member
try:
welcome_message = (
f"Welcome to the Resonance Rumble Discord server, {member.name}!\n\n"
"We're excited to have you join our community. Here are a few things to get you started:\n"
"• Come play the game here https://resonancerumble.com\n"
"• Introduce yourself in the #introductions channel.\n"
"• If you need any help, feel free to ask in the #help channel.\n\n"
"Don't forget to link your Discord account in the game to unlock an exclusive class!\n"
"Have fun and happy rumbling!"
)
await member.send(welcome_message)
logger.info(f"Sent welcome DM to {member.name}")
except discord.Forbidden:
logger.error(f"Failed to send welcome DM to {member.name}: User has DMs disabled")
except discord.HTTPException as e:
logger.error(f"Failed to send welcome DM to {member.name}: {str(e)}")
async def class_autocomplete(interaction: discord.Interaction, current: str) -> list[app_commands.Choice[str]]:
classes = classes_collection.find({}, {"name": 1})

View File

@ -30,6 +30,8 @@ import requests
from urllib.parse import urlencode
import secrets
from werkzeug.http import generate_etag
import discord
import asyncio
from config import DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, DISCORD_REDIRECT_URI, DISCORD_BOT_TOKEN, DISCORD_GUILD_ID, ACCOUNT_LINKED_ROLE_ID, DISCORD_WEBHOOK_URL
secret_key = secrets.token_hex(16)
@ -85,6 +87,25 @@ main_room = 'main_game_room'
MAP_WIDTH = 3000
MAP_HEIGHT = 2000
async def send_discord_dm(user_id, message):
try:
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
await client.login(DISCORD_BOT_TOKEN)
user = await client.fetch_user(user_id)
if user:
await user.send(message)
print(f"Sent achievement DM to user {user_id}")
else:
print(f"Couldn't find Discord user with ID {user_id}")
except Exception as e:
print(f"Error sending Discord DM: {str(e)}")
finally:
await client.close()
def award_achievement(user_id, achievement_id):
user = users_collection.find_one({'_id': ObjectId(user_id)})
if not user:
@ -105,6 +126,15 @@ def award_achievement(user_id, achievement_id):
send_discord_alert(f"🏆 Player {user['username']} has earned the '{achievement['name']}' achievement!", user['username'])
# Send a DM to the user if they have a linked Discord account
if 'discord_id' in user:
achievement_message = (
f"Congratulations! You've earned the '{achievement['name']}' achievement in Resonance Rumble!\n\n"
f"Achievement description: {achievement['description']}\n\n"
"Keep up the great work and continue resonating!"
)
asyncio.run(send_discord_dm(user['discord_id'], achievement_message))
# Check for classes to unlock
classes_to_unlock = list(classes_collection.find({'unlock_requirements.achievement': achievement_id}))
for class_doc in classes_to_unlock:
@ -118,6 +148,7 @@ def award_achievement(user_id, achievement_id):
return False
def send_discord_alert(message, username=None):
if username:
user = users_collection.find_one({'username': username})
@ -295,10 +326,14 @@ def initiate_discord_link(user_id):
@app.route('/discord-callback')
def discord_callback():
logging.info("Discord callback route hit")
code = request.args.get('code')
state = request.args.get('state')
logging.info(f"Received code: {code}, state: {state}")
if not code or not state:
logging.error("Missing code or state")
return "Error: Missing parameters", 400
# Verify state and get user_id
@ -308,9 +343,11 @@ def discord_callback():
})
if not oauth_state:
logging.error("Invalid or expired state")
return "Error: Invalid or expired state", 400
user_id = oauth_state['user_id']
logging.info(f"Valid state for user_id: {user_id}")
# Exchange code for token
data = {
@ -323,50 +360,60 @@ def discord_callback():
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
logging.info("Exchanging code for token")
r = requests.post(f'{DISCORD_API_ENDPOINT}/oauth2/token', data=data, headers=headers)
if r.status_code != 200:
logging.error(f"Failed to exchange code for token. Status: {r.status_code}, Response: {r.text}")
return "Error: Failed to exchange code for token", 400
tokens = r.json()
logging.info("Successfully exchanged code for token")
# Get user info
headers = {
'Authorization': f'Bearer {tokens["access_token"]}'
}
logging.info("Getting user info from Discord")
r = requests.get(f'{DISCORD_API_ENDPOINT}/users/@me', headers=headers)
if r.status_code != 200:
logging.error(f"Failed to get user info. Status: {r.status_code}, Response: {r.text}")
return "Error: Failed to get user info", 400
user_data = r.json()
logging.info(f"Retrieved user info for Discord user: {user_data['username']}#{user_data['discriminator']}")
# Update user in database
users_collection.update_one(
{'_id': ObjectId(user_id)},
{'$set': {
'discord_id': user_data['id'],
'discord_username': f"{user_data['username']}#{user_data['discriminator']}",
'discord_avatar': user_data['avatar']
}}
)
try:
result = users_collection.update_one(
{'_id': ObjectId(user_id)},
{'$set': {
'discord_id': user_data['id'],
'discord_username': f"{user_data['username']}#{user_data['discriminator']}",
'discord_avatar': user_data['avatar']
}}
)
logging.info(f"Updated user in database. Modified count: {result.modified_count}")
except Exception as e:
logging.error(f"Failed to update user in database: {str(e)}")
return "Error: Failed to update user information", 500
# Award the achievement
if award_achievement(user_id, 'discord_linked'):
socketio.emit('achievement_unlocked', {
'achievement_id': 'discord_linked',
'name': 'Discord Linked',
'description': 'Successfully linked your Discord account',
'image': 'discord_achievement.png'
}, room=request.sid)
logging.info(f"User {user_id} unlocked the 'Discord Linked' achievement")
# Add Discord role
try:
add_discord_role(user_data['id'], ACCOUNT_LINKED_ROLE_ID)
logging.info(f"Added Discord role to user {user_data['id']}")
except Exception as e:
logging.error(f"Failed to add Discord role: {str(e)}")
# After successfully updating the user in the database:
add_discord_role(user_data['id'], ACCOUNT_LINKED_ROLE_ID)
logging.info("Discord callback completed successfully")
return """
<script>
console.log("Discord link successful. Closing window...");
window.opener.postMessage('discord-linked', '*');
window.close();
</script>