From caefd6dbb2fb8f449d475476f184ed2c688e20de Mon Sep 17 00:00:00 2001 From: Refringe Date: Mon, 30 Sep 2024 14:06:37 -0400 Subject: [PATCH] Discord Avatar Import Imports the user's avatar from discord when a new user is created through OAuth. --- .gitignore | 4 ++ app/Http/Controllers/SocialiteController.php | 43 +++++++++++++++++++- app/Jobs/Import/ImportHubDataJob.php | 2 +- app/Models/User.php | 8 ++++ config/services.php | 2 +- storage/app/.gitignore | 3 -- storage/app/public/.gitignore | 2 - storage/app/public/cover-photos/.gitkeep | 0 storage/app/public/profile-photos/.gitkeep | 0 9 files changed, 56 insertions(+), 8 deletions(-) delete mode 100644 storage/app/.gitignore delete mode 100644 storage/app/public/.gitignore create mode 100644 storage/app/public/cover-photos/.gitkeep create mode 100644 storage/app/public/profile-photos/.gitkeep diff --git a/.gitignore b/.gitignore index e554aa8..2855410 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,10 @@ public/build public/hot public/storage storage/*.key +storage/app/livewire-tmp +storage/app/public +!storage/app/public/cover-photos/.gitkeep +!storage/app/public/profile-photos/.gitkeep vendor auth.json frankenphp diff --git a/app/Http/Controllers/SocialiteController.php b/app/Http/Controllers/SocialiteController.php index fca73b8..29488fd 100644 --- a/app/Http/Controllers/SocialiteController.php +++ b/app/Http/Controllers/SocialiteController.php @@ -7,6 +7,9 @@ use App\Models\User; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Auth; 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\Facades\Socialite; @@ -80,11 +83,13 @@ class SocialiteController extends Controller // If one exists, connect that account. Otherwise, create a new one. return DB::transaction(function () use ($providerUser, $provider) { + $user = User::firstOrCreate(['email' => $providerUser->getEmail()], [ 'name' => $providerUser->getName() ?? $providerUser->getNickname(), 'password' => null, ]); - $user->oAuthConnections()->create([ + + $connection = $user->oAuthConnections()->create([ 'provider' => $provider, 'provider_id' => $providerUser->getId(), 'token' => $providerUser->token, @@ -95,7 +100,43 @@ class SocialiteController extends Controller 'avatar' => $providerUser->getAvatar() ?? '', ]); + $this->updateAvatar($user, $connection->avatar); + 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(); + } } diff --git a/app/Jobs/Import/ImportHubDataJob.php b/app/Jobs/Import/ImportHubDataJob.php index 3815ace..084d1c3 100644 --- a/app/Jobs/Import/ImportHubDataJob.php +++ b/app/Jobs/Import/ImportHubDataJob.php @@ -392,7 +392,7 @@ class ImportHubDataJob implements ShouldBeUnique, ShouldQueue $hashShort = substr($avatar->fileHash, 0, 2); $fileName = $avatar->fileHash.'.'.$avatar->avatarExtension; $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); } diff --git a/app/Models/User.php b/app/Models/User.php index 21715d9..a20d6d1 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -44,6 +44,14 @@ class User extends Authenticatable implements MustVerifyEmail '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. * diff --git a/config/services.php b/config/services.php index 89df54e..8fe5103 100644 --- a/config/services.php +++ b/config/services.php @@ -45,7 +45,7 @@ return [ 'client_secret' => env('DISCORD_CLIENT_SECRET'), 'redirect' => env('DISCORD_REDIRECT_URI'), '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'), ], ]; diff --git a/storage/app/.gitignore b/storage/app/.gitignore deleted file mode 100644 index 8f4803c..0000000 --- a/storage/app/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!public/ -!.gitignore diff --git a/storage/app/public/.gitignore b/storage/app/public/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/storage/app/public/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/storage/app/public/cover-photos/.gitkeep b/storage/app/public/cover-photos/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/storage/app/public/profile-photos/.gitkeep b/storage/app/public/profile-photos/.gitkeep new file mode 100644 index 0000000..e69de29