Discord Avatar Import

Imports the user's avatar from discord when a new user is created through OAuth.
This commit is contained in:
Refringe 2024-09-30 14:06:37 -04:00
parent 746fed1746
commit caefd6dbb2
Signed by: Refringe
SSH Key Fingerprint: SHA256:t865XsQpfTeqPRBMN2G6+N8wlDjkgUCZF3WGW6O9N/k
9 changed files with 56 additions and 8 deletions

4
.gitignore vendored
View File

@ -16,6 +16,10 @@ public/build
public/hot public/hot
public/storage public/storage
storage/*.key storage/*.key
storage/app/livewire-tmp
storage/app/public
!storage/app/public/cover-photos/.gitkeep
!storage/app/public/profile-photos/.gitkeep
vendor vendor
auth.json auth.json
frankenphp frankenphp

View File

@ -7,6 +7,9 @@ use App\Models\User;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\User as ProviderUser; use Laravel\Socialite\Contracts\User as ProviderUser;
use Laravel\Socialite\Facades\Socialite; use Laravel\Socialite\Facades\Socialite;
@ -80,11 +83,13 @@ class SocialiteController extends Controller
// If one exists, connect that account. Otherwise, create a new one. // If one exists, connect that account. Otherwise, create a new one.
return DB::transaction(function () use ($providerUser, $provider) { return DB::transaction(function () use ($providerUser, $provider) {
$user = User::firstOrCreate(['email' => $providerUser->getEmail()], [ $user = User::firstOrCreate(['email' => $providerUser->getEmail()], [
'name' => $providerUser->getName() ?? $providerUser->getNickname(), 'name' => $providerUser->getName() ?? $providerUser->getNickname(),
'password' => null, 'password' => null,
]); ]);
$user->oAuthConnections()->create([
$connection = $user->oAuthConnections()->create([
'provider' => $provider, 'provider' => $provider,
'provider_id' => $providerUser->getId(), 'provider_id' => $providerUser->getId(),
'token' => $providerUser->token, 'token' => $providerUser->token,
@ -95,7 +100,43 @@ class SocialiteController extends Controller
'avatar' => $providerUser->getAvatar() ?? '', 'avatar' => $providerUser->getAvatar() ?? '',
]); ]);
$this->updateAvatar($user, $connection->avatar);
return $user; return $user;
}); });
} }
private function updateAvatar(User $user, string $avatarUrl): void
{
// Determine the disk to use based on the environment.
$disk = match (config('app.env')) {
'production' => 'r2', // Cloudflare R2 Storage
default => 'public', // Local
};
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_URL, $avatarUrl);
$image = curl_exec($curl);
if ($image === false) {
Log::error('There was an error attempting to download the image. cURL error: '.curl_error($curl));
return;
}
// Generate a random path for the image and ensure that it doesn't already exist.
do {
$relativePath = User::profilePhotoStoragePath().'/'.Str::random(40).'.webp';
} while (Storage::disk($disk)->exists($relativePath));
// Store the image on the disk.
Storage::disk($disk)->put($relativePath, $image);
// Update the user's profile photo path.
$user->forceFill([
'profile_photo_path' => $relativePath,
])->save();
}
} }

View File

@ -392,7 +392,7 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue
$hashShort = substr($avatar->fileHash, 0, 2); $hashShort = substr($avatar->fileHash, 0, 2);
$fileName = $avatar->fileHash.'.'.$avatar->avatarExtension; $fileName = $avatar->fileHash.'.'.$avatar->avatarExtension;
$hubUrl = 'https://hub.sp-tarkov.com/images/avatars/'.$hashShort.'/'.$avatar->avatarID.'-'.$fileName; $hubUrl = 'https://hub.sp-tarkov.com/images/avatars/'.$hashShort.'/'.$avatar->avatarID.'-'.$fileName;
$relativePath = 'user-avatars/'.$fileName; $relativePath = User::profilePhotoStoragePath().'/'.$fileName;
return $this->fetchAndStoreImage($curl, $hubUrl, $relativePath); return $this->fetchAndStoreImage($curl, $hubUrl, $relativePath);
} }

View File

@ -44,6 +44,14 @@ class User extends Authenticatable implements MustVerifyEmail
'profile_photo_url', 'profile_photo_url',
]; ];
/**
* Get the storage path for profile photos.
*/
public static function profilePhotoStoragePath(): string
{
return 'profile-photos';
}
/** /**
* The relationship between a user and their mods. * The relationship between a user and their mods.
* *

View File

@ -45,7 +45,7 @@ return [
'client_secret' => env('DISCORD_CLIENT_SECRET'), 'client_secret' => env('DISCORD_CLIENT_SECRET'),
'redirect' => env('DISCORD_REDIRECT_URI'), 'redirect' => env('DISCORD_REDIRECT_URI'),
'allow_gif_avatars' => (bool) env('DISCORD_AVATAR_GIF', true), 'allow_gif_avatars' => (bool) env('DISCORD_AVATAR_GIF', true),
'avatar_default_extension' => env('DISCORD_EXTENSION_DEFAULT', 'png'), 'avatar_default_extension' => env('DISCORD_EXTENSION_DEFAULT', 'webp'),
], ],
]; ];

View File

@ -1,3 +0,0 @@
*
!public/
!.gitignore

View File

@ -1,2 +0,0 @@
*
!.gitignore

View File