Fixed discord oauth2 integration, it was giving a 500 error on the first attempt. It should work properly now.
This commit is contained in:
parent
0c74366e4a
commit
67a80cdca1
@ -53,6 +53,24 @@ async def on_member_join(member):
|
||||
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})
|
||||
return [
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
# After successfully updating the user in the database:
|
||||
add_discord_role(user_data['id'], ACCOUNT_LINKED_ROLE_ID)
|
||||
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)}")
|
||||
|
||||
logging.info("Discord callback completed successfully")
|
||||
return """
|
||||
<script>
|
||||
console.log("Discord link successful. Closing window...");
|
||||
window.opener.postMessage('discord-linked', '*');
|
||||
window.close();
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user