Files
hstream/app/Http/Controllers/Auth/DiscordAuthController.php
2026-01-07 19:04:51 +01:00

122 lines
3.3 KiB
PHP

<?php
namespace App\Http\Controllers\Auth;
use App\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Laravel\Socialite\Facades\Socialite;
class DiscordAuthController extends Controller
{
/**
* Redirect to Discord
*/
public function redirect(): RedirectResponse
{
return Socialite::driver('discord')->redirect();
}
/**
* Callback received from Discord
*/
public function callback(): RedirectResponse
{
$discordUser = Socialite::driver('discord')->user();
$user = User::where('discord_id', $discordUser->id)->first();
if (! $user) {
// link by email if it already exists
$user = User::where('email', $discordUser->email)->first();
if ($user) {
$user->update([
'discord_id' => $discordUser->id,
'discord_name' => $discordUser->nickname ?? $discordUser->name,
'discord_avatar' => $discordUser->avatar,
]);
} else {
// Create new user
$user = User::create([
'name' => $discordUser->name,
'email' => $discordUser->email,
'discord_id' => $discordUser->id,
'discord_name' => $discordUser->nickname ?? $discordUser->name,
'discord_avatar' => $discordUser->avatar,
'password' => bcrypt(Str::random(40)),
]);
}
}
$this->checkDiscordRoles($user);
Auth::login($user, true);
return redirect()->route('home.index');
}
/**
* Check Discord Roles if user is Patreon member
*/
private function checkDiscordRoles(User $user): void
{
// Should not ever happen
if (!$user->discord_id) {
return;
}
$guildId = config('discord.guild_id');
$response = Http::withToken(config('discord.discord_bot_token'), 'Bot')
->timeout(5)
->get("https://discord.com/api/v10/guilds/{$guildId}/members/{$user->discord_id}");
// User is not in the guild
if ($response->status() === 404) {
$user->update([
'is_patreon' => false,
]);
return;
}
// Something else failed
if ($response->failed()) {
Log::warning('Discord role check failed', [
'user_id' => $user->id,
'discord_id' => $user->discord_id,
'status' => $response->status(),
'body' => $response->body(),
]);
return;
}
$discordRoles = $response->json('roles', []);
$patreonRoles = config('discord.patreon_roles', []);
$isPatreon = false;
foreach($patreonRoles as $patreonRole)
{
if (in_array($patreonRole, $discordRoles, true)) {
$isPatreon = true;
break;
}
}
// Only update if something actually changed
if ($user->is_patreon !== $isPatreon) {
$user->update([
'is_patreon' => $isPatreon,
]);
}
}
}