diff --git a/CHANGELOG.md b/CHANGELOG.md index 12c35cd56..4ad37d53f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,11 @@ ## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.4...dev) ### New Features +- Mobile App Registration ([#3829](https://github.com/pixelfed/pixelfed/pull/3829)) - Portfolios ([#3705](https://github.com/pixelfed/pixelfed/pull/3705)) - Server Directory ([#3762](https://github.com/pixelfed/pixelfed/pull/3762)) - Manually verify email address (php artisan user:verifyemail) ([682f5f0f](https://github.com/pixelfed/pixelfed/commit/682f5f0f)) +- Manually generate in-app registration confirmation links (php artisan user:app-magic-link) ([73eb9e36](https://github.com/pixelfed/pixelfed/commit/73eb9e36)) ### Updates - Update ApiV1Controller, include self likes in favourited_by endpoint ([58b331d2](https://github.com/pixelfed/pixelfed/commit/58b331d2)) @@ -26,8 +28,7 @@ - Update landing view, add `app.name` and `app.short_description` for better customizability ([bda9d16b](https://github.com/pixelfed/pixelfed/commit/bda9d16b)) - Update Profile, fix avatarUrl paths. Fixes #3559 #3634 ([989e4249](https://github.com/pixelfed/pixelfed/commit/989e4249)) - Update InboxPipeline, bump request timeout from 5s to 60s ([bb120019](https://github.com/pixelfed/pixelfed/commit/bb120019)) -- Update web routes, fix missing hom route ([a9f4ddfc](https://github.com/pixelfed/pixelfed/commit/a9f4ddfc)) -- ([](https://github.com/pixelfed/pixelfed/commit/)) +- Update web routes, fix missing home route ([a9f4ddfc](https://github.com/pixelfed/pixelfed/commit/a9f4ddfc)) ## [v0.11.4 (2022-10-04)](https://github.com/pixelfed/pixelfed/compare/v0.11.3...v0.11.4) diff --git a/app/Console/Commands/AvatarStorage.php b/app/Console/Commands/AvatarStorage.php new file mode 100644 index 000000000..b0d388053 --- /dev/null +++ b/app/Console/Commands/AvatarStorage.php @@ -0,0 +1,123 @@ +info('Pixelfed Avatar Storage Manager'); + $this->line(' '); + $segments = [ + [ + 'Local', + Avatar::whereNull('is_remote')->count(), + PrettyNumber::size(Avatar::whereNull('is_remote')->sum('size')) + ], + [ + 'Remote', + Avatar::whereNotNull('is_remote')->count(), + PrettyNumber::size(Avatar::whereNotNull('is_remote')->sum('size')) + ], + [ + 'Cached (CDN)', + Avatar::whereNotNull('cdn_url')->count(), + PrettyNumber::size(Avatar::whereNotNull('cdn_url')->sum('size')) + ], + [ + 'Uncached', + Avatar::whereNull('is_remote')->whereNull('cdn_url')->count(), + PrettyNumber::size(Avatar::whereNull('is_remote')->whereNull('cdn_url')->sum('size')) + ], + [ + '------------', + '----------', + '-----' + ], + [ + 'Total', + Avatar::count(), + PrettyNumber::size(Avatar::sum('size')) + ], + ]; + $this->table( + ['Segment', 'Count', 'Space Used'], + $segments + ); + + $this->line(' '); + + if(config_cache('pixelfed.cloud_storage')) { + $this->info('✅ - Cloud storage configured'); + $this->line(' '); + } + + if(config_cache('instance.avatar.local_to_cloud')) { + $this->info('✅ - Store avatars on cloud filesystem'); + $this->line(' '); + } + + if(config_cache('pixelfed.cloud_storage') && config_cache('instance.avatar.local_to_cloud')) { + $disk = Storage::disk(config_cache('filesystems.cloud')); + $exists = $disk->exists('cache/avatars/default.jpg'); + $state = $exists ? '✅' : '❌'; + $msg = $state . ' - Cloud default avatar exists'; + $this->info($msg); + } + + $choice = $this->choice( + 'Select action:', + [ + 'Upload default avatar to cloud', + 'Move local avatars to cloud', + 'Move cloud avatars to local' + ], + 0 + ); + + return $this->handleChoice($choice); + } + + protected function handleChoice($id) + { + switch ($id) { + case 'Upload default avatar to cloud': + return $this->uploadDefaultAvatar(); + break; + } + } + + protected function uploadDefaultAvatar() + { + $disk = Storage::disk(config_cache('filesystems.cloud')); + $disk->put('cache/avatars/default.jpg', Storage::get('public/avatars/default.jpg')); + Avatar::whereMediaPath('public/avatars/default.jpg')->update(['cdn_url' => $disk->url('cache/avatars/default.jpg')]); + $this->info('Successfully uploaded default avatar to cloud storage!'); + $this->info($disk->url('cache/avatars/default.jpg')); + } +} diff --git a/app/Jobs/AvatarPipeline/AvatarOptimize.php b/app/Jobs/AvatarPipeline/AvatarOptimize.php index 8d5d2446d..f462ddde0 100644 --- a/app/Jobs/AvatarPipeline/AvatarOptimize.php +++ b/app/Jobs/AvatarPipeline/AvatarOptimize.php @@ -13,6 +13,7 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Str; use Image as Intervention; +use Storage; class AvatarOptimize implements ShouldQueue { @@ -63,6 +64,13 @@ class AvatarOptimize implements ShouldQueue $avatar->save(); Cache::forget('avatar:' . $avatar->profile_id); $this->deleteOldAvatar($avatar->media_path, $this->current); + + if(config_cache('pixelfed.cloud_storage') && config_cache('instance.avatar.local_to_cloud')) { + $this->uploadToCloud($avatar); + } else { + $avatar->cdn_url = null; + $avatar->save(); + } } catch (Exception $e) { } } @@ -79,4 +87,17 @@ class AvatarOptimize implements ShouldQueue @unlink($current); } } + + protected function uploadToCloud($avatar) + { + $base = 'cache/avatars/' . $avatar->profile_id; + $disk = Storage::disk(config('filesystems.cloud')); + $disk->deleteDirectory($base); + $path = $base . '/' . 'a' . strtolower(Str::random(random_int(3,6))) . $avatar->change_count . '.' . pathinfo($avatar->media_path, PATHINFO_EXTENSION); + $url = $disk->put($path, Storage::get($avatar->media_path)); + $avatar->cdn_url = $disk->url($path); + $avatar->save(); + Storage::delete($avatar->media_path); + Cache::forget('avatar:' . $avatar->profile_id); + } } diff --git a/config/instance.php b/config/instance.php index 528fe47b5..174baa81f 100644 --- a/config/instance.php +++ b/config/instance.php @@ -93,4 +93,8 @@ return [ ], 'hide_nsfw_on_public_feeds' => env('PF_HIDE_NSFW_ON_PUBLIC_FEEDS', false), + + 'avatar' => [ + 'local_to_cloud' => env('PF_LOCAL_AVATAR_TO_CLOUD', false) + ], ];