From 3861e7ddfe7496e607e43f1550ae985732b365ec Mon Sep 17 00:00:00 2001
From: daniel
Date: Tue, 13 May 2025 02:25:23 -0600
Subject: [PATCH] Staging (#5978)
* Added current title as value for input so that the current value remains stored by default
* Added parameter 'show_legal_notice_link' => (bool) config_cache('instance.has_legal_notice'),
* Added conditional display of a link to legal notice if the page is active
* Added key 'legalNotice'
* feat translate story
* translate auth
- register
- login
* add remove follow
* Update ApiV1Controller.php
Co-Authored-By: Mathieu <385764+Casmo@users.noreply.github.com>
* New translations web.php (Chinese Simplified)
[ci skip]
* Added current title as value for input so that the current value remains stored by default
* Added parameter 'show_legal_notice_link' => (bool) config_cache('instance.has_legal_notice'),
* Added conditional display of a link to legal notice if the page is active
* Added key 'legalNotice'
* add missing key
* add missing keys
* New translations web.php (Portuguese, Brazilian)
[ci skip]
* New translations web.php (Turkish)
[ci skip]
* New translations web.php (Italian)
[ci skip]
* translate custom filter
* New translations web.php (Italian)
[ci skip]
* use configured alt text length limit when uploading multiple photos
* in notifications sidebar, show popover on shared posts too, not just liked posts
* use case insensitive search when tagging accounts
* New translations web.php (Portuguese, Brazilian)
[ci skip]
* Generic OIDC Support
* Everything should be configurable by env variables
* Basic request tests
* Fixes for items highlighted by review.ai
* Consider using `hash_equals()` instead of `==` when comparing the state values to prevent timing attacks:
`abort_unless(hash_equals($request->input('state'), $request->session()->pull('oauth2state')), 400, 'invalid
state');`
* For better data integrity, consider adding a foreign key constraint to the user_id column: `$table-
>foreign('user_id')->references('id')->on('users')->onDelete('cascade');`
* Does the OIDC provider guarantee that the username field exists in the userInfo data? Consider adding a
null check or fallback: `$userInfoData[config('remote-auth.oidc.field_username')] ?? null`
* field isnt accessTokenResourceOwnerId but responseResourceOwnerId
* New translations web.php (Dutch)
[ci skip]
* Fix components
* Update LandingService and Config util to properly support the legal_notice setting
* Update footer to use legalNotice i18n
* Update i18n
* Update sidebar with gap padding for footer links
* Update compiled assets
* Update i18n json
* Update OIDC config with comments, and disable tests as we dont have db tests configured
* Update remove_from_followers api endpoint
* Update i18n
* Update compiled assets
* Update changelog
* New supported formats, Preserve ICC Color Profiles, libvips support
Update image pipeline to handle avif, heic and webp and preserve ICC color profiles and added libvips support.
* Fix tests
* Update CHANGELOG.md
---------
Co-authored-by: Samy Elshamy
Co-authored-by: Felipe Mateus
Co-authored-by: Mathieu <385764+Casmo@users.noreply.github.com>
Co-authored-by: Mackenzie Morgan
Co-authored-by: Gavin Mogan
---
CHANGELOG.md | 7 +
.../Commands/CatchUnoptimizedMedia.php | 1 +
app/Console/Commands/FixMediaDriver.php | 239 +-
app/Console/Commands/ImportEmojis.php | 2 +-
app/Console/Commands/RegenerateThumbnails.php | 2 +-
app/Http/Controllers/Api/ApiV1Controller.php | 44 +-
.../Controllers/Api/ApiV1Dot1Controller.php | 1 +
app/Http/Controllers/Api/ApiV2Controller.php | 1 +
app/Http/Controllers/ComposeController.php | 3 +-
app/Http/Controllers/ImportPostController.php | 2 +-
app/Http/Controllers/RemoteAuthController.php | 33 +-
app/Http/Controllers/RemoteOidcController.php | 121 +
.../Stories/StoryApiV1Controller.php | 2 +-
.../Controllers/StoryComposeController.php | 2 +-
.../ImageOptimizePipeline/ImageOptimize.php | 3 +
app/Media.php | 2 +-
app/Models/UserOidcMapping.php | 25 +
app/Providers/AppServiceProvider.php | 5 +-
app/Rules/EmailNotBanned.php | 25 +
app/Rules/PixelfedUsername.php | 57 +
app/Services/LandingService.php | 1 +
app/Services/MediaStorageService.php | 7 +-
app/Services/UserOidcService.php | 21 +
app/Status.php | 696 ++--
app/Util/ActivityPub/Helpers.php | 2 +-
app/Util/Media/Blurhash.php | 95 +-
app/Util/Media/Image.php | 488 ++-
app/Util/Site/Config.php | 1 +
composer.json | 3 +-
composer.lock | 937 +++--
config/image.php | 8 +-
config/remote-auth.php | 75 +
..._061434_create_user_oidc_mapping_table.php | 30 +
public/_lang/de.json | 1 +
public/_lang/en.json | 109 +-
public/_lang/it.json | 4 +-
public/_lang/nl.json | 18 +-
public/_lang/pt.json | 128 +-
public/_lang/tr.json | 2 +-
public/_lang/zh.json | 260 +-
public/js/app.js | 2 +-
.../js/changelog.bundle.8ee4f1174f52ec8b.js | 1 +
.../js/changelog.bundle.efd3d17aee17020e.js | 1 -
public/js/compose.chunk.80e32f21442c8a91.js | 2 -
public/js/compose.chunk.8292176da8a20099.js | 2 +
...ose.chunk.8292176da8a20099.js.LICENSE.txt} | 0
public/js/compose.js | 2 +-
public/js/custom_filters.js | 2 +-
public/js/daci.chunk.0903327306251770.js | 1 +
public/js/daci.chunk.4eaae509ed4a084c.js | 1 -
public/js/discover.chunk.0ca404627af971f2.js | 1 -
public/js/discover.chunk.8698471944aa4417.js | 1 +
...over~findfriends.chunk.2ccaf3c586ba03fc.js | 1 -
...over~findfriends.chunk.c3db8f429e763088.js | 1 +
...iscover~hashtag.bundle.3f6d5e3bb2865a61.js | 1 +
...iscover~hashtag.bundle.fffb7ab6f02db6fe.js | 1 -
...iscover~memories.chunk.8601596a52c06bfc.js | 1 +
...iscover~memories.chunk.8ea5b8e37111f15f.js | 1 -
...cover~myhashtags.chunk.57eeb9257cb300fd.js | 1 -
...cover~myhashtags.chunk.9b2cd210943ec613.js | 1 +
...cover~serverfeed.chunk.7eeef300c5b29e82.js | 1 +
...cover~serverfeed.chunk.b7e1082a3be6ef4c.js | 1 -
...iscover~settings.chunk.80c4e5afc970254e.js | 1 +
...iscover~settings.chunk.edeee5803151d4eb.js | 1 -
public/js/dms.chunk.13449036a5b769e6.js | 1 -
public/js/dms.chunk.746342b9470dc71f.js | 1 +
.../js/dms~message.chunk.8cdd27784f95ee11.js | 1 +
.../js/dms~message.chunk.f0d6ccb6f2f1cbf7.js | 1 -
...e9.js => group.create.e34ad5621d07870d.js} | 2 +-
public/js/home.chunk.7b3c50ff0f7828a4.js | 2 -
public/js/home.chunk.cf3e6ccd3b76689d.js | 2 +
...ome.chunk.cf3e6ccd3b76689d.js.LICENSE.txt} | 0
public/js/i18n.bundle.85976a3b9d6b922a.js | 1 -
public/js/i18n.bundle.ff6f2af48fd2e3d5.js | 1 +
public/js/landing.js | 2 +-
public/js/manifest.js | 2 +-
.../notifications.chunk.a8193668255b2c9a.js | 1 -
.../notifications.chunk.eb78183fd97a9f0f.js | 1 +
public/js/post.chunk.cdef3ec51a723c2f.js | 2 +
...ost.chunk.cdef3ec51a723c2f.js.LICENSE.txt} | 0
public/js/post.chunk.d0c8b400a930b92a.js | 2 -
public/js/profile.chunk.5b03b78ed621f690.js | 1 +
public/js/profile.chunk.5d560ecb7d4a57ce.js | 1 -
public/js/settings.js | 1 +
public/js/spa.js | 2 +-
public/js/stories.js | 2 +-
public/js/story-compose.js | 2 +-
public/js/timeline.js | 2 +-
public/mix-manifest.json | 55 +-
.../components/landing/sections/footer.vue | 62 +-
.../partials/profile/ProfileSidebar.vue | 1506 +++----
.../assets/components/partials/sidebar.vue | 1194 +++---
.../partials/timeline/StoryCarousel.vue | 2 +-
.../components/sections/Notifications.vue | 8 +-
.../assets/js/components/ComposeModal.vue | 3638 ++++++++---------
resources/assets/js/components/Stories.vue | 4 +-
.../assets/js/components/StoryCompose.vue | 52 +-
.../js/components/StoryTimelineComponent.vue | 2 +-
.../assets/js/components/StoryViewer.vue | 16 +-
.../js/components/filters/FilterCard.vue | 4 +-
.../js/components/filters/FilterModal.vue | 162 +-
.../js/components/filters/FiltersList.vue | 25 +-
resources/assets/js/i18n/de.json | 1 +
resources/assets/js/i18n/en.json | 109 +-
resources/assets/js/i18n/it.json | 4 +-
resources/assets/js/i18n/nl.json | 18 +-
resources/assets/js/i18n/pt.json | 128 +-
resources/assets/js/i18n/tr.json | 2 +-
resources/assets/js/i18n/zh.json | 260 +-
resources/assets/js/settings.js | 19 +
resources/lang/de/web.php | 15 +-
resources/lang/en/auth.php | 28 +
resources/lang/en/settings.php | 32 +-
resources/lang/en/web.php | 115 +-
resources/lang/it/web.php | 4 +-
resources/lang/nl/web.php | 18 +-
resources/lang/pt/auth.php | 29 +-
resources/lang/pt/settings.php | 4 +
resources/lang/pt/web.php | 135 +-
resources/lang/tr/web.php | 2 +-
resources/lang/zh/web.php | 272 +-
resources/views/admin/pages/edit.blade.php | 2 +-
resources/views/auth/login.blade.php | 27 +-
resources/views/auth/register.blade.php | 26 +-
.../views/layouts/partial/footer.blade.php | 2 +-
resources/views/layouts/partial/nav.blade.php | 8 +-
.../views/settings/partial/sidebar.blade.php | 2 +-
.../settings/relationships/home.blade.php | 11 +
resources/views/settings/template.blade.php | 8 +-
routes/api.php | 1 +
routes/web-api.php | 1 +
routes/web.php | 4 +
tests/Feature/RemoteOidcTest.php | 117 +
webpack.mix.js | 1 +
134 files changed, 6577 insertions(+), 5082 deletions(-)
create mode 100644 app/Http/Controllers/RemoteOidcController.php
create mode 100644 app/Models/UserOidcMapping.php
create mode 100644 app/Rules/EmailNotBanned.php
create mode 100644 app/Rules/PixelfedUsername.php
create mode 100644 app/Services/UserOidcService.php
create mode 100644 database/migrations/2025_01_30_061434_create_user_oidc_mapping_table.php
create mode 100644 public/js/changelog.bundle.8ee4f1174f52ec8b.js
delete mode 100644 public/js/changelog.bundle.efd3d17aee17020e.js
delete mode 100644 public/js/compose.chunk.80e32f21442c8a91.js
create mode 100644 public/js/compose.chunk.8292176da8a20099.js
rename public/js/{compose.chunk.80e32f21442c8a91.js.LICENSE.txt => compose.chunk.8292176da8a20099.js.LICENSE.txt} (100%)
create mode 100644 public/js/daci.chunk.0903327306251770.js
delete mode 100644 public/js/daci.chunk.4eaae509ed4a084c.js
delete mode 100644 public/js/discover.chunk.0ca404627af971f2.js
create mode 100644 public/js/discover.chunk.8698471944aa4417.js
delete mode 100644 public/js/discover~findfriends.chunk.2ccaf3c586ba03fc.js
create mode 100644 public/js/discover~findfriends.chunk.c3db8f429e763088.js
create mode 100644 public/js/discover~hashtag.bundle.3f6d5e3bb2865a61.js
delete mode 100644 public/js/discover~hashtag.bundle.fffb7ab6f02db6fe.js
create mode 100644 public/js/discover~memories.chunk.8601596a52c06bfc.js
delete mode 100644 public/js/discover~memories.chunk.8ea5b8e37111f15f.js
delete mode 100644 public/js/discover~myhashtags.chunk.57eeb9257cb300fd.js
create mode 100644 public/js/discover~myhashtags.chunk.9b2cd210943ec613.js
create mode 100644 public/js/discover~serverfeed.chunk.7eeef300c5b29e82.js
delete mode 100644 public/js/discover~serverfeed.chunk.b7e1082a3be6ef4c.js
create mode 100644 public/js/discover~settings.chunk.80c4e5afc970254e.js
delete mode 100644 public/js/discover~settings.chunk.edeee5803151d4eb.js
delete mode 100644 public/js/dms.chunk.13449036a5b769e6.js
create mode 100644 public/js/dms.chunk.746342b9470dc71f.js
create mode 100644 public/js/dms~message.chunk.8cdd27784f95ee11.js
delete mode 100644 public/js/dms~message.chunk.f0d6ccb6f2f1cbf7.js
rename public/js/{group.create.38102523ebf4cde9.js => group.create.e34ad5621d07870d.js} (71%)
delete mode 100644 public/js/home.chunk.7b3c50ff0f7828a4.js
create mode 100644 public/js/home.chunk.cf3e6ccd3b76689d.js
rename public/js/{home.chunk.7b3c50ff0f7828a4.js.LICENSE.txt => home.chunk.cf3e6ccd3b76689d.js.LICENSE.txt} (100%)
delete mode 100644 public/js/i18n.bundle.85976a3b9d6b922a.js
create mode 100644 public/js/i18n.bundle.ff6f2af48fd2e3d5.js
delete mode 100644 public/js/notifications.chunk.a8193668255b2c9a.js
create mode 100644 public/js/notifications.chunk.eb78183fd97a9f0f.js
create mode 100644 public/js/post.chunk.cdef3ec51a723c2f.js
rename public/js/{post.chunk.d0c8b400a930b92a.js.LICENSE.txt => post.chunk.cdef3ec51a723c2f.js.LICENSE.txt} (100%)
delete mode 100644 public/js/post.chunk.d0c8b400a930b92a.js
create mode 100644 public/js/profile.chunk.5b03b78ed621f690.js
delete mode 100644 public/js/profile.chunk.5d560ecb7d4a57ce.js
create mode 100644 public/js/settings.js
create mode 100644 resources/assets/js/settings.js
create mode 100644 tests/Feature/RemoteOidcTest.php
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe67ce809..f68c546d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@
### Added
- Pinned Posts ([2f655d000](https://github.com/pixelfed/pixelfed/commit/2f655d000))
- Custom Filters ([#5928](https://github.com/pixelfed/pixelfed/pull/5928)) ([437d742ac](https://github.com/pixelfed/pixelfed/commit/437d742ac))
+- Legal Notice page ([#5606](https://github.com/pixelfed/pixelfed/pull/5606)) ([c72fa0529](https://github.com/pixelfed/pixelfed/commit/c72fa0529))
+- OIDC Support ([#5608](https://github.com/pixelfed/pixelfed/pull/5608)) ([c72fa0529](https://github.com/pixelfed/pixelfed/commit/c72fa0529))
+- Avif, HEIC, webp, libvips support + Preserve ICC color profiles ([ab9c13fe0](https://github.com/pixelfed/pixelfed/commit/ab9c13fe0))
### Updates
- Update PublicApiController, use pixelfed entities for /api/pixelfed/v1/accounts/id/statuses with bookmarked state ([5ddb6d842](https://github.com/pixelfed/pixelfed/commit/5ddb6d842))
@@ -20,6 +23,10 @@
- Update report views, fix missing forms ([475d1d627](https://github.com/pixelfed/pixelfed/commit/475d1d627))
- Update private settings, change "Private Account" to "Manually Review Follow Requests" ([31dd1ab35](https://github.com/pixelfed/pixelfed/commit/31dd1ab35))
- Update ReportController, fix type validation ([ccc7f2fc6](https://github.com/pixelfed/pixelfed/commit/ccc7f2fc6))
+- Update footer to use legalNotice i18n ([0e59098da](https://github.com/pixelfed/pixelfed/commit/0e59098da))
+- Update sidebar with gap padding for footer links ([dbd8289fe](https://github.com/pixelfed/pixelfed/commit/dbd8289fe))
+- Update translations for Stories ([0a4dc7724](https://github.com/pixelfed/pixelfed/commit/0a4dc7724))
+- Update translations for Auth ([756102696](https://github.com/pixelfed/pixelfed/commit/756102696))
- ([](https://github.com/pixelfed/pixelfed/commit/))
## [v0.12.5 (2025-03-23)](https://github.com/pixelfed/pixelfed/compare/v0.12.5...dev)
diff --git a/app/Console/Commands/CatchUnoptimizedMedia.php b/app/Console/Commands/CatchUnoptimizedMedia.php
index a5bb22f98..9c5dba5e9 100644
--- a/app/Console/Commands/CatchUnoptimizedMedia.php
+++ b/app/Console/Commands/CatchUnoptimizedMedia.php
@@ -48,6 +48,7 @@ class CatchUnoptimizedMedia extends Command
->whereNotNull('status_id')
->whereNotNull('media_path')
->whereIn('mime', [
+ 'image/jpg',
'image/jpeg',
'image/png',
])
diff --git a/app/Console/Commands/FixMediaDriver.php b/app/Console/Commands/FixMediaDriver.php
index a20b0574e..b8537d4ab 100644
--- a/app/Console/Commands/FixMediaDriver.php
+++ b/app/Console/Commands/FixMediaDriver.php
@@ -11,123 +11,124 @@ use App\Jobs\MediaPipeline\MediaFixLocalFilesystemCleanupPipeline;
class FixMediaDriver extends Command
{
- /**
- * The name and signature of the console command.
- *
- * @var string
- */
- protected $signature = 'media:fix-nonlocal-driver';
-
- /**
- * The console command description.
- *
- * @var string
- */
- protected $description = 'Fix filesystem when FILESYSTEM_DRIVER not set to local';
-
- /**
- * Execute the console command.
- *
- * @return int
- */
- public function handle()
- {
- if(config('filesystems.default') !== 'local') {
- $this->error('Invalid default filesystem, set FILESYSTEM_DRIVER=local to proceed');
- return Command::SUCCESS;
- }
-
- if((bool) config_cache('pixelfed.cloud_storage') == false) {
- $this->error('Cloud storage not enabled, exiting...');
- return Command::SUCCESS;
- }
-
- $this->info(' ____ _ ______ __ ');
- $this->info(' / __ \(_) _____ / / __/__ ____/ / ');
- $this->info(' / /_/ / / |/_/ _ \/ / /_/ _ \/ __ / ');
- $this->info(' / ____/ /> __/ / __/ __/ /_/ / ');
- $this->info(' /_/ /_/_/|_|\___/_/_/ \___/\__,_/ ');
- $this->info(' ');
- $this->info(' Media Filesystem Fix');
- $this->info(' =====================');
- $this->info(' Fix media that was created when FILESYSTEM_DRIVER=local');
- $this->info(' was not properly set. This command will fix media urls');
- $this->info(' and optionally optimize/generate thumbnails when applicable,');
- $this->info(' clean up temporary local media files and clear the app cache');
- $this->info(' to fix media paths/urls.');
- $this->info(' ');
- $this->error(' Remember, FILESYSTEM_DRIVER=local must remain set or you will break things!');
-
- if(!$this->confirm('Are you sure you want to perform this command?')) {
- $this->info('Exiting...');
- return Command::SUCCESS;
- }
-
- $optimize = $this->choice(
- 'Do you want to optimize media and generate thumbnails? This will store s3 locally and re-upload optimized versions.',
- ['no', 'yes'],
- 1
- );
-
- $cloud = Storage::disk(config('filesystems.cloud'));
- $mountManager = new MountManager([
- 's3' => $cloud->getDriver(),
- 'local' => Storage::disk('local')->getDriver(),
- ]);
-
- $this->info('Fixing media, this may take a while...');
- $this->line(' ');
- $bar = $this->output->createProgressBar(Media::whereNotNull('status_id')->whereNull('cdn_url')->count());
- $bar->start();
-
- foreach(Media::whereNotNull('status_id')->whereNull('cdn_url')->lazyById(20) as $media) {
- if($cloud->exists($media->media_path)) {
- if($optimize === 'yes') {
- $mountManager->copy(
- 's3://' . $media->media_path,
- 'local://' . $media->media_path
- );
- sleep(1);
- if(empty($media->original_sha256)) {
- $hash = \hash_file('sha256', Storage::disk('local')->path($media->media_path));
- $media->original_sha256 = $hash;
- $media->save();
- sleep(1);
- }
- if(
- $media->mime &&
- in_array($media->mime, [
- 'image/jpeg',
- 'image/png',
- 'image/webp'
- ])
- ) {
- ImageOptimize::dispatch($media);
- sleep(3);
- }
- } else {
- $media->cdn_url = $cloud->url($media->media_path);
- $media->save();
- }
- }
- $bar->advance();
- }
-
- $bar->finish();
- $this->line(' ');
- $this->line(' ');
-
- $this->callSilently('cache:clear');
-
- $this->info('Successfully fixed media paths and cleared cached!');
-
- if($optimize === 'yes') {
- MediaFixLocalFilesystemCleanupPipeline::dispatch()->delay(now()->addMinutes(15))->onQueue('default');
- $this->line(' ');
- $this->info('A cleanup job has been dispatched to delete media stored locally, it may take a few minutes to process!');
- }
-
- $this->line(' ');
- return Command::SUCCESS;
- }
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'media:fix-nonlocal-driver';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Fix filesystem when FILESYSTEM_DRIVER not set to local';
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ if(config('filesystems.default') !== 'local') {
+ $this->error('Invalid default filesystem, set FILESYSTEM_DRIVER=local to proceed');
+ return Command::SUCCESS;
+ }
+
+ if((bool) config_cache('pixelfed.cloud_storage') == false) {
+ $this->error('Cloud storage not enabled, exiting...');
+ return Command::SUCCESS;
+ }
+
+ $this->info(' ____ _ ______ __ ');
+ $this->info(' / __ \(_) _____ / / __/__ ____/ / ');
+ $this->info(' / /_/ / / |/_/ _ \/ / /_/ _ \/ __ / ');
+ $this->info(' / ____/ /> __/ / __/ __/ /_/ / ');
+ $this->info(' /_/ /_/_/|_|\___/_/_/ \___/\__,_/ ');
+ $this->info(' ');
+ $this->info(' Media Filesystem Fix');
+ $this->info(' =====================');
+ $this->info(' Fix media that was created when FILESYSTEM_DRIVER=local');
+ $this->info(' was not properly set. This command will fix media urls');
+ $this->info(' and optionally optimize/generate thumbnails when applicable,');
+ $this->info(' clean up temporary local media files and clear the app cache');
+ $this->info(' to fix media paths/urls.');
+ $this->info(' ');
+ $this->error(' Remember, FILESYSTEM_DRIVER=local must remain set or you will break things!');
+
+ if(!$this->confirm('Are you sure you want to perform this command?')) {
+ $this->info('Exiting...');
+ return Command::SUCCESS;
+ }
+
+ $optimize = $this->choice(
+ 'Do you want to optimize media and generate thumbnails? This will store s3 locally and re-upload optimized versions.',
+ ['no', 'yes'],
+ 1
+ );
+
+ $cloud = Storage::disk(config('filesystems.cloud'));
+ $mountManager = new MountManager([
+ 's3' => $cloud->getDriver(),
+ 'local' => Storage::disk('local')->getDriver(),
+ ]);
+
+ $this->info('Fixing media, this may take a while...');
+ $this->line(' ');
+ $bar = $this->output->createProgressBar(Media::whereNotNull('status_id')->whereNull('cdn_url')->count());
+ $bar->start();
+
+ foreach(Media::whereNotNull('status_id')->whereNull('cdn_url')->lazyById(20) as $media) {
+ if($cloud->exists($media->media_path)) {
+ if($optimize === 'yes') {
+ $mountManager->copy(
+ 's3://' . $media->media_path,
+ 'local://' . $media->media_path
+ );
+ sleep(1);
+ if(empty($media->original_sha256)) {
+ $hash = \hash_file('sha256', Storage::disk('local')->path($media->media_path));
+ $media->original_sha256 = $hash;
+ $media->save();
+ sleep(1);
+ }
+ if(
+ $media->mime &&
+ in_array($media->mime, [
+ 'image/jpg',
+ 'image/jpeg',
+ 'image/png',
+ 'image/webp'
+ ])
+ ) {
+ ImageOptimize::dispatch($media);
+ sleep(3);
+ }
+ } else {
+ $media->cdn_url = $cloud->url($media->media_path);
+ $media->save();
+ }
+ }
+ $bar->advance();
+ }
+
+ $bar->finish();
+ $this->line(' ');
+ $this->line(' ');
+
+ $this->callSilently('cache:clear');
+
+ $this->info('Successfully fixed media paths and cleared cached!');
+
+ if($optimize === 'yes') {
+ MediaFixLocalFilesystemCleanupPipeline::dispatch()->delay(now()->addMinutes(15))->onQueue('default');
+ $this->line(' ');
+ $this->info('A cleanup job has been dispatched to delete media stored locally, it may take a few minutes to process!');
+ }
+
+ $this->line(' ');
+ return Command::SUCCESS;
+ }
}
diff --git a/app/Console/Commands/ImportEmojis.php b/app/Console/Commands/ImportEmojis.php
index 77a0c29a4..aea3d9e08 100644
--- a/app/Console/Commands/ImportEmojis.php
+++ b/app/Console/Commands/ImportEmojis.php
@@ -110,7 +110,7 @@ class ImportEmojis extends Command
private function isEmoji($filename)
{
- $allowedMimeTypes = ['image/png', 'image/jpeg', 'image/webp'];
+ $allowedMimeTypes = ['image/png', 'image/jpeg', 'image/webp', 'image/jpg'];
$mimeType = mime_content_type($filename);
return in_array($mimeType, $allowedMimeTypes);
diff --git a/app/Console/Commands/RegenerateThumbnails.php b/app/Console/Commands/RegenerateThumbnails.php
index f5759c36f..488baa041 100644
--- a/app/Console/Commands/RegenerateThumbnails.php
+++ b/app/Console/Commands/RegenerateThumbnails.php
@@ -40,7 +40,7 @@ class RegenerateThumbnails extends Command
public function handle()
{
DB::transaction(function() {
- Media::whereIn('mime', ['image/jpeg', 'image/png'])
+ Media::whereIn('mime', ['image/jpeg', 'image/png', 'image/jpg'])
->chunk(50, function($medias) {
foreach($medias as $media) {
\App\Jobs\ImageOptimizePipeline\ImageThumbnail::dispatch($media);
diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php
index c8e3d5e9e..467df3a7b 100644
--- a/app/Http/Controllers/Api/ApiV1Controller.php
+++ b/app/Http/Controllers/Api/ApiV1Controller.php
@@ -243,7 +243,7 @@ class ApiV1Controller extends Controller
}
$this->validate($request, [
- 'avatar' => 'sometimes|mimetypes:image/jpeg,image/png|max:'.config('pixelfed.max_avatar_size'),
+ 'avatar' => 'sometimes|mimetypes:image/jpeg,image/jpg,image/png|max:'.config('pixelfed.max_avatar_size'),
'display_name' => 'nullable|string|max:30',
'note' => 'nullable|string|max:200',
'locked' => 'nullable',
@@ -1907,6 +1907,7 @@ class ApiV1Controller extends Controller
$media->save();
switch ($media->mime) {
+ case 'image/jpg':
case 'image/jpeg':
case 'image/png':
case 'image/webp':
@@ -2137,6 +2138,7 @@ class ApiV1Controller extends Controller
$media->save();
switch ($media->mime) {
+ case 'image/jpg':
case 'image/jpeg':
case 'image/png':
case 'image/webp':
@@ -4563,6 +4565,46 @@ class ApiV1Controller extends Controller
);
}
+ public function accountRemoveFollowById(Request $request, $id)
+ {
+ abort_if(! $request->user(), 403);
+
+ $pid = $request->user()->profile_id;
+
+ if ($pid === $id) {
+ return $this->json(['error' => 'Request invalid! target_id is same user id.'], 500);
+ }
+
+ $exists = Follower::whereProfileId($id)
+ ->whereFollowingId($pid)
+ ->first();
+
+ abort_unless($exists, 404);
+
+ $exists->delete();
+
+ RelationshipService::refresh($pid, $id);
+ RelationshipService::refresh($pid, $id);
+
+ UnfollowPipeline::dispatch($id, $pid)->onQueue('high');
+
+ Cache::forget('profile:following:'.$id);
+ Cache::forget('profile:followers:'.$id);
+ Cache::forget('profile:following:'.$pid);
+ Cache::forget('profile:followers:'.$pid);
+ Cache::forget('api:local:exp:rec:'.$pid);
+ Cache::forget('user:account:id:'.$id);
+ Cache::forget('user:account:id:'.$pid);
+ Cache::forget('profile:follower_count:'.$id);
+ Cache::forget('profile:follower_count:'.$pid);
+ Cache::forget('profile:following_count:'.$id);
+ Cache::forget('profile:following_count:'.$pid);
+ AccountService::del($pid);
+ AccountService::del($id);
+
+ $res = RelationshipService::get($id, $pid);
+ return $this->json($res);
+ }
/**
* GET /api/v1/statuses/{id}/pin
*/
diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php
index f9cac94be..a7c796592 100644
--- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php
+++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php
@@ -1307,6 +1307,7 @@ class ApiV1Dot1Controller extends Controller
$media->save();
switch ($media->mime) {
+ case 'image/jpg':
case 'image/jpeg':
case 'image/png':
ImageOptimize::dispatch($media)->onQueue('mmo');
diff --git a/app/Http/Controllers/Api/ApiV2Controller.php b/app/Http/Controllers/Api/ApiV2Controller.php
index bf248bf0e..f8794b323 100644
--- a/app/Http/Controllers/Api/ApiV2Controller.php
+++ b/app/Http/Controllers/Api/ApiV2Controller.php
@@ -310,6 +310,7 @@ class ApiV2Controller extends Controller
switch ($media->mime) {
case 'image/jpeg':
+ case 'image/jpg':
case 'image/png':
ImageOptimize::dispatch($media)->onQueue('mmo');
break;
diff --git a/app/Http/Controllers/ComposeController.php b/app/Http/Controllers/ComposeController.php
index 721401d01..088febe83 100644
--- a/app/Http/Controllers/ComposeController.php
+++ b/app/Http/Controllers/ComposeController.php
@@ -268,10 +268,11 @@ class ComposeController extends Controller
$blocked->push($request->user()->profile_id);
+ $operator = config('database.default') === 'pgsql' ? 'ilike' : 'like';
$results = Profile::select('id', 'domain', 'username')
->whereNotIn('id', $blocked)
->whereNull('domain')
- ->where('username', 'like', '%'.$q.'%')
+ ->where('username', $operator, '%'.$q.'%')
->limit(15)
->get()
->map(function ($r) {
diff --git a/app/Http/Controllers/ImportPostController.php b/app/Http/Controllers/ImportPostController.php
index e491019f8..39a6257b2 100644
--- a/app/Http/Controllers/ImportPostController.php
+++ b/app/Http/Controllers/ImportPostController.php
@@ -201,7 +201,7 @@ class ImportPostController extends Controller
$this->checkPermissions($request);
- $allowedMimeTypes = ['image/png', 'image/jpeg'];
+ $allowedMimeTypes = ['image/png', 'image/jpeg', 'image/jpg'];
if (config('import.instagram.allow_image_webp') && str_contains(config_cache('pixelfed.media_types'), 'image/webp')) {
$allowedMimeTypes[] = 'image/webp';
diff --git a/app/Http/Controllers/RemoteAuthController.php b/app/Http/Controllers/RemoteAuthController.php
index 73d4c5592..5f559761a 100644
--- a/app/Http/Controllers/RemoteAuthController.php
+++ b/app/Http/Controllers/RemoteAuthController.php
@@ -14,6 +14,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
+use App\Rules\PixelfedUsername;
use InvalidArgumentException;
use Purify;
@@ -359,37 +360,7 @@ class RemoteAuthController extends Controller
'required',
'min:2',
'max:30',
- function ($attribute, $value, $fail) {
- $dash = substr_count($value, '-');
- $underscore = substr_count($value, '_');
- $period = substr_count($value, '.');
-
- if (ends_with($value, ['.php', '.js', '.css'])) {
- return $fail('Username is invalid.');
- }
-
- if (($dash + $underscore + $period) > 1) {
- return $fail('Username is invalid. Can only contain one dash (-), period (.) or underscore (_).');
- }
-
- if (! ctype_alnum($value[0])) {
- return $fail('Username is invalid. Must start with a letter or number.');
- }
-
- if (! ctype_alnum($value[strlen($value) - 1])) {
- return $fail('Username is invalid. Must end with a letter or number.');
- }
-
- $val = str_replace(['_', '.', '-'], '', $value);
- if (! ctype_alnum($val)) {
- return $fail('Username is invalid. Username must be alpha-numeric and may contain dashes (-), periods (.) and underscores (_).');
- }
-
- $restricted = RestrictedNames::get();
- if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
- return $fail('Username cannot be used.');
- }
- },
+ new PixelfedUsername(),
],
]);
$username = strtolower($request->input('username'));
diff --git a/app/Http/Controllers/RemoteOidcController.php b/app/Http/Controllers/RemoteOidcController.php
new file mode 100644
index 000000000..8f30d9baa
--- /dev/null
+++ b/app/Http/Controllers/RemoteOidcController.php
@@ -0,0 +1,121 @@
+user()) {
+ return redirect('/');
+ }
+
+ $url = $provider->getAuthorizationUrl([
+ 'scope' => $provider->getDefaultScopes(),
+ ]);
+
+ $request->session()->put('oauth2state', $provider->getState());
+
+ return redirect($url);
+ }
+
+ public function handleCallback(UserOidcService $provider, Request $request)
+ {
+ abort_unless((bool) config('remote-auth.oidc.enabled'), 404);
+
+ if ($request->user()) {
+ return redirect('/');
+ }
+
+ abort_unless($request->input("state"), 400);
+ abort_unless($request->input("code"), 400);
+
+ abort_unless(hash_equals($request->session()->pull('oauth2state'), $request->input("state")), 400, "invalid state");
+
+ $accessToken = $provider->getAccessToken('authorization_code', [
+ 'code' => $request->get('code')
+ ]);
+
+ $userInfo = $provider->getResourceOwner($accessToken);
+ $userInfoId = $userInfo->getId();
+ $userInfoData = $userInfo->toArray();
+
+ $mappedUser = UserOidcMapping::where('oidc_id', $userInfoId)->first();
+ if ($mappedUser) {
+ $this->guarder()->login($mappedUser->user);
+ return redirect('/');
+ }
+
+ abort_if(EmailService::isBanned($userInfoData["email"]), 400, 'Banned email.');
+
+ $user = $this->createUser([
+ 'username' => $userInfoData[config('remote-auth.oidc.field_username')],
+ 'name' => $userInfoData["name"] ?? $userInfoData["display_name"] ?? $userInfoData[config('remote-auth.oidc.field_username')] ?? null,
+ 'email' => $userInfoData["email"],
+ ]);
+
+ UserOidcMapping::create([
+ 'user_id' => $user->id,
+ 'oidc_id' => $userInfoId,
+ ]);
+
+ return redirect('/');
+ }
+
+ protected function createUser($data)
+ {
+ $this->validate(new Request($data), [
+ 'email' => [
+ 'required',
+ 'string',
+ 'email:strict,filter_unicode,dns,spoof',
+ 'max:255',
+ 'unique:users',
+ new EmailNotBanned(),
+ ],
+ 'username' => [
+ 'required',
+ 'min:2',
+ 'max:30',
+ 'unique:users,username',
+ new PixelfedUsername(),
+ ],
+ 'name' => 'nullable|max:30',
+ ]);
+
+ event(new Registered($user = User::create([
+ 'name' => Purify::clean($data['name']),
+ 'username' => $data['username'],
+ 'email' => $data['email'],
+ 'password' => Hash::make(Str::password()),
+ 'email_verified_at' => now(),
+ 'app_register_ip' => request()->ip(),
+ 'register_source' => 'oidc',
+ ])));
+
+ $this->guarder()->login($user);
+
+ return $user;
+ }
+
+ protected function guarder()
+ {
+ return Auth::guard();
+ }
+}
diff --git a/app/Http/Controllers/Stories/StoryApiV1Controller.php b/app/Http/Controllers/Stories/StoryApiV1Controller.php
index 48599fc3a..a1f55c7ef 100644
--- a/app/Http/Controllers/Stories/StoryApiV1Controller.php
+++ b/app/Http/Controllers/Stories/StoryApiV1Controller.php
@@ -260,7 +260,7 @@ class StoryApiV1Controller extends Controller
'file' => function () {
return [
'required',
- 'mimetypes:image/jpeg,image/png,video/mp4',
+ 'mimetypes:image/jpeg,image/jpg,image/png,video/mp4',
'max:'.config_cache('pixelfed.max_photo_size'),
];
},
diff --git a/app/Http/Controllers/StoryComposeController.php b/app/Http/Controllers/StoryComposeController.php
index e02e2d219..44aff1e23 100644
--- a/app/Http/Controllers/StoryComposeController.php
+++ b/app/Http/Controllers/StoryComposeController.php
@@ -34,7 +34,7 @@ class StoryComposeController extends Controller
'file' => function () {
return [
'required',
- 'mimetypes:image/jpeg,image/png,video/mp4',
+ 'mimetypes:image/jpeg,image/png,video/mp4,image/jpg',
'max:'.config_cache('pixelfed.max_photo_size'),
];
},
diff --git a/app/Jobs/ImageOptimizePipeline/ImageOptimize.php b/app/Jobs/ImageOptimizePipeline/ImageOptimize.php
index e2d558143..28685d1f7 100644
--- a/app/Jobs/ImageOptimizePipeline/ImageOptimize.php
+++ b/app/Jobs/ImageOptimizePipeline/ImageOptimize.php
@@ -40,6 +40,9 @@ class ImageOptimize implements ShouldQueue
public function handle()
{
$media = $this->media;
+ if(!$media) {
+ return;
+ }
$path = storage_path('app/'.$media->media_path);
if (!is_file($path) || $media->skip_optimize) {
return;
diff --git a/app/Media.php b/app/Media.php
index 51bc21152..e1c545729 100644
--- a/app/Media.php
+++ b/app/Media.php
@@ -64,7 +64,7 @@ class Media extends Model
return $this->cdn_url;
}
- if ($this->media_path && $this->mime && in_array($this->mime, ['image/jpeg', 'image/png'])) {
+ if ($this->media_path && $this->mime && in_array($this->mime, ['image/jpeg', 'image/png', 'image/jpg'])) {
return $this->remote_media || Str::startsWith($this->media_path, 'http') ?
$this->media_path :
url(Storage::url($this->media_path));
diff --git a/app/Models/UserOidcMapping.php b/app/Models/UserOidcMapping.php
new file mode 100644
index 000000000..8932ff617
--- /dev/null
+++ b/app/Models/UserOidcMapping.php
@@ -0,0 +1,25 @@
+belongsTo(User::class);
+ }
+
+}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 9c5fdb7fa..c9eeba627 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -21,6 +21,7 @@ use App\Observers\UserFilterObserver;
use App\Observers\UserObserver;
use App\Profile;
use App\Services\AccountService;
+use App\Services\UserOidcService;
use App\Status;
use App\StatusHashtag;
use App\User;
@@ -112,6 +113,8 @@ class AppServiceProvider extends ServiceProvider
*/
public function register()
{
- //
+ $this->app->bind(UserOidcService::class, function() {
+ return UserOidcService::build();
+ });
}
}
diff --git a/app/Rules/EmailNotBanned.php b/app/Rules/EmailNotBanned.php
new file mode 100644
index 000000000..3d637ada8
--- /dev/null
+++ b/app/Rules/EmailNotBanned.php
@@ -0,0 +1,25 @@
+ 1) {
+ $fail('Username is invalid. Can only contain one dash (-), period (.) or underscore (_).');
+ return;
+ }
+
+ if (! ctype_alnum($value[0])) {
+ $fail('Username is invalid. Must start with a letter or number.');
+ return;
+ }
+
+ if (! ctype_alnum($value[strlen($value) - 1])) {
+ $fail('Username is invalid. Must end with a letter or number.');
+ return;
+ }
+
+ $val = str_replace(['_', '.', '-'], '', $value);
+ if (! ctype_alnum($val)) {
+ $fail('Username is invalid. Username must be alpha-numeric and may contain dashes (-), periods (.) and underscores (_).');
+ return;
+ }
+
+ $restricted = RestrictedNames::get();
+ if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
+ $fail('Username cannot be used.');
+ return;
+ }
+ }
+}
diff --git a/app/Services/LandingService.php b/app/Services/LandingService.php
index d6180771d..f70f3d41a 100644
--- a/app/Services/LandingService.php
+++ b/app/Services/LandingService.php
@@ -52,6 +52,7 @@ class LandingService
'domain' => config('pixelfed.domain.app'),
'show_directory' => (bool) config_cache('instance.landing.show_directory'),
'show_explore_feed' => (bool) config_cache('instance.landing.show_explore'),
+ 'show_legal_notice_link' => (bool) config('instance.has_legal_notice'),
'open_registration' => (bool) $openReg,
'curated_onboarding' => (bool) config_cache('instance.curated_registration.enabled'),
'version' => config('pixelfed.version'),
diff --git a/app/Services/MediaStorageService.php b/app/Services/MediaStorageService.php
index d4751e102..f746f8acf 100644
--- a/app/Services/MediaStorageService.php
+++ b/app/Services/MediaStorageService.php
@@ -138,6 +138,7 @@ class MediaStorageService
}
$mimes = [
+ 'image/jpg',
'image/jpeg',
'image/png',
'video/mp4',
@@ -166,6 +167,7 @@ class MediaStorageService
$ext = '.gif';
break;
+ case 'image/jpg':
case 'image/jpeg':
$ext = '.jpg';
break;
@@ -219,6 +221,7 @@ class MediaStorageService
$mimes = [
'application/octet-stream',
+ 'image/jpg',
'image/jpeg',
'image/png',
];
@@ -249,7 +252,7 @@ class MediaStorageService
}
$base = ($local ? 'public/cache/' : 'cache/').'avatars/'.$avatar->profile_id;
- $ext = $head['mime'] == 'image/jpeg' ? 'jpg' : 'png';
+ $ext = ($head['mime'] == 'image/png') ? 'png' : 'jpg';
$path = 'avatar_'.strtolower(Str::random(random_int(3, 6))).'.'.$ext;
$tmpBase = storage_path('app/remcache/');
$tmpPath = 'avatar_'.$avatar->profile_id.'-'.$path;
@@ -262,7 +265,7 @@ class MediaStorageService
$mimeCheck = Storage::mimeType('remcache/'.$tmpPath);
- if (! $mimeCheck || ! in_array($mimeCheck, ['image/png', 'image/jpeg'])) {
+ if (! $mimeCheck || ! in_array($mimeCheck, ['image/png', 'image/jpeg', 'image/jpg'])) {
$avatar->last_fetched_at = now();
$avatar->save();
unlink($tmpName);
diff --git a/app/Services/UserOidcService.php b/app/Services/UserOidcService.php
new file mode 100644
index 000000000..c89975935
--- /dev/null
+++ b/app/Services/UserOidcService.php
@@ -0,0 +1,21 @@
+ config('remote-auth.oidc.clientId'),
+ 'clientSecret' => config('remote-auth.oidc.clientSecret'),
+ 'redirectUri' => url('auth/oidc/callback'),
+ 'urlAuthorize' => config('remote-auth.oidc.authorizeURL'),
+ 'urlAccessToken' => config('remote-auth.oidc.tokenURL'),
+ 'urlResourceOwnerDetails' => config('remote-auth.oidc.profileURL'),
+ 'scopes' => config('remote-auth.oidc.scopes'),
+ 'responseResourceOwnerId' => config('remote-auth.oidc.field_id'),
+ ]);
+ }
+}
diff --git a/app/Status.php b/app/Status.php
index 8b69c199c..be209efe4 100644
--- a/app/Status.php
+++ b/app/Status.php
@@ -15,104 +15,104 @@ use Illuminate\Support\Str;
class Status extends Model
{
- use HasSnowflakePrimary, SoftDeletes;
-
- /**
- * Indicates if the IDs are auto-incrementing.
- *
- * @var bool
- */
- public $incrementing = false;
-
- /**
- * The attributes that should be mutated to dates.
- *
- * @var array
- */
- protected $casts = [
- 'deleted_at' => 'datetime',
- 'edited_at' => 'datetime'
- ];
-
- protected $guarded = [];
-
- const STATUS_TYPES = [
- 'text',
- 'photo',
- 'photo:album',
- 'video',
- 'video:album',
- 'photo:video:album',
- 'share',
- 'reply',
- 'story',
- 'story:reply',
- 'story:reaction',
- 'story:live',
- 'loop'
- ];
-
- const MAX_MENTIONS = 20;
-
- const MAX_HASHTAGS = 60;
-
- const MAX_LINKS = 5;
-
- public function profile()
- {
- return $this->belongsTo(Profile::class);
- }
-
- public function media()
- {
- return $this->hasMany(Media::class);
- }
-
- public function firstMedia()
- {
- return $this->hasMany(Media::class)->orderBy('order', 'asc')->first();
- }
-
- public function viewType()
- {
- if($this->type) {
- return $this->type;
- }
- return $this->setType();
- }
-
- public function setType()
- {
- if(in_array($this->type, self::STATUS_TYPES)) {
- return $this->type;
- }
- $mimes = $this->media->pluck('mime')->toArray();
- $type = StatusController::mimeTypeCheck($mimes);
- if($type) {
- $this->type = $type;
- $this->save();
- return $type;
- }
- }
-
- public function thumb($showNsfw = false)
- {
- $entity = StatusService::get($this->id, false);
-
- if(!$entity || !isset($entity['media_attachments']) || empty($entity['media_attachments'])) {
- return url(Storage::url('public/no-preview.png'));
- }
-
- if((!isset($entity['sensitive']) || $entity['sensitive']) && !$showNsfw) {
- return url(Storage::url('public/no-preview.png'));
- }
+ use HasSnowflakePrimary, SoftDeletes;
+
+ /**
+ * Indicates if the IDs are auto-incrementing.
+ *
+ * @var bool
+ */
+ public $incrementing = false;
+
+ /**
+ * The attributes that should be mutated to dates.
+ *
+ * @var array
+ */
+ protected $casts = [
+ 'deleted_at' => 'datetime',
+ 'edited_at' => 'datetime'
+ ];
+
+ protected $guarded = [];
+
+ const STATUS_TYPES = [
+ 'text',
+ 'photo',
+ 'photo:album',
+ 'video',
+ 'video:album',
+ 'photo:video:album',
+ 'share',
+ 'reply',
+ 'story',
+ 'story:reply',
+ 'story:reaction',
+ 'story:live',
+ 'loop'
+ ];
+
+ const MAX_MENTIONS = 20;
+
+ const MAX_HASHTAGS = 60;
+
+ const MAX_LINKS = 5;
+
+ public function profile()
+ {
+ return $this->belongsTo(Profile::class);
+ }
+
+ public function media()
+ {
+ return $this->hasMany(Media::class);
+ }
+
+ public function firstMedia()
+ {
+ return $this->hasMany(Media::class)->orderBy('order', 'asc')->first();
+ }
+
+ public function viewType()
+ {
+ if($this->type) {
+ return $this->type;
+ }
+ return $this->setType();
+ }
+
+ public function setType()
+ {
+ if(in_array($this->type, self::STATUS_TYPES)) {
+ return $this->type;
+ }
+ $mimes = $this->media->pluck('mime')->toArray();
+ $type = StatusController::mimeTypeCheck($mimes);
+ if($type) {
+ $this->type = $type;
+ $this->save();
+ return $type;
+ }
+ }
+
+ public function thumb($showNsfw = false)
+ {
+ $entity = StatusService::get($this->id, false);
+
+ if(!$entity || !isset($entity['media_attachments']) || empty($entity['media_attachments'])) {
+ return url(Storage::url('public/no-preview.png'));
+ }
+
+ if((!isset($entity['sensitive']) || $entity['sensitive']) && !$showNsfw) {
+ return url(Storage::url('public/no-preview.png'));
+ }
if(!isset($entity['visibility']) || !in_array($entity['visibility'], ['public', 'unlisted'])) {
return url(Storage::url('public/no-preview.png'));
}
- return collect($entity['media_attachments'])
- ->filter(fn($media) => $media['type'] == 'image' && in_array($media['mime'], ['image/jpeg', 'image/png']))
+ return collect($entity['media_attachments'])
+ ->filter(fn($media) => $media['type'] == 'image' && in_array($media['mime'], ['image/jpeg', 'image/png', 'image/jpg']))
->map(function($media) {
if(!Str::endsWith($media['preview_url'], ['no-preview.png', 'no-preview.jpg'])) {
return $media['preview_url'];
@@ -121,259 +121,259 @@ class Status extends Model
return $media['url'];
})
->first() ?? url(Storage::url('public/no-preview.png'));
- }
-
- public function url($forceLocal = false)
- {
- if($this->uri) {
- return $forceLocal ? "/i/web/post/_/{$this->profile_id}/{$this->id}" : $this->uri;
- } else {
- $id = $this->id;
- $account = AccountService::get($this->profile_id, true);
- if(!$account || !isset($account['username'])) {
- return '/404';
- }
- $path = url(config('app.url')."/p/{$account['username']}/{$id}");
- return $path;
- }
- }
-
- public function permalink($suffix = '/activity')
- {
- $id = $this->id;
- $username = $this->profile->username;
- $path = config('app.url')."/p/{$username}/{$id}{$suffix}";
-
- return url($path);
- }
-
- public function editUrl()
- {
- return $this->url().'/edit';
- }
-
- public function mediaUrl()
- {
- $media = $this->firstMedia();
- $path = $media->media_path;
- $hash = is_null($media->processed_at) ? md5('unprocessed') : md5($media->created_at);
- $url = $media->cdn_url ? $media->cdn_url . "?v={$hash}" : url(Storage::url($path)."?v={$hash}");
-
- return $url;
- }
-
- public function likes()
- {
- return $this->hasMany(Like::class);
- }
-
- public function liked() : bool
- {
- if(!Auth::check()) {
- return false;
- }
-
- $pid = Auth::user()->profile_id;
-
- return Like::select('status_id', 'profile_id')
- ->whereStatusId($this->id)
- ->whereProfileId($pid)
- ->exists();
- }
-
- public function likedBy()
- {
- return $this->hasManyThrough(
- Profile::class,
- Like::class,
- 'status_id',
- 'id',
- 'id',
- 'profile_id'
- );
- }
-
- public function comments()
- {
- return $this->hasMany(self::class, 'in_reply_to_id');
- }
-
- public function bookmarked()
- {
- if (!Auth::check()) {
- return false;
- }
- $profile = Auth::user()->profile;
-
- return Bookmark::whereProfileId($profile->id)->whereStatusId($this->id)->count();
- }
-
- public function shares()
- {
- return $this->hasMany(self::class, 'reblog_of_id');
- }
-
- public function shared() : bool
- {
- if(!Auth::check()) {
- return false;
- }
- $pid = Auth::user()->profile_id;
-
- return $this->select('profile_id', 'reblog_of_id')
- ->whereProfileId($pid)
- ->whereReblogOfId($this->id)
- ->exists();
- }
-
- public function sharedBy()
- {
- return $this->hasManyThrough(
- Profile::class,
- Status::class,
- 'reblog_of_id',
- 'id',
- 'id',
- 'profile_id'
- );
- }
-
- public function parent()
- {
- $parent = $this->in_reply_to_id ?? $this->reblog_of_id;
- if (!empty($parent)) {
- return $this->findOrFail($parent);
- } else {
- return false;
- }
- }
-
- public function conversation()
- {
- return $this->hasOne(Conversation::class);
- }
-
- public function hashtags()
- {
- return $this->hasManyThrough(
- Hashtag::class,
- StatusHashtag::class,
- 'status_id',
- 'id',
- 'id',
- 'hashtag_id'
- );
- }
-
- public function mentions()
- {
- return $this->hasManyThrough(
- Profile::class,
- Mention::class,
- 'status_id',
- 'id',
- 'id',
- 'profile_id'
- );
- }
-
- public function reportUrl()
- {
- return route('report.form')."?type=post&id={$this->id}";
- }
-
- public function toActivityStream()
- {
- $media = $this->media;
- $mediaCollection = [];
- foreach ($media as $image) {
- $mediaCollection[] = [
- 'type' => 'Link',
- 'href' => $image->url(),
- 'mediaType' => $image->mime,
- ];
- }
- $obj = [
- '@context' => 'https://www.w3.org/ns/activitystreams',
- 'type' => 'Image',
- 'name' => null,
- 'url' => $mediaCollection,
- ];
-
- return $obj;
- }
-
- public function recentComments()
- {
- return $this->comments()->orderBy('created_at', 'desc')->take(3);
- }
-
- public function scopeToAudience($audience)
- {
- if(!in_array($audience, ['to', 'cc']) || $this->local == false) {
- return;
- }
- $res = [];
- $res['to'] = [];
- $res['cc'] = [];
- $scope = $this->scope;
- $mentions = $this->mentions->map(function ($mention) {
- return $mention->permalink();
- })->toArray();
-
- if($this->in_reply_to_id != null) {
- $parent = $this->parent();
- if($parent) {
- $mentions = array_merge([$parent->profile->permalink()], $mentions);
- }
- }
-
- switch ($scope) {
- case 'public':
- $res['to'] = [
- "https://www.w3.org/ns/activitystreams#Public"
- ];
- $res['cc'] = array_merge([$this->profile->permalink('/followers')], $mentions);
- break;
-
- case 'unlisted':
- $res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
- $res['cc'] = [
- "https://www.w3.org/ns/activitystreams#Public"
- ];
- break;
-
- case 'private':
- $res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
- $res['cc'] = [];
- break;
-
- // TODO: Update scope when DMs are supported
- case 'direct':
- $res['to'] = [];
- $res['cc'] = [];
- break;
- }
- return $res[$audience];
- }
-
- public function place()
- {
- return $this->belongsTo(Place::class);
- }
-
- public function directMessage()
- {
- return $this->hasOne(DirectMessage::class);
- }
-
- public function poll()
- {
- return $this->hasOne(Poll::class);
- }
-
- public function edits()
- {
- return $this->hasMany(StatusEdit::class);
- }
+ }
+
+ public function url($forceLocal = false)
+ {
+ if($this->uri) {
+ return $forceLocal ? "/i/web/post/_/{$this->profile_id}/{$this->id}" : $this->uri;
+ } else {
+ $id = $this->id;
+ $account = AccountService::get($this->profile_id, true);
+ if(!$account || !isset($account['username'])) {
+ return '/404';
+ }
+ $path = url(config('app.url')."/p/{$account['username']}/{$id}");
+ return $path;
+ }
+ }
+
+ public function permalink($suffix = '/activity')
+ {
+ $id = $this->id;
+ $username = $this->profile->username;
+ $path = config('app.url')."/p/{$username}/{$id}{$suffix}";
+
+ return url($path);
+ }
+
+ public function editUrl()
+ {
+ return $this->url().'/edit';
+ }
+
+ public function mediaUrl()
+ {
+ $media = $this->firstMedia();
+ $path = $media->media_path;
+ $hash = is_null($media->processed_at) ? md5('unprocessed') : md5($media->created_at);
+ $url = $media->cdn_url ? $media->cdn_url . "?v={$hash}" : url(Storage::url($path)."?v={$hash}");
+
+ return $url;
+ }
+
+ public function likes()
+ {
+ return $this->hasMany(Like::class);
+ }
+
+ public function liked() : bool
+ {
+ if(!Auth::check()) {
+ return false;
+ }
+
+ $pid = Auth::user()->profile_id;
+
+ return Like::select('status_id', 'profile_id')
+ ->whereStatusId($this->id)
+ ->whereProfileId($pid)
+ ->exists();
+ }
+
+ public function likedBy()
+ {
+ return $this->hasManyThrough(
+ Profile::class,
+ Like::class,
+ 'status_id',
+ 'id',
+ 'id',
+ 'profile_id'
+ );
+ }
+
+ public function comments()
+ {
+ return $this->hasMany(self::class, 'in_reply_to_id');
+ }
+
+ public function bookmarked()
+ {
+ if (!Auth::check()) {
+ return false;
+ }
+ $profile = Auth::user()->profile;
+
+ return Bookmark::whereProfileId($profile->id)->whereStatusId($this->id)->count();
+ }
+
+ public function shares()
+ {
+ return $this->hasMany(self::class, 'reblog_of_id');
+ }
+
+ public function shared() : bool
+ {
+ if(!Auth::check()) {
+ return false;
+ }
+ $pid = Auth::user()->profile_id;
+
+ return $this->select('profile_id', 'reblog_of_id')
+ ->whereProfileId($pid)
+ ->whereReblogOfId($this->id)
+ ->exists();
+ }
+
+ public function sharedBy()
+ {
+ return $this->hasManyThrough(
+ Profile::class,
+ Status::class,
+ 'reblog_of_id',
+ 'id',
+ 'id',
+ 'profile_id'
+ );
+ }
+
+ public function parent()
+ {
+ $parent = $this->in_reply_to_id ?? $this->reblog_of_id;
+ if (!empty($parent)) {
+ return $this->findOrFail($parent);
+ } else {
+ return false;
+ }
+ }
+
+ public function conversation()
+ {
+ return $this->hasOne(Conversation::class);
+ }
+
+ public function hashtags()
+ {
+ return $this->hasManyThrough(
+ Hashtag::class,
+ StatusHashtag::class,
+ 'status_id',
+ 'id',
+ 'id',
+ 'hashtag_id'
+ );
+ }
+
+ public function mentions()
+ {
+ return $this->hasManyThrough(
+ Profile::class,
+ Mention::class,
+ 'status_id',
+ 'id',
+ 'id',
+ 'profile_id'
+ );
+ }
+
+ public function reportUrl()
+ {
+ return route('report.form')."?type=post&id={$this->id}";
+ }
+
+ public function toActivityStream()
+ {
+ $media = $this->media;
+ $mediaCollection = [];
+ foreach ($media as $image) {
+ $mediaCollection[] = [
+ 'type' => 'Link',
+ 'href' => $image->url(),
+ 'mediaType' => $image->mime,
+ ];
+ }
+ $obj = [
+ '@context' => 'https://www.w3.org/ns/activitystreams',
+ 'type' => 'Image',
+ 'name' => null,
+ 'url' => $mediaCollection,
+ ];
+
+ return $obj;
+ }
+
+ public function recentComments()
+ {
+ return $this->comments()->orderBy('created_at', 'desc')->take(3);
+ }
+
+ public function scopeToAudience($audience)
+ {
+ if(!in_array($audience, ['to', 'cc']) || $this->local == false) {
+ return;
+ }
+ $res = [];
+ $res['to'] = [];
+ $res['cc'] = [];
+ $scope = $this->scope;
+ $mentions = $this->mentions->map(function ($mention) {
+ return $mention->permalink();
+ })->toArray();
+
+ if($this->in_reply_to_id != null) {
+ $parent = $this->parent();
+ if($parent) {
+ $mentions = array_merge([$parent->profile->permalink()], $mentions);
+ }
+ }
+
+ switch ($scope) {
+ case 'public':
+ $res['to'] = [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ];
+ $res['cc'] = array_merge([$this->profile->permalink('/followers')], $mentions);
+ break;
+
+ case 'unlisted':
+ $res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
+ $res['cc'] = [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ];
+ break;
+
+ case 'private':
+ $res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
+ $res['cc'] = [];
+ break;
+
+ // TODO: Update scope when DMs are supported
+ case 'direct':
+ $res['to'] = [];
+ $res['cc'] = [];
+ break;
+ }
+ return $res[$audience];
+ }
+
+ public function place()
+ {
+ return $this->belongsTo(Place::class);
+ }
+
+ public function directMessage()
+ {
+ return $this->hasOne(DirectMessage::class);
+ }
+
+ public function poll()
+ {
+ return $this->hasOne(Poll::class);
+ }
+
+ public function edits()
+ {
+ return $this->hasMany(StatusEdit::class);
+ }
}
diff --git a/app/Util/ActivityPub/Helpers.php b/app/Util/ActivityPub/Helpers.php
index 7be32ede7..4ee4929c6 100644
--- a/app/Util/ActivityPub/Helpers.php
+++ b/app/Util/ActivityPub/Helpers.php
@@ -175,7 +175,7 @@ class Helpers
return false;
}
- if (! self::passesSecurityChecks($host, $disableDNSCheck, $forceBanCheck)) {
+ if (!$disableDNSCheck && ! self::passesSecurityChecks($host, $disableDNSCheck, $forceBanCheck)) {
return false;
}
diff --git a/app/Util/Media/Blurhash.php b/app/Util/Media/Blurhash.php
index 8e232ea17..037c2d70a 100644
--- a/app/Util/Media/Blurhash.php
+++ b/app/Util/Media/Blurhash.php
@@ -7,53 +7,52 @@ use App\Media;
class Blurhash {
- const DEFAULT_HASH = 'U4Rfzst8?bt7ogayj[j[~pfQ9Goe%Mj[WBay';
-
- public static function generate(Media $media)
- {
- if(!in_array($media->mime, ['image/png', 'image/jpeg', 'video/mp4'])) {
- return self::DEFAULT_HASH;
- }
-
- if($media->thumbnail_path == null) {
- return self::DEFAULT_HASH;
- }
-
- $file = storage_path('app/' . $media->thumbnail_path);
-
- if(!is_file($file)) {
- return self::DEFAULT_HASH;
- }
-
- $image = imagecreatefromstring(file_get_contents($file));
- if(!$image) {
- return self::DEFAULT_HASH;
- }
- $width = imagesx($image);
- $height = imagesy($image);
-
- $pixels = [];
- for ($y = 0; $y < $height; ++$y) {
- $row = [];
- for ($x = 0; $x < $width; ++$x) {
- $index = imagecolorat($image, $x, $y);
- $colors = imagecolorsforindex($image, $index);
-
- $row[] = [$colors['red'], $colors['green'], $colors['blue']];
- }
- $pixels[] = $row;
- }
-
- // Free the allocated GdImage object from memory:
- imagedestroy($image);
-
- $components_x = 4;
- $components_y = 4;
- $blurhash = BlurhashEngine::encode($pixels, $components_x, $components_y);
- if(strlen($blurhash) > 191) {
- return self::DEFAULT_HASH;
- }
- return $blurhash;
- }
+ const DEFAULT_HASH = 'U4Rfzst8?bt7ogayj[j[~pfQ9Goe%Mj[WBay';
+
+ public static function generate(Media $media)
+ {
+ if(!in_array($media->mime, ['image/png', 'image/jpeg', 'image/jpg', 'video/mp4'])) {
+ return self::DEFAULT_HASH;
+ }
+
+ if($media->thumbnail_path == null) {
+ return self::DEFAULT_HASH;
+ }
+
+ $file = storage_path('app/' . $media->thumbnail_path);
+
+ if(!is_file($file)) {
+ return self::DEFAULT_HASH;
+ }
+
+ $image = imagecreatefromstring(file_get_contents($file));
+ if(!$image) {
+ return self::DEFAULT_HASH;
+ }
+ $width = imagesx($image);
+ $height = imagesy($image);
+
+ $pixels = [];
+ for ($y = 0; $y < $height; ++$y) {
+ $row = [];
+ for ($x = 0; $x < $width; ++$x) {
+ $index = imagecolorat($image, $x, $y);
+ $colors = imagecolorsforindex($image, $index);
+
+ $row[] = [$colors['red'], $colors['green'], $colors['blue']];
+ }
+ $pixels[] = $row;
+ }
+
+ imagedestroy($image);
+
+ $components_x = 4;
+ $components_y = 4;
+ $blurhash = BlurhashEngine::encode($pixels, $components_x, $components_y);
+ if(strlen($blurhash) > 191) {
+ return self::DEFAULT_HASH;
+ }
+ return $blurhash;
+ }
}
diff --git a/app/Util/Media/Image.php b/app/Util/Media/Image.php
index bbd3918ad..f77045046 100644
--- a/app/Util/Media/Image.php
+++ b/app/Util/Media/Image.php
@@ -3,223 +3,281 @@
namespace App\Util\Media;
use App\Media;
-use Image as Intervention;
+use Intervention\Image\ImageManager;
+use Intervention\Image\Encoders\JpegEncoder;
+use Intervention\Image\Encoders\WebpEncoder;
+use Intervention\Image\Encoders\AvifEncoder;
+use Intervention\Image\Encoders\PngEncoder;
use Cache, Log, Storage;
+use App\Util\Media\Blurhash;
class Image
{
- public $square;
- public $landscape;
- public $portrait;
- public $thumbnail;
- public $orientation;
- public $acceptedMimes = [
- 'image/png',
- 'image/jpeg',
- 'image/webp',
- 'image/avif',
- ];
-
- public function __construct()
- {
- ini_set('memory_limit', config('pixelfed.memory_limit', '1024M'));
-
- $this->square = $this->orientations()['square'];
- $this->landscape = $this->orientations()['landscape'];
- $this->portrait = $this->orientations()['portrait'];
- $this->thumbnail = [
- 'width' => 640,
- 'height' => 640,
- ];
- $this->orientation = null;
- }
-
- public function orientations()
- {
- return [
- 'square' => [
- 'width' => 1080,
- 'height' => 1080,
- ],
- 'landscape' => [
- 'width' => 1920,
- 'height' => 1080,
- ],
- 'portrait' => [
- 'width' => 1080,
- 'height' => 1350,
- ],
- ];
- }
-
- public function getAspectRatio($mediaPath, $thumbnail = false)
- {
- if (!is_file($mediaPath)) {
- throw new \Exception('Invalid Media Path');
- }
- if ($thumbnail) {
- return [
- 'dimensions' => $this->thumbnail,
- 'orientation' => 'thumbnail',
- ];
- }
-
- list($width, $height) = getimagesize($mediaPath);
- $aspect = $width / $height;
- $orientation = $aspect === 1 ? 'square' :
- ($aspect > 1 ? 'landscape' : 'portrait');
- $this->orientation = $orientation;
-
- return [
- 'dimensions' => $this->orientations()[$orientation],
- 'orientation' => $orientation,
- 'width_original' => $width,
- 'height_original' => $height,
- ];
- }
-
- public function resizeImage(Media $media)
- {
- $basePath = storage_path('app/'.$media->media_path);
-
- $this->handleResizeImage($media);
- }
-
- public function resizeThumbnail(Media $media)
- {
- $basePath = storage_path('app/'.$media->media_path);
-
- $this->handleThumbnailImage($media);
- }
-
- public function handleResizeImage(Media $media)
- {
- $this->handleImageTransform($media, false);
- }
-
- public function handleThumbnailImage(Media $media)
- {
- $this->handleImageTransform($media, true);
- }
-
- public function handleImageTransform(Media $media, $thumbnail = false)
- {
- $path = $media->media_path;
- $file = storage_path('app/'.$path);
- if (!in_array($media->mime, $this->acceptedMimes)) {
- return;
- }
- $ratio = $this->getAspectRatio($file, $thumbnail);
- $aspect = $ratio['dimensions'];
- $orientation = $ratio['orientation'];
-
- try {
- $img = Intervention::make($file);
- $metadata = $img->exif();
- $img->orientate();
- if($thumbnail) {
- $img->resize($aspect['width'], $aspect['height'], function ($constraint) {
- $constraint->aspectRatio();
- });
- } else {
- if(config('media.exif.database', false) == true && $metadata) {
- $meta = [];
- $keys = [
- "COMPUTED",
- "FileName",
- "FileSize",
- "FileType",
- "Make",
- "Model",
- "MimeType",
- "ColorSpace",
- "ExifVersion",
- "Orientation",
- "UserComment",
- "XResolution",
- "YResolution",
- "FileDateTime",
- "SectionsFound",
- "ExifImageWidth",
- "ResolutionUnit",
- "ExifImageLength",
- "FlashPixVersion",
- "Exif_IFD_Pointer",
- "YCbCrPositioning",
- "ComponentsConfiguration",
- "ExposureTime",
- "FNumber",
- "ISOSpeedRatings",
- "ShutterSpeedValue"
- ];
- foreach ($metadata as $k => $v) {
- if(in_array($k, $keys)) {
- $meta[$k] = $v;
- }
- }
- $media->metadata = json_encode($meta);
- }
-
- if (
- ($ratio['width_original'] > $aspect['width'])
- || ($ratio['height_original'] > $aspect['height'])
- ) {
- $img->resize($aspect['width'], $aspect['height'], function ($constraint) {
- $constraint->aspectRatio();
- });
- }
- }
- $converted = $this->setBaseName($path, $thumbnail, $img->extension);
- $newPath = storage_path('app/'.$converted['path']);
-
- $quality = config_cache('pixelfed.image_quality');
- $img->save($newPath, $quality);
-
- if ($thumbnail == true) {
- $media->thumbnail_path = $converted['path'];
- $media->thumbnail_url = url(Storage::url($converted['path']));
- } else {
- $media->width = $img->width();
- $media->height = $img->height();
- $media->orientation = $orientation;
- $media->media_path = $converted['path'];
- $media->mime = $img->mime;
- }
-
- $img->destroy();
- $media->save();
-
- if($thumbnail) {
- $this->generateBlurhash($media);
- }
-
- Cache::forget('status:transformer:media:attachments:'.$media->status_id);
- Cache::forget('status:thumb:'.$media->status_id);
-
- } catch (Exception $e) {
- $media->processed_at = now();
- $media->save();
- Log::info('MediaResizeException: Could not process media id: ' . $media->id);
- }
- }
-
- public function setBaseName($basePath, $thumbnail, $extension)
- {
- $png = false;
- $path = explode('.', $basePath);
- $name = ($thumbnail == true) ? $path[0].'_thumb' : $path[0];
- $ext = last($path);
- $basePath = "{$name}.{$ext}";
-
- return ['path' => $basePath, 'png' => $png];
- }
-
- protected function generateBlurhash($media)
- {
- $blurhash = Blurhash::generate($media);
- if($blurhash) {
- $media->blurhash = $blurhash;
- $media->save();
- }
- }
+ public $square;
+ public $landscape;
+ public $portrait;
+ public $thumbnail;
+ public $orientation;
+ public $acceptedMimes = [
+ 'image/png',
+ 'image/jpeg',
+ 'image/jpg',
+ 'image/webp',
+ 'image/avif',
+ 'image/heic',
+ ];
+
+ protected $imageManager;
+
+ public function __construct()
+ {
+ ini_set('memory_limit', config('pixelfed.memory_limit', '1024M'));
+
+ $this->square = $this->orientations()['square'];
+ $this->landscape = $this->orientations()['landscape'];
+ $this->portrait = $this->orientations()['portrait'];
+ $this->thumbnail = [
+ 'width' => 640,
+ 'height' => 640,
+ ];
+ $this->orientation = null;
+
+ $driver = match(config('image.driver')) {
+ 'imagick' => new \Intervention\Image\Drivers\Imagick\Driver(),
+ 'vips' => new \Intervention\Image\Drivers\Vips\Driver(),
+ default => new \Intervention\Image\Drivers\Gd\Driver()
+ };
+
+ $this->imageManager = new ImageManager(
+ $driver,
+ autoOrientation: true,
+ decodeAnimation: true,
+ blendingColor: 'ffffff',
+ strip: true
+ );
+ }
+
+ public function orientations()
+ {
+ return [
+ 'square' => [
+ 'width' => 1080,
+ 'height' => 1080,
+ ],
+ 'landscape' => [
+ 'width' => 1920,
+ 'height' => 1080,
+ ],
+ 'portrait' => [
+ 'width' => 1080,
+ 'height' => 1350,
+ ],
+ ];
+ }
+
+ public function getAspectRatio($mediaPath, $thumbnail = false)
+ {
+ if ($thumbnail) {
+ return [
+ 'dimensions' => $this->thumbnail,
+ 'orientation' => 'thumbnail',
+ ];
+ }
+
+ if (!is_file($mediaPath)) {
+ throw new \Exception('Invalid Media Path');
+ }
+
+ list($width, $height) = getimagesize($mediaPath);
+ $aspect = $width / $height;
+ $orientation = $aspect === 1 ? 'square' :
+ ($aspect > 1 ? 'landscape' : 'portrait');
+ $this->orientation = $orientation;
+
+ return [
+ 'dimensions' => $this->orientations()[$orientation],
+ 'orientation' => $orientation,
+ 'width_original' => $width,
+ 'height_original' => $height,
+ ];
+ }
+
+ public function resizeImage(Media $media)
+ {
+ $this->handleResizeImage($media);
+ }
+
+ public function resizeThumbnail(Media $media)
+ {
+ $this->handleThumbnailImage($media);
+ }
+
+ public function handleResizeImage(Media $media)
+ {
+ $this->handleImageTransform($media, false);
+ }
+
+ public function handleThumbnailImage(Media $media)
+ {
+ $this->handleImageTransform($media, true);
+ }
+
+ public function handleImageTransform(Media $media, $thumbnail = false)
+ {
+ $path = $media->media_path;
+ $file = storage_path('app/'.$path);
+ if (!in_array($media->mime, $this->acceptedMimes)) {
+ return;
+ }
+ $ratio = $this->getAspectRatio($file, $thumbnail);
+ $aspect = $ratio['dimensions'];
+ $orientation = $ratio['orientation'];
+
+ try {
+ $fileInfo = pathinfo($file);
+ $extension = strtolower($fileInfo['extension'] ?? 'jpg');
+
+ $metadata = null;
+ if (!$thumbnail && config('media.exif.database', false) == true) {
+ try {
+ $exif = @exif_read_data($file);
+ if ($exif) {
+ $meta = [];
+ $keys = [
+ "FileName",
+ "FileSize",
+ "FileType",
+ "Make",
+ "Model",
+ "MimeType",
+ "ColorSpace",
+ "ExifVersion",
+ "Orientation",
+ "UserComment",
+ "XResolution",
+ "YResolution",
+ "FileDateTime",
+ "SectionsFound",
+ "ExifImageWidth",
+ "ResolutionUnit",
+ "ExifImageLength",
+ "FlashPixVersion",
+ "Exif_IFD_Pointer",
+ "YCbCrPositioning",
+ "ComponentsConfiguration",
+ "ExposureTime",
+ "FNumber",
+ "ISOSpeedRatings",
+ "ShutterSpeedValue"
+ ];
+ foreach ($exif as $k => $v) {
+ if (in_array($k, $keys)) {
+ $meta[$k] = $v;
+ }
+ }
+ $media->metadata = json_encode($meta);
+ }
+ } catch (\Exception $e) {
+ Log::info('EXIF extraction failed: ' . $e->getMessage());
+ }
+ }
+
+ $img = $this->imageManager->read($file);
+
+ if ($thumbnail) {
+ $img = $img->coverDown(
+ $aspect['width'],
+ $aspect['height']
+ );
+ } else {
+ if (
+ ($ratio['width_original'] > $aspect['width'])
+ || ($ratio['height_original'] > $aspect['height'])
+ ) {
+ $img = $img->scaleDown(
+ $aspect['width'],
+ $aspect['height']
+ );
+ }
+ }
+
+ $converted = $this->setBaseName($path, $thumbnail, $extension);
+ $newPath = storage_path('app/'.$converted['path']);
+
+ $quality = config_cache('pixelfed.image_quality');
+
+ $encoder = null;
+ switch ($extension) {
+ case 'jpeg':
+ case 'jpg':
+ $encoder = new JpegEncoder($quality);
+ break;
+ case 'png':
+ $encoder = new PngEncoder();
+ break;
+ case 'webp':
+ $encoder = new WebpEncoder($quality);
+ break;
+ case 'avif':
+ $encoder = new AvifEncoder($quality);
+ break;
+ case 'heic':
+ $encoder = new JpegEncoder($quality);
+ $extension = 'jpg';
+ break;
+ default:
+ $encoder = new JpegEncoder($quality);
+ $extension = 'jpg';
+ }
+
+ $encoded = $encoder->encode($img);
+
+ file_put_contents($newPath, $encoded->toString());
+
+ if ($thumbnail == true) {
+ $media->thumbnail_path = $converted['path'];
+ $media->thumbnail_url = url(Storage::url($converted['path']));
+ } else {
+ $media->width = $img->width();
+ $media->height = $img->height();
+ $media->orientation = $orientation;
+ $media->media_path = $converted['path'];
+ $media->mime = 'image/' . $extension;
+ }
+
+ $media->save();
+
+ if ($thumbnail) {
+ $this->generateBlurhash($media);
+ }
+
+ Cache::forget('status:transformer:media:attachments:'.$media->status_id);
+ Cache::forget('status:thumb:'.$media->status_id);
+
+ } catch (\Exception $e) {
+ $media->processed_at = now();
+ $media->save();
+ Log::info('MediaResizeException: ' . $e->getMessage() . ' | Could not process media id: ' . $media->id);
+ }
+ }
+
+ public function setBaseName($basePath, $thumbnail, $extension)
+ {
+ $png = false;
+ $path = explode('.', $basePath);
+ $name = ($thumbnail == true) ? $path[0].'_thumb' : $path[0];
+ $ext = last($path);
+ $basePath = "{$name}.{$ext}";
+
+ return ['path' => $basePath, 'png' => $png];
+ }
+
+ protected function generateBlurhash($media)
+ {
+ $blurhash = Blurhash::generate($media);
+ if ($blurhash) {
+ $media->blurhash = $blurhash;
+ $media->save();
+ }
+ }
}
diff --git a/app/Util/Site/Config.php b/app/Util/Site/Config.php
index e6406776b..b1fb65035 100644
--- a/app/Util/Site/Config.php
+++ b/app/Util/Site/Config.php
@@ -29,6 +29,7 @@ class Config
return [
'version' => config('pixelfed.version'),
'open_registration' => (bool) config_cache('pixelfed.open_registration'),
+ 'show_legal_notice_link' => (bool) config('instance.has_legal_notice'),
'uploader' => [
'max_photo_size' => (int) config_cache('pixelfed.max_photo_size'),
'max_caption_length' => (int) config_cache('pixelfed.max_caption_length'),
diff --git a/composer.json b/composer.json
index b9a11b462..583079928 100644
--- a/composer.json
+++ b/composer.json
@@ -18,7 +18,7 @@
"buzz/laravel-h-captcha": "^1.0.4",
"doctrine/dbal": "^3.0",
"endroid/qr-code": "^6.0",
- "intervention/image": "^2.4",
+ "intervention/image": "^3.11.2",
"jenssegers/agent": "^2.6",
"laravel-notification-channels/expo": "^2.0.0",
"laravel-notification-channels/webpush": "^10.2",
@@ -31,6 +31,7 @@
"laravel/ui": "^4.2",
"league/flysystem-aws-s3-v3": "^3.0",
"league/iso3166": "^2.1|^4.0",
+ "league/oauth2-client": "^2.8",
"league/uri": "^7.4",
"pbmedia/laravel-ffmpeg": "^8.0",
"phpseclib/phpseclib": "~2.0",
diff --git a/composer.lock b/composer.lock
index 19440079d..cbe80a276 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a011d3030ab0153865ef4cd6a7b615a3",
+ "content-hash": "fc7f320209f9bd3f731d3de6e6f1755f",
"packages": [
{
"name": "aws/aws-crt-php",
@@ -62,16 +62,16 @@
},
{
"name": "aws/aws-sdk-php",
- "version": "3.342.4",
+ "version": "3.343.9",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
- "reference": "65cc842b9998d415b05d635b6146d0728934ff4a"
+ "reference": "6ca5eb1c60b879cf516e5fadefec87afc6219e74"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/65cc842b9998d415b05d635b6146d0728934ff4a",
- "reference": "65cc842b9998d415b05d635b6146d0728934ff4a",
+ "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6ca5eb1c60b879cf516e5fadefec87afc6219e74",
+ "reference": "6ca5eb1c60b879cf516e5fadefec87afc6219e74",
"shasum": ""
},
"require": {
@@ -153,9 +153,9 @@
"support": {
"forum": "https://github.com/aws/aws-sdk-php/discussions",
"issues": "https://github.com/aws/aws-sdk-php/issues",
- "source": "https://github.com/aws/aws-sdk-php/tree/3.342.4"
+ "source": "https://github.com/aws/aws-sdk-php/tree/3.343.9"
},
- "time": "2025-03-11T18:27:07+00:00"
+ "time": "2025-05-12T18:11:31+00:00"
},
{
"name": "bacon/bacon-qr-code",
@@ -793,26 +793,29 @@
},
{
"name": "doctrine/deprecations",
- "version": "1.1.4",
+ "version": "1.1.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/deprecations.git",
- "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9"
+ "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9",
- "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
+ "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
+ "conflict": {
+ "phpunit/phpunit": "<=7.5 || >=13"
+ },
"require-dev": {
- "doctrine/coding-standard": "^9 || ^12",
- "phpstan/phpstan": "1.4.10 || 2.0.3",
+ "doctrine/coding-standard": "^9 || ^12 || ^13",
+ "phpstan/phpstan": "1.4.10 || 2.1.11",
"phpstan/phpstan-phpunit": "^1.0 || ^2",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12",
"psr/log": "^1 || ^2 || ^3"
},
"suggest": {
@@ -832,9 +835,9 @@
"homepage": "https://www.doctrine-project.org/",
"support": {
"issues": "https://github.com/doctrine/deprecations/issues",
- "source": "https://github.com/doctrine/deprecations/tree/1.1.4"
+ "source": "https://github.com/doctrine/deprecations/tree/1.1.5"
},
- "time": "2024-12-07T21:18:45+00:00"
+ "time": "2025-04-07T20:06:18+00:00"
},
{
"name": "doctrine/event-manager",
@@ -1217,16 +1220,16 @@
},
{
"name": "egulias/email-validator",
- "version": "4.0.3",
+ "version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/egulias/EmailValidator.git",
- "reference": "b115554301161fa21467629f1e1391c1936de517"
+ "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b115554301161fa21467629f1e1391c1936de517",
- "reference": "b115554301161fa21467629f1e1391c1936de517",
+ "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa",
+ "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa",
"shasum": ""
},
"require": {
@@ -1272,7 +1275,7 @@
],
"support": {
"issues": "https://github.com/egulias/EmailValidator/issues",
- "source": "https://github.com/egulias/EmailValidator/tree/4.0.3"
+ "source": "https://github.com/egulias/EmailValidator/tree/4.0.4"
},
"funding": [
{
@@ -1280,20 +1283,20 @@
"type": "github"
}
],
- "time": "2024-12-27T00:36:43+00:00"
+ "time": "2025-03-06T22:45:56+00:00"
},
{
"name": "endroid/qr-code",
- "version": "6.0.5",
+ "version": "6.0.8",
"source": {
"type": "git",
"url": "https://github.com/endroid/qr-code.git",
- "reference": "238baddf22500bbfeb2fa1ddc1eb2bd9374a6998"
+ "reference": "8102273afbcd5e3d95f1faaab2c5aa31e3637f61"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/endroid/qr-code/zipball/238baddf22500bbfeb2fa1ddc1eb2bd9374a6998",
- "reference": "238baddf22500bbfeb2fa1ddc1eb2bd9374a6998",
+ "url": "https://api.github.com/repos/endroid/qr-code/zipball/8102273afbcd5e3d95f1faaab2c5aa31e3637f61",
+ "reference": "8102273afbcd5e3d95f1faaab2c5aa31e3637f61",
"shasum": ""
},
"require": {
@@ -1344,7 +1347,7 @@
],
"support": {
"issues": "https://github.com/endroid/qr-code/issues",
- "source": "https://github.com/endroid/qr-code/tree/6.0.5"
+ "source": "https://github.com/endroid/qr-code/tree/6.0.8"
},
"funding": [
{
@@ -1352,7 +1355,7 @@
"type": "github"
}
],
- "time": "2025-03-07T08:15:43+00:00"
+ "time": "2025-05-10T14:28:45+00:00"
},
{
"name": "evenement/evenement",
@@ -1464,16 +1467,16 @@
},
{
"name": "firebase/php-jwt",
- "version": "v6.11.0",
+ "version": "v6.11.1",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
- "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712"
+ "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/firebase/php-jwt/zipball/8f718f4dfc9c5d5f0c994cdfd103921b43592712",
- "reference": "8f718f4dfc9c5d5f0c994cdfd103921b43592712",
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66",
+ "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66",
"shasum": ""
},
"require": {
@@ -1521,9 +1524,9 @@
],
"support": {
"issues": "https://github.com/firebase/php-jwt/issues",
- "source": "https://github.com/firebase/php-jwt/tree/v6.11.0"
+ "source": "https://github.com/firebase/php-jwt/tree/v6.11.1"
},
- "time": "2025-01-23T05:11:06+00:00"
+ "time": "2025-04-09T20:32:01+00:00"
},
{
"name": "fruitcake/php-cors",
@@ -1660,16 +1663,16 @@
},
{
"name": "guzzlehttp/guzzle",
- "version": "7.9.2",
+ "version": "7.9.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
- "reference": "d281ed313b989f213357e3be1a179f02196ac99b"
+ "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b",
- "reference": "d281ed313b989f213357e3be1a179f02196ac99b",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
+ "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
"shasum": ""
},
"require": {
@@ -1766,7 +1769,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
- "source": "https://github.com/guzzle/guzzle/tree/7.9.2"
+ "source": "https://github.com/guzzle/guzzle/tree/7.9.3"
},
"funding": [
{
@@ -1782,20 +1785,20 @@
"type": "tidelift"
}
],
- "time": "2024-07-24T11:22:20+00:00"
+ "time": "2025-03-27T13:37:11+00:00"
},
{
"name": "guzzlehttp/promises",
- "version": "2.0.4",
+ "version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
- "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455"
+ "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
- "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c",
+ "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c",
"shasum": ""
},
"require": {
@@ -1849,7 +1852,7 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
- "source": "https://github.com/guzzle/promises/tree/2.0.4"
+ "source": "https://github.com/guzzle/promises/tree/2.2.0"
},
"funding": [
{
@@ -1865,20 +1868,20 @@
"type": "tidelift"
}
],
- "time": "2024-10-17T10:06:22+00:00"
+ "time": "2025-03-27T13:27:01+00:00"
},
{
"name": "guzzlehttp/psr7",
- "version": "2.7.0",
+ "version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
- "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201"
+ "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
- "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16",
+ "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16",
"shasum": ""
},
"require": {
@@ -1965,7 +1968,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
- "source": "https://github.com/guzzle/psr7/tree/2.7.0"
+ "source": "https://github.com/guzzle/psr7/tree/2.7.1"
},
"funding": [
{
@@ -1981,7 +1984,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-18T11:15:46+00:00"
+ "time": "2025-03-27T12:30:47+00:00"
},
{
"name": "guzzlehttp/uri-template",
@@ -2069,51 +2072,107 @@
],
"time": "2025-02-03T10:55:03+00:00"
},
+ {
+ "name": "intervention/gif",
+ "version": "4.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Intervention/gif.git",
+ "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Intervention/gif/zipball/5999eac6a39aa760fb803bc809e8909ee67b451a",
+ "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.1",
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
+ "slevomat/coding-standard": "~8.0",
+ "squizlabs/php_codesniffer": "^3.8"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Intervention\\Gif\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Oliver Vogel",
+ "email": "oliver@intervention.io",
+ "homepage": "https://intervention.io/"
+ }
+ ],
+ "description": "Native PHP GIF Encoder/Decoder",
+ "homepage": "https://github.com/intervention/gif",
+ "keywords": [
+ "animation",
+ "gd",
+ "gif",
+ "image"
+ ],
+ "support": {
+ "issues": "https://github.com/Intervention/gif/issues",
+ "source": "https://github.com/Intervention/gif/tree/4.2.2"
+ },
+ "funding": [
+ {
+ "url": "https://paypal.me/interventionio",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/Intervention",
+ "type": "github"
+ },
+ {
+ "url": "https://ko-fi.com/interventionphp",
+ "type": "ko_fi"
+ }
+ ],
+ "time": "2025-03-29T07:46:21+00:00"
+ },
{
"name": "intervention/image",
- "version": "2.7.2",
+ "version": "3.11.2",
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
- "reference": "04be355f8d6734c826045d02a1079ad658322dad"
+ "reference": "ebbb711871fb261c064cf4c422f5f3c124fe1842"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad",
- "reference": "04be355f8d6734c826045d02a1079ad658322dad",
+ "url": "https://api.github.com/repos/Intervention/image/zipball/ebbb711871fb261c064cf4c422f5f3c124fe1842",
+ "reference": "ebbb711871fb261c064cf4c422f5f3c124fe1842",
"shasum": ""
},
"require": {
- "ext-fileinfo": "*",
- "guzzlehttp/psr7": "~1.1 || ^2.0",
- "php": ">=5.4.0"
+ "ext-mbstring": "*",
+ "intervention/gif": "^4.2",
+ "php": "^8.1"
},
"require-dev": {
- "mockery/mockery": "~0.9.2",
- "phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15"
+ "mockery/mockery": "^1.6",
+ "phpstan/phpstan": "^2.1",
+ "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0",
+ "slevomat/coding-standard": "~8.0",
+ "squizlabs/php_codesniffer": "^3.8"
},
"suggest": {
- "ext-gd": "to use GD library based image processing.",
- "ext-imagick": "to use Imagick based image processing.",
- "intervention/imagecache": "Caching extension for the Intervention Image library"
+ "ext-exif": "Recommended to be able to read EXIF data properly."
},
"type": "library",
- "extra": {
- "laravel": {
- "aliases": {
- "Image": "Intervention\\Image\\Facades\\Image"
- },
- "providers": [
- "Intervention\\Image\\ImageServiceProvider"
- ]
- },
- "branch-alias": {
- "dev-master": "2.4-dev"
- }
- },
"autoload": {
"psr-4": {
- "Intervention\\Image\\": "src/Intervention/Image"
+ "Intervention\\Image\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -2127,19 +2186,19 @@
"homepage": "https://intervention.io/"
}
],
- "description": "Image handling and manipulation library with support for Laravel integration",
- "homepage": "http://image.intervention.io/",
+ "description": "PHP image manipulation",
+ "homepage": "https://image.intervention.io/",
"keywords": [
"gd",
"image",
"imagick",
- "laravel",
+ "resize",
"thumbnail",
"watermark"
],
"support": {
"issues": "https://github.com/Intervention/image/issues",
- "source": "https://github.com/Intervention/image/tree/2.7.2"
+ "source": "https://github.com/Intervention/image/tree/3.11.2"
},
"funding": [
{
@@ -2149,9 +2208,13 @@
{
"url": "https://github.com/Intervention",
"type": "github"
+ },
+ {
+ "url": "https://ko-fi.com/interventionphp",
+ "type": "ko_fi"
}
],
- "time": "2022-05-21T17:30:32+00:00"
+ "time": "2025-02-27T13:08:55+00:00"
},
{
"name": "jaybizzle/crawler-detect",
@@ -2420,16 +2483,16 @@
},
{
"name": "laravel/framework",
- "version": "v12.1.1",
+ "version": "v12.13.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "9be5738f1ca1530055bb9d6db81f909a7ed34842"
+ "reference": "52b588bcd8efc6d01bc1493d2d67848f8065f269"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/9be5738f1ca1530055bb9d6db81f909a7ed34842",
- "reference": "9be5738f1ca1530055bb9d6db81f909a7ed34842",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/52b588bcd8efc6d01bc1493d2d67848f8065f269",
+ "reference": "52b588bcd8efc6d01bc1493d2d67848f8065f269",
"shasum": ""
},
"require": {
@@ -2450,7 +2513,7 @@
"guzzlehttp/uri-template": "^1.0",
"laravel/prompts": "^0.3.0",
"laravel/serializable-closure": "^1.3|^2.0",
- "league/commonmark": "^2.6",
+ "league/commonmark": "^2.7",
"league/flysystem": "^3.25.1",
"league/flysystem-local": "^3.25.1",
"league/uri": "^7.5.1",
@@ -2538,11 +2601,11 @@
"league/flysystem-sftp-v3": "^3.25.1",
"mockery/mockery": "^1.6.10",
"orchestra/testbench-core": "^10.0.0",
- "pda/pheanstalk": "^5.0.6",
+ "pda/pheanstalk": "^5.0.6|^7.0.0",
"php-http/discovery": "^1.15",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1",
- "predis/predis": "^2.3",
+ "predis/predis": "^2.3|^3.0",
"resend/resend-php": "^0.10.0",
"symfony/cache": "^7.2.0",
"symfony/http-client": "^7.2.0",
@@ -2574,7 +2637,7 @@
"pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).",
"php-http/discovery": "Required to use PSR-7 bridging features (^1.15).",
"phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).",
- "predis/predis": "Required to use the predis connector (^2.3).",
+ "predis/predis": "Required to use the predis connector (^2.3|^3.0).",
"psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).",
"resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).",
@@ -2631,7 +2694,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2025-03-05T15:31:19+00:00"
+ "time": "2025-05-07T17:29:01+00:00"
},
{
"name": "laravel/helpers",
@@ -2692,16 +2755,16 @@
},
{
"name": "laravel/horizon",
- "version": "v5.31.0",
+ "version": "v5.31.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/horizon.git",
- "reference": "a21e7d64784b24eaf3bf873f82affbf67707a72a"
+ "reference": "e6068c65be6c02a01e34531abf3143fab91f0de0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/horizon/zipball/a21e7d64784b24eaf3bf873f82affbf67707a72a",
- "reference": "a21e7d64784b24eaf3bf873f82affbf67707a72a",
+ "url": "https://api.github.com/repos/laravel/horizon/zipball/e6068c65be6c02a01e34531abf3143fab91f0de0",
+ "reference": "e6068c65be6c02a01e34531abf3143fab91f0de0",
"shasum": ""
},
"require": {
@@ -2766,9 +2829,9 @@
],
"support": {
"issues": "https://github.com/laravel/horizon/issues",
- "source": "https://github.com/laravel/horizon/tree/v5.31.0"
+ "source": "https://github.com/laravel/horizon/tree/v5.31.2"
},
- "time": "2025-03-04T14:56:42+00:00"
+ "time": "2025-04-18T12:57:39+00:00"
},
{
"name": "laravel/passport",
@@ -2907,16 +2970,16 @@
},
{
"name": "laravel/pulse",
- "version": "v1.4.0",
+ "version": "v1.4.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/pulse.git",
- "reference": "62099ede70df2272544f0c0657eda0c73d25a6b2"
+ "reference": "b3cf86e88fa78ea8e6aeb86a7d9ea25ba2c1d31f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pulse/zipball/62099ede70df2272544f0c0657eda0c73d25a6b2",
- "reference": "62099ede70df2272544f0c0657eda0c73d25a6b2",
+ "url": "https://api.github.com/repos/laravel/pulse/zipball/b3cf86e88fa78ea8e6aeb86a7d9ea25ba2c1d31f",
+ "reference": "b3cf86e88fa78ea8e6aeb86a7d9ea25ba2c1d31f",
"shasum": ""
},
"require": {
@@ -2949,7 +3012,7 @@
"orchestra/testbench": "^8.23.1|^9.0|^10.0",
"pestphp/pest": "^2.0",
"pestphp/pest-plugin-laravel": "^2.2",
- "phpstan/phpstan": "^1.11",
+ "phpstan/phpstan": "^1.12.21",
"predis/predis": "^1.0|^2.0"
},
"type": "library",
@@ -2990,20 +3053,20 @@
"issues": "https://github.com/laravel/pulse/issues",
"source": "https://github.com/laravel/pulse"
},
- "time": "2025-02-11T13:36:44+00:00"
+ "time": "2025-03-30T16:25:37+00:00"
},
{
"name": "laravel/serializable-closure",
- "version": "v2.0.3",
+ "version": "v2.0.4",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
- "reference": "f379c13663245f7aa4512a7869f62eb14095f23f"
+ "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f379c13663245f7aa4512a7869f62eb14095f23f",
- "reference": "f379c13663245f7aa4512a7869f62eb14095f23f",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841",
+ "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841",
"shasum": ""
},
"require": {
@@ -3051,7 +3114,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
- "time": "2025-02-11T15:03:05+00:00"
+ "time": "2025-03-19T13:51:03+00:00"
},
{
"name": "laravel/tinker",
@@ -3321,16 +3384,16 @@
},
{
"name": "league/commonmark",
- "version": "2.6.1",
+ "version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
- "reference": "d990688c91cedfb69753ffc2512727ec646df2ad"
+ "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d990688c91cedfb69753ffc2512727ec646df2ad",
- "reference": "d990688c91cedfb69753ffc2512727ec646df2ad",
+ "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
+ "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
"shasum": ""
},
"require": {
@@ -3367,7 +3430,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "2.7-dev"
+ "dev-main": "2.8-dev"
}
},
"autoload": {
@@ -3424,7 +3487,7 @@
"type": "tidelift"
}
],
- "time": "2024-12-29T14:10:59+00:00"
+ "time": "2025-05-05T12:20:28+00:00"
},
{
"name": "league/config",
@@ -3510,20 +3573,20 @@
},
{
"name": "league/event",
- "version": "2.2.0",
+ "version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/event.git",
- "reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119"
+ "reference": "062ebb450efbe9a09bc2478e89b7c933875b0935"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/event/zipball/d2cc124cf9a3fab2bb4ff963307f60361ce4d119",
- "reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119",
+ "url": "https://api.github.com/repos/thephpleague/event/zipball/062ebb450efbe9a09bc2478e89b7c933875b0935",
+ "reference": "062ebb450efbe9a09bc2478e89b7c933875b0935",
"shasum": ""
},
"require": {
- "php": ">=5.4.0"
+ "php": ">=7.1.0"
},
"require-dev": {
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
@@ -3558,9 +3621,9 @@
],
"support": {
"issues": "https://github.com/thephpleague/event/issues",
- "source": "https://github.com/thephpleague/event/tree/master"
+ "source": "https://github.com/thephpleague/event/tree/2.3.0"
},
- "time": "2018-11-26T11:52:41+00:00"
+ "time": "2025-03-14T19:51:10+00:00"
},
{
"name": "league/flysystem",
@@ -3872,6 +3935,71 @@
],
"time": "2024-09-21T08:32:55+00:00"
},
+ {
+ "name": "league/oauth2-client",
+ "version": "2.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/oauth2-client.git",
+ "reference": "9df2924ca644736c835fc60466a3a60390d334f9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/9df2924ca644736c835fc60466a3a60390d334f9",
+ "reference": "9df2924ca644736c835fc60466a3a60390d334f9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5",
+ "php": "^7.1 || >=8.0.0 <8.5.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.3.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11",
+ "squizlabs/php_codesniffer": "^3.11"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\OAuth2\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Alex Bilbie",
+ "email": "hello@alexbilbie.com",
+ "homepage": "http://www.alexbilbie.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Woody Gilk",
+ "homepage": "https://github.com/shadowhand",
+ "role": "Contributor"
+ }
+ ],
+ "description": "OAuth 2.0 Client Library",
+ "keywords": [
+ "Authentication",
+ "SSO",
+ "authorization",
+ "identity",
+ "idp",
+ "oauth",
+ "oauth2",
+ "single sign on"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/oauth2-client/issues",
+ "source": "https://github.com/thephpleague/oauth2-client/tree/2.8.1"
+ },
+ "time": "2025-02-26T04:37:30+00:00"
+ },
{
"name": "league/oauth2-server",
"version": "8.5.5",
@@ -4136,16 +4264,16 @@
},
{
"name": "livewire/livewire",
- "version": "v3.6.1",
+ "version": "v3.6.3",
"source": {
"type": "git",
"url": "https://github.com/livewire/livewire.git",
- "reference": "0df0a762698176d714e42e2dfed92b6b9e24b8e4"
+ "reference": "56aa1bb63a46e06181c56fa64717a7287e19115e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/livewire/livewire/zipball/0df0a762698176d714e42e2dfed92b6b9e24b8e4",
- "reference": "0df0a762698176d714e42e2dfed92b6b9e24b8e4",
+ "url": "https://api.github.com/repos/livewire/livewire/zipball/56aa1bb63a46e06181c56fa64717a7287e19115e",
+ "reference": "56aa1bb63a46e06181c56fa64717a7287e19115e",
"shasum": ""
},
"require": {
@@ -4200,7 +4328,7 @@
"description": "A front-end framework for Laravel.",
"support": {
"issues": "https://github.com/livewire/livewire/issues",
- "source": "https://github.com/livewire/livewire/tree/v3.6.1"
+ "source": "https://github.com/livewire/livewire/tree/v3.6.3"
},
"funding": [
{
@@ -4208,7 +4336,7 @@
"type": "github"
}
],
- "time": "2025-03-04T21:48:52+00:00"
+ "time": "2025-04-12T22:26:52+00:00"
},
{
"name": "minishlink/web-push",
@@ -4339,16 +4467,16 @@
},
{
"name": "monolog/monolog",
- "version": "3.8.1",
+ "version": "3.9.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4"
+ "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/aef6ee73a77a66e404dd6540934a9ef1b3c855b4",
- "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6",
+ "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6",
"shasum": ""
},
"require": {
@@ -4426,7 +4554,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
- "source": "https://github.com/Seldaek/monolog/tree/3.8.1"
+ "source": "https://github.com/Seldaek/monolog/tree/3.9.0"
},
"funding": [
{
@@ -4438,7 +4566,7 @@
"type": "tidelift"
}
],
- "time": "2024-12-05T17:15:07+00:00"
+ "time": "2025-03-24T10:02:05+00:00"
},
{
"name": "mtdowling/jmespath.php",
@@ -4508,16 +4636,16 @@
},
{
"name": "nesbot/carbon",
- "version": "3.8.6",
+ "version": "3.9.1",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
- "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd"
+ "reference": "ced71f79398ece168e24f7f7710462f462310d4d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ff2f20cf83bd4d503720632ce8a426dc747bf7fd",
- "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd",
+ "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d",
+ "reference": "ced71f79398ece168e24f7f7710462f462310d4d",
"shasum": ""
},
"require": {
@@ -4610,7 +4738,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-20T17:33:38+00:00"
+ "time": "2025-05-01T19:51:51+00:00"
},
{
"name": "nette/schema",
@@ -4676,16 +4804,16 @@
},
{
"name": "nette/utils",
- "version": "v4.0.5",
+ "version": "v4.0.6",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
- "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96"
+ "reference": "ce708655043c7050eb050df361c5e313cf708309"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
- "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
+ "url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309",
+ "reference": "ce708655043c7050eb050df361c5e313cf708309",
"shasum": ""
},
"require": {
@@ -4756,9 +4884,9 @@
],
"support": {
"issues": "https://github.com/nette/utils/issues",
- "source": "https://github.com/nette/utils/tree/v4.0.5"
+ "source": "https://github.com/nette/utils/tree/v4.0.6"
},
- "time": "2024-08-07T15:39:19+00:00"
+ "time": "2025-03-30T21:06:30+00:00"
},
{
"name": "nikic/php-parser",
@@ -4820,31 +4948,31 @@
},
{
"name": "nunomaduro/termwind",
- "version": "v2.3.0",
+ "version": "v2.3.1",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/termwind.git",
- "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda"
+ "reference": "dfa08f390e509967a15c22493dc0bac5733d9123"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda",
- "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda",
+ "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123",
+ "reference": "dfa08f390e509967a15c22493dc0bac5733d9123",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "^8.2",
- "symfony/console": "^7.1.8"
+ "symfony/console": "^7.2.6"
},
"require-dev": {
- "illuminate/console": "^11.33.2",
- "laravel/pint": "^1.18.2",
+ "illuminate/console": "^11.44.7",
+ "laravel/pint": "^1.22.0",
"mockery/mockery": "^1.6.12",
- "pestphp/pest": "^2.36.0",
- "phpstan/phpstan": "^1.12.11",
- "phpstan/phpstan-strict-rules": "^1.6.1",
- "symfony/var-dumper": "^7.1.8",
+ "pestphp/pest": "^2.36.0 || ^3.8.2",
+ "phpstan/phpstan": "^1.12.25",
+ "phpstan/phpstan-strict-rules": "^1.6.2",
+ "symfony/var-dumper": "^7.2.6",
"thecodingmachine/phpstan-strict-rules": "^1.0.0"
},
"type": "library",
@@ -4887,7 +5015,7 @@
],
"support": {
"issues": "https://github.com/nunomaduro/termwind/issues",
- "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0"
+ "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1"
},
"funding": [
{
@@ -4903,7 +5031,7 @@
"type": "github"
}
],
- "time": "2024-11-21T10:39:51+00:00"
+ "time": "2025-05-08T08:14:37+00:00"
},
{
"name": "nyholm/psr7",
@@ -5193,16 +5321,16 @@
},
{
"name": "pbmedia/laravel-ffmpeg",
- "version": "8.7.0",
+ "version": "8.7.1",
"source": {
"type": "git",
"url": "https://github.com/protonemedia/laravel-ffmpeg.git",
- "reference": "01249a226bce0172a7e87a43fc5448b975a56282"
+ "reference": "596804eee95b97bca146653770e7622159976bb1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/protonemedia/laravel-ffmpeg/zipball/01249a226bce0172a7e87a43fc5448b975a56282",
- "reference": "01249a226bce0172a7e87a43fc5448b975a56282",
+ "url": "https://api.github.com/repos/protonemedia/laravel-ffmpeg/zipball/596804eee95b97bca146653770e7622159976bb1",
+ "reference": "596804eee95b97bca146653770e7622159976bb1",
"shasum": ""
},
"require": {
@@ -5212,6 +5340,7 @@
"ramsey/collection": "^2.0"
},
"require-dev": {
+ "laravel/pint": "^1.21",
"league/flysystem-memory": "^3.10",
"mockery/mockery": "^1.4.4",
"nesbot/carbon": "^2.66|^3.0",
@@ -5259,7 +5388,7 @@
],
"support": {
"issues": "https://github.com/protonemedia/laravel-ffmpeg/issues",
- "source": "https://github.com/protonemedia/laravel-ffmpeg/tree/8.7.0"
+ "source": "https://github.com/protonemedia/laravel-ffmpeg/tree/8.7.1"
},
"funding": [
{
@@ -5267,20 +5396,20 @@
"type": "github"
}
],
- "time": "2025-02-16T22:06:08+00:00"
+ "time": "2025-04-01T21:11:35+00:00"
},
{
"name": "php-ffmpeg/php-ffmpeg",
- "version": "v1.3.1",
+ "version": "v1.3.2",
"source": {
"type": "git",
"url": "https://github.com/PHP-FFMpeg/PHP-FFMpeg.git",
- "reference": "0fbbc4c6a6336155679adc800616001ae3328c7a"
+ "reference": "8e74bdc07ad200da7a6cfb21ec2652875e4368e0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHP-FFMpeg/PHP-FFMpeg/zipball/0fbbc4c6a6336155679adc800616001ae3328c7a",
- "reference": "0fbbc4c6a6336155679adc800616001ae3328c7a",
+ "url": "https://api.github.com/repos/PHP-FFMpeg/PHP-FFMpeg/zipball/8e74bdc07ad200da7a6cfb21ec2652875e4368e0",
+ "reference": "8e74bdc07ad200da7a6cfb21ec2652875e4368e0",
"shasum": ""
},
"require": {
@@ -5354,9 +5483,9 @@
],
"support": {
"issues": "https://github.com/PHP-FFMpeg/PHP-FFMpeg/issues",
- "source": "https://github.com/PHP-FFMpeg/PHP-FFMpeg/tree/v1.3.1"
+ "source": "https://github.com/PHP-FFMpeg/PHP-FFMpeg/tree/v1.3.2"
},
- "time": "2025-01-10T20:23:57+00:00"
+ "time": "2025-04-01T20:36:46+00:00"
},
{
"name": "phpoption/phpoption",
@@ -5723,16 +5852,16 @@
},
{
"name": "predis/predis",
- "version": "v2.3.0",
+ "version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/predis/predis.git",
- "reference": "bac46bfdb78cd6e9c7926c697012aae740cb9ec9"
+ "reference": "f49e13ee3a2a825631562aa0223ac922ec5d058b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/predis/predis/zipball/bac46bfdb78cd6e9c7926c697012aae740cb9ec9",
- "reference": "bac46bfdb78cd6e9c7926c697012aae740cb9ec9",
+ "url": "https://api.github.com/repos/predis/predis/zipball/f49e13ee3a2a825631562aa0223ac922ec5d058b",
+ "reference": "f49e13ee3a2a825631562aa0223ac922ec5d058b",
"shasum": ""
},
"require": {
@@ -5741,6 +5870,7 @@
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.3",
"phpstan/phpstan": "^1.9",
+ "phpunit/phpcov": "^6.0 || ^8.0",
"phpunit/phpunit": "^8.0 || ^9.4"
},
"suggest": {
@@ -5763,7 +5893,7 @@
"role": "Maintainer"
}
],
- "description": "A flexible and feature-complete Redis client for PHP.",
+ "description": "A flexible and feature-complete Redis/Valkey client for PHP.",
"homepage": "http://github.com/predis/predis",
"keywords": [
"nosql",
@@ -5772,7 +5902,7 @@
],
"support": {
"issues": "https://github.com/predis/predis/issues",
- "source": "https://github.com/predis/predis/tree/v2.3.0"
+ "source": "https://github.com/predis/predis/tree/v2.4.0"
},
"funding": [
{
@@ -5780,7 +5910,7 @@
"type": "github"
}
],
- "time": "2024-11-21T20:00:02+00:00"
+ "time": "2025-04-30T15:16:02+00:00"
},
{
"name": "psr/cache",
@@ -6245,16 +6375,16 @@
},
{
"name": "psy/psysh",
- "version": "v0.12.7",
+ "version": "v0.12.8",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
- "reference": "d73fa3c74918ef4522bb8a3bf9cab39161c4b57c"
+ "reference": "85057ceedee50c49d4f6ecaff73ee96adb3b3625"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/bobthecow/psysh/zipball/d73fa3c74918ef4522bb8a3bf9cab39161c4b57c",
- "reference": "d73fa3c74918ef4522bb8a3bf9cab39161c4b57c",
+ "url": "https://api.github.com/repos/bobthecow/psysh/zipball/85057ceedee50c49d4f6ecaff73ee96adb3b3625",
+ "reference": "85057ceedee50c49d4f6ecaff73ee96adb3b3625",
"shasum": ""
},
"require": {
@@ -6318,9 +6448,9 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
- "source": "https://github.com/bobthecow/psysh/tree/v0.12.7"
+ "source": "https://github.com/bobthecow/psysh/tree/v0.12.8"
},
- "time": "2024-12-10T01:58:33+00:00"
+ "time": "2025-03-16T03:05:19+00:00"
},
{
"name": "pusher/pusher-php-server",
@@ -6429,16 +6559,16 @@
},
{
"name": "ramsey/collection",
- "version": "2.1.0",
+ "version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/ramsey/collection.git",
- "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109"
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/collection/zipball/3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109",
- "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
"shasum": ""
},
"require": {
@@ -6499,9 +6629,9 @@
],
"support": {
"issues": "https://github.com/ramsey/collection/issues",
- "source": "https://github.com/ramsey/collection/tree/2.1.0"
+ "source": "https://github.com/ramsey/collection/tree/2.1.1"
},
- "time": "2025-03-02T04:48:29+00:00"
+ "time": "2025-03-22T05:38:12+00:00"
},
{
"name": "ramsey/uuid",
@@ -6772,16 +6902,16 @@
},
{
"name": "spatie/laravel-backup",
- "version": "9.2.9",
+ "version": "9.3.2",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-backup.git",
- "reference": "997c781a38bc701ab7623954b2e0438680caa0bf"
+ "reference": "c5ced5777fa1c6e89a11afb6520e37e2b98d9a47"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-backup/zipball/997c781a38bc701ab7623954b2e0438680caa0bf",
- "reference": "997c781a38bc701ab7623954b2e0438680caa0bf",
+ "url": "https://api.github.com/repos/spatie/laravel-backup/zipball/c5ced5777fa1c6e89a11afb6520e37e2b98d9a47",
+ "reference": "c5ced5777fa1c6e89a11afb6520e37e2b98d9a47",
"shasum": ""
},
"require": {
@@ -6794,7 +6924,7 @@
"illuminate/support": "^10.10.0|^11.0|^12.0",
"league/flysystem": "^3.0",
"php": "^8.2",
- "spatie/db-dumper": "^3.7",
+ "spatie/db-dumper": "^3.8",
"spatie/laravel-package-tools": "^1.6.2",
"spatie/laravel-signal-aware-command": "^1.2|^2.0",
"spatie/temporary-directory": "^2.0",
@@ -6856,7 +6986,7 @@
],
"support": {
"issues": "https://github.com/spatie/laravel-backup/issues",
- "source": "https://github.com/spatie/laravel-backup/tree/9.2.9"
+ "source": "https://github.com/spatie/laravel-backup/tree/9.3.2"
},
"funding": [
{
@@ -6868,7 +6998,7 @@
"type": "other"
}
],
- "time": "2025-03-03T12:10:03+00:00"
+ "time": "2025-04-25T13:42:20+00:00"
},
{
"name": "spatie/laravel-image-optimizer",
@@ -6940,16 +7070,16 @@
},
{
"name": "spatie/laravel-package-tools",
- "version": "1.19.0",
+ "version": "1.92.4",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-package-tools.git",
- "reference": "1c9c30ac6a6576b8d15c6c37b6cf23d748df2faa"
+ "reference": "d20b1969f836d210459b78683d85c9cd5c5f508c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/1c9c30ac6a6576b8d15c6c37b6cf23d748df2faa",
- "reference": "1c9c30ac6a6576b8d15c6c37b6cf23d748df2faa",
+ "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/d20b1969f836d210459b78683d85c9cd5c5f508c",
+ "reference": "d20b1969f836d210459b78683d85c9cd5c5f508c",
"shasum": ""
},
"require": {
@@ -6960,6 +7090,7 @@
"mockery/mockery": "^1.5",
"orchestra/testbench": "^7.7|^8.0|^9.0|^10.0",
"pestphp/pest": "^1.23|^2.1|^3.1",
+ "phpunit/php-code-coverage": "^9.0|^10.0|^11.0",
"phpunit/phpunit": "^9.5.24|^10.5|^11.5",
"spatie/pest-plugin-test-time": "^1.1|^2.2"
},
@@ -6988,7 +7119,7 @@
],
"support": {
"issues": "https://github.com/spatie/laravel-package-tools/issues",
- "source": "https://github.com/spatie/laravel-package-tools/tree/1.19.0"
+ "source": "https://github.com/spatie/laravel-package-tools/tree/1.92.4"
},
"funding": [
{
@@ -6996,7 +7127,7 @@
"type": "github"
}
],
- "time": "2025-02-06T14:58:20+00:00"
+ "time": "2025-04-11T15:27:14+00:00"
},
{
"name": "spatie/laravel-signal-aware-command",
@@ -7201,20 +7332,20 @@
},
{
"name": "spomky-labs/pki-framework",
- "version": "1.2.2",
+ "version": "1.2.3",
"source": {
"type": "git",
"url": "https://github.com/Spomky-Labs/pki-framework.git",
- "reference": "5ac374c3e295c8b917208ff41b4d30f76668478c"
+ "reference": "5ff1dcc21e961b60149a80e77f744fc047800b31"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/5ac374c3e295c8b917208ff41b4d30f76668478c",
- "reference": "5ac374c3e295c8b917208ff41b4d30f76668478c",
+ "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/5ff1dcc21e961b60149a80e77f744fc047800b31",
+ "reference": "5ff1dcc21e961b60149a80e77f744fc047800b31",
"shasum": ""
},
"require": {
- "brick/math": "^0.10|^0.11|^0.12",
+ "brick/math": "^0.10|^0.11|^0.12|^0.13",
"ext-mbstring": "*",
"php": ">=8.1"
},
@@ -7229,7 +7360,7 @@
"phpstan/phpstan-deprecation-rules": "^1.0|^2.0",
"phpstan/phpstan-phpunit": "^1.1|^2.0",
"phpstan/phpstan-strict-rules": "^1.3|^2.0",
- "phpunit/phpunit": "^10.1|^11.0",
+ "phpunit/phpunit": "^10.1|^11.0|^12.0",
"rector/rector": "^1.0|^2.0",
"roave/security-advisories": "dev-latest",
"symfony/string": "^6.4|^7.0",
@@ -7294,7 +7425,7 @@
],
"support": {
"issues": "https://github.com/Spomky-Labs/pki-framework/issues",
- "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.2.2"
+ "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.2.3"
},
"funding": [
{
@@ -7306,7 +7437,7 @@
"type": "patreon"
}
],
- "time": "2025-01-03T09:35:48+00:00"
+ "time": "2025-04-25T15:57:13+00:00"
},
{
"name": "stevebauman/purify",
@@ -7376,16 +7507,16 @@
},
{
"name": "symfony/cache",
- "version": "v7.2.4",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache.git",
- "reference": "d33cd9e14326e14a4145c21e600602eaf17cc9e7"
+ "reference": "8b49dde3f5a5e9867595a3a269977f78418d75ee"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/cache/zipball/d33cd9e14326e14a4145c21e600602eaf17cc9e7",
- "reference": "d33cd9e14326e14a4145c21e600602eaf17cc9e7",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/8b49dde3f5a5e9867595a3a269977f78418d75ee",
+ "reference": "8b49dde3f5a5e9867595a3a269977f78418d75ee",
"shasum": ""
},
"require": {
@@ -7454,7 +7585,7 @@
"psr6"
],
"support": {
- "source": "https://github.com/symfony/cache/tree/v7.2.4"
+ "source": "https://github.com/symfony/cache/tree/v7.2.6"
},
"funding": [
{
@@ -7470,7 +7601,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-26T09:57:54+00:00"
+ "time": "2025-04-08T09:06:23+00:00"
},
{
"name": "symfony/cache-contracts",
@@ -7624,16 +7755,16 @@
},
{
"name": "symfony/console",
- "version": "v7.2.1",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3"
+ "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
- "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
+ "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218",
+ "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218",
"shasum": ""
},
"require": {
@@ -7697,7 +7828,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.2.1"
+ "source": "https://github.com/symfony/console/tree/v7.2.6"
},
"funding": [
{
@@ -7713,7 +7844,7 @@
"type": "tidelift"
}
],
- "time": "2024-12-11T03:49:26+00:00"
+ "time": "2025-04-07T19:09:28+00:00"
},
{
"name": "symfony/css-selector",
@@ -7849,16 +7980,16 @@
},
{
"name": "symfony/error-handler",
- "version": "v7.2.4",
+ "version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "aabf79938aa795350c07ce6464dd1985607d95d5"
+ "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/aabf79938aa795350c07ce6464dd1985607d95d5",
- "reference": "aabf79938aa795350c07ce6464dd1985607d95d5",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b",
+ "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b",
"shasum": ""
},
"require": {
@@ -7904,7 +8035,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/error-handler/tree/v7.2.4"
+ "source": "https://github.com/symfony/error-handler/tree/v7.2.5"
},
"funding": [
{
@@ -7920,7 +8051,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-02T20:27:07+00:00"
+ "time": "2025-03-03T07:12:39+00:00"
},
{
"name": "symfony/event-dispatcher",
@@ -8315,16 +8446,16 @@
},
{
"name": "symfony/http-foundation",
- "version": "v7.2.3",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "ee1b504b8926198be89d05e5b6fc4c3810c090f0"
+ "reference": "6023ec7607254c87c5e69fb3558255aca440d72b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ee1b504b8926198be89d05e5b6fc4c3810c090f0",
- "reference": "ee1b504b8926198be89d05e5b6fc4c3810c090f0",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6023ec7607254c87c5e69fb3558255aca440d72b",
+ "reference": "6023ec7607254c87c5e69fb3558255aca440d72b",
"shasum": ""
},
"require": {
@@ -8373,7 +8504,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v7.2.3"
+ "source": "https://github.com/symfony/http-foundation/tree/v7.2.6"
},
"funding": [
{
@@ -8389,20 +8520,20 @@
"type": "tidelift"
}
],
- "time": "2025-01-17T10:56:55+00:00"
+ "time": "2025-04-09T08:14:01+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v7.2.4",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "9f1103734c5789798fefb90e91de4586039003ed"
+ "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/9f1103734c5789798fefb90e91de4586039003ed",
- "reference": "9f1103734c5789798fefb90e91de4586039003ed",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f9dec01e6094a063e738f8945ef69c0cfcf792ec",
+ "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec",
"shasum": ""
},
"require": {
@@ -8487,7 +8618,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-kernel/tree/v7.2.4"
+ "source": "https://github.com/symfony/http-kernel/tree/v7.2.6"
},
"funding": [
{
@@ -8503,20 +8634,20 @@
"type": "tidelift"
}
],
- "time": "2025-02-26T11:01:22+00:00"
+ "time": "2025-05-02T09:04:03+00:00"
},
{
"name": "symfony/mailer",
- "version": "v7.2.3",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3"
+ "reference": "998692469d6e698c6eadc7ef37a6530a9eabb356"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/f3871b182c44997cf039f3b462af4a48fb85f9d3",
- "reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/998692469d6e698c6eadc7ef37a6530a9eabb356",
+ "reference": "998692469d6e698c6eadc7ef37a6530a9eabb356",
"shasum": ""
},
"require": {
@@ -8567,7 +8698,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v7.2.3"
+ "source": "https://github.com/symfony/mailer/tree/v7.2.6"
},
"funding": [
{
@@ -8583,7 +8714,7 @@
"type": "tidelift"
}
],
- "time": "2025-01-27T11:08:17+00:00"
+ "time": "2025-04-04T09:50:51+00:00"
},
{
"name": "symfony/mailgun-mailer",
@@ -8656,16 +8787,16 @@
},
{
"name": "symfony/mime",
- "version": "v7.2.4",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "87ca22046b78c3feaff04b337f33b38510fd686b"
+ "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b",
- "reference": "87ca22046b78c3feaff04b337f33b38510fd686b",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/706e65c72d402539a072d0d6ad105fff6c161ef1",
+ "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1",
"shasum": ""
},
"require": {
@@ -8720,7 +8851,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v7.2.4"
+ "source": "https://github.com/symfony/mime/tree/v7.2.6"
},
"funding": [
{
@@ -8736,11 +8867,11 @@
"type": "tidelift"
}
],
- "time": "2025-02-19T08:51:20+00:00"
+ "time": "2025-04-27T13:34:41+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.31.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@@ -8799,7 +8930,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
},
"funding": [
{
@@ -8819,7 +8950,7 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.31.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
@@ -8877,7 +9008,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0"
},
"funding": [
{
@@ -8897,16 +9028,16 @@
},
{
"name": "symfony/polyfill-intl-idn",
- "version": "v1.31.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
- "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773"
+ "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773",
- "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
+ "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
"shasum": ""
},
"require": {
@@ -8960,7 +9091,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0"
},
"funding": [
{
@@ -8976,11 +9107,11 @@
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2024-09-10T14:38:51+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.31.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@@ -9041,7 +9172,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
},
"funding": [
{
@@ -9061,19 +9192,20 @@
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.31.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
- "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
"shasum": ""
},
"require": {
+ "ext-iconv": "*",
"php": ">=7.2"
},
"provide": {
@@ -9121,7 +9253,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
},
"funding": [
{
@@ -9137,20 +9269,20 @@
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2024-12-23T08:48:59+00:00"
},
{
"name": "symfony/polyfill-php80",
- "version": "v1.31.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
+ "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
- "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+ "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
"shasum": ""
},
"require": {
@@ -9201,7 +9333,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0"
},
"funding": [
{
@@ -9217,11 +9349,11 @@
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2025-01-02T08:10:11+00:00"
},
{
"name": "symfony/polyfill-php83",
- "version": "v1.31.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php83.git",
@@ -9277,7 +9409,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0"
},
"funding": [
{
@@ -9297,7 +9429,7 @@
},
{
"name": "symfony/polyfill-uuid",
- "version": "v1.31.0",
+ "version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-uuid.git",
@@ -9356,7 +9488,7 @@
"uuid"
],
"support": {
- "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0"
},
"funding": [
{
@@ -9376,16 +9508,16 @@
},
{
"name": "symfony/process",
- "version": "v7.2.4",
+ "version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf"
+ "reference": "87b7c93e57df9d8e39a093d32587702380ff045d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
- "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
+ "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d",
+ "reference": "87b7c93e57df9d8e39a093d32587702380ff045d",
"shasum": ""
},
"require": {
@@ -9417,7 +9549,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.2.4"
+ "source": "https://github.com/symfony/process/tree/v7.2.5"
},
"funding": [
{
@@ -9433,7 +9565,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-05T08:33:46+00:00"
+ "time": "2025-03-13T12:21:46+00:00"
},
{
"name": "symfony/psr-http-message-bridge",
@@ -9684,16 +9816,16 @@
},
{
"name": "symfony/string",
- "version": "v7.2.0",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82"
+ "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82",
- "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82",
+ "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931",
+ "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931",
"shasum": ""
},
"require": {
@@ -9751,7 +9883,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.2.0"
+ "source": "https://github.com/symfony/string/tree/v7.2.6"
},
"funding": [
{
@@ -9767,20 +9899,20 @@
"type": "tidelift"
}
],
- "time": "2024-11-13T13:31:26+00:00"
+ "time": "2025-04-20T20:18:16+00:00"
},
{
"name": "symfony/translation",
- "version": "v7.2.4",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "283856e6981286cc0d800b53bd5703e8e363f05a"
+ "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a",
- "reference": "283856e6981286cc0d800b53bd5703e8e363f05a",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6",
+ "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6",
"shasum": ""
},
"require": {
@@ -9846,7 +9978,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v7.2.4"
+ "source": "https://github.com/symfony/translation/tree/v7.2.6"
},
"funding": [
{
@@ -9862,7 +9994,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-13T10:27:23+00:00"
+ "time": "2025-04-07T19:09:28+00:00"
},
{
"name": "symfony/translation-contracts",
@@ -10018,16 +10150,16 @@
},
{
"name": "symfony/var-dumper",
- "version": "v7.2.3",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "82b478c69745d8878eb60f9a049a4d584996f73a"
+ "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a",
- "reference": "82b478c69745d8878eb60f9a049a4d584996f73a",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9c46038cd4ed68952166cf7001b54eb539184ccb",
+ "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb",
"shasum": ""
},
"require": {
@@ -10081,7 +10213,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v7.2.3"
+ "source": "https://github.com/symfony/var-dumper/tree/v7.2.6"
},
"funding": [
{
@@ -10097,20 +10229,20 @@
"type": "tidelift"
}
],
- "time": "2025-01-17T11:39:41+00:00"
+ "time": "2025-04-09T08:14:01+00:00"
},
{
"name": "symfony/var-exporter",
- "version": "v7.2.4",
+ "version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
- "reference": "4ede73aa7a73d81506002d2caadbbdad1ef5b69a"
+ "reference": "422b8de94c738830a1e071f59ad14d67417d7007"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-exporter/zipball/4ede73aa7a73d81506002d2caadbbdad1ef5b69a",
- "reference": "4ede73aa7a73d81506002d2caadbbdad1ef5b69a",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/422b8de94c738830a1e071f59ad14d67417d7007",
+ "reference": "422b8de94c738830a1e071f59ad14d67417d7007",
"shasum": ""
},
"require": {
@@ -10157,7 +10289,7 @@
"serialize"
],
"support": {
- "source": "https://github.com/symfony/var-exporter/tree/v7.2.4"
+ "source": "https://github.com/symfony/var-exporter/tree/v7.2.6"
},
"funding": [
{
@@ -10173,7 +10305,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-13T10:27:23+00:00"
+ "time": "2025-05-02T08:36:00+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@@ -10232,16 +10364,16 @@
},
{
"name": "vlucas/phpdotenv",
- "version": "v5.6.1",
+ "version": "v5.6.2",
"source": {
"type": "git",
"url": "https://github.com/vlucas/phpdotenv.git",
- "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2"
+ "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2",
- "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2",
+ "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
+ "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
"shasum": ""
},
"require": {
@@ -10300,7 +10432,7 @@
],
"support": {
"issues": "https://github.com/vlucas/phpdotenv/issues",
- "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1"
+ "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2"
},
"funding": [
{
@@ -10312,7 +10444,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-20T21:52:34+00:00"
+ "time": "2025-04-30T23:37:27+00:00"
},
{
"name": "voku/portable-ascii",
@@ -10390,16 +10522,16 @@
},
{
"name": "web-token/jwt-library",
- "version": "3.4.7",
+ "version": "3.4.8",
"source": {
"type": "git",
"url": "https://github.com/web-token/jwt-library.git",
- "reference": "1a25c8ced3e2b3c31d32dcfad215cbd8cb812f28"
+ "reference": "92445671cc788fa5f639898a67c06f9fd0bf491f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/web-token/jwt-library/zipball/1a25c8ced3e2b3c31d32dcfad215cbd8cb812f28",
- "reference": "1a25c8ced3e2b3c31d32dcfad215cbd8cb812f28",
+ "url": "https://api.github.com/repos/web-token/jwt-library/zipball/92445671cc788fa5f639898a67c06f9fd0bf491f",
+ "reference": "92445671cc788fa5f639898a67c06f9fd0bf491f",
"shasum": ""
},
"require": {
@@ -10409,7 +10541,7 @@
"paragonie/constant_time_encoding": "^2.6|^3.0",
"paragonie/sodium_compat": "^1.20|^2.0",
"php": ">=8.1",
- "psr/cache": "^3.0",
+ "psr/cache": "^2.0|^3.0",
"psr/clock": "^1.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
@@ -10472,7 +10604,7 @@
],
"support": {
"issues": "https://github.com/web-token/jwt-library/issues",
- "source": "https://github.com/web-token/jwt-library/tree/3.4.7"
+ "source": "https://github.com/web-token/jwt-library/tree/3.4.8"
},
"funding": [
{
@@ -10484,7 +10616,7 @@
"type": "patreon"
}
],
- "time": "2024-07-02T16:35:11+00:00"
+ "time": "2025-05-07T09:11:18+00:00"
},
{
"name": "webmozart/assert",
@@ -10611,16 +10743,16 @@
},
{
"name": "filp/whoops",
- "version": "2.17.0",
+ "version": "2.18.0",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
- "reference": "075bc0c26631110584175de6523ab3f1652eb28e"
+ "reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/filp/whoops/zipball/075bc0c26631110584175de6523ab3f1652eb28e",
- "reference": "075bc0c26631110584175de6523ab3f1652eb28e",
+ "url": "https://api.github.com/repos/filp/whoops/zipball/a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e",
+ "reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e",
"shasum": ""
},
"require": {
@@ -10670,7 +10802,7 @@
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
- "source": "https://github.com/filp/whoops/tree/2.17.0"
+ "source": "https://github.com/filp/whoops/tree/2.18.0"
},
"funding": [
{
@@ -10678,24 +10810,24 @@
"type": "github"
}
],
- "time": "2025-01-25T12:00:00+00:00"
+ "time": "2025-03-15T12:00:00+00:00"
},
{
"name": "hamcrest/hamcrest-php",
- "version": "v2.0.1",
+ "version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/hamcrest/hamcrest-php.git",
- "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3"
+ "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3",
- "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3",
+ "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
+ "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
"shasum": ""
},
"require": {
- "php": "^5.3|^7.0|^8.0"
+ "php": "^7.4|^8.0"
},
"replace": {
"cordoval/hamcrest-php": "*",
@@ -10703,8 +10835,8 @@
"kodova/hamcrest-php": "*"
},
"require-dev": {
- "phpunit/php-file-iterator": "^1.4 || ^2.0",
- "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0"
+ "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0",
+ "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"type": "library",
"extra": {
@@ -10727,22 +10859,22 @@
],
"support": {
"issues": "https://github.com/hamcrest/hamcrest-php/issues",
- "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1"
+ "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1"
},
- "time": "2020-07-09T08:09:16+00:00"
+ "time": "2025-04-30T06:54:44+00:00"
},
{
"name": "laravel/pint",
- "version": "v1.21.1",
+ "version": "v1.22.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
- "reference": "c44bffbb2334e90fba560933c45948fa4a3f3e86"
+ "reference": "941d1927c5ca420c22710e98420287169c7bcaf7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pint/zipball/c44bffbb2334e90fba560933c45948fa4a3f3e86",
- "reference": "c44bffbb2334e90fba560933c45948fa4a3f3e86",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/941d1927c5ca420c22710e98420287169c7bcaf7",
+ "reference": "941d1927c5ca420c22710e98420287169c7bcaf7",
"shasum": ""
},
"require": {
@@ -10753,12 +10885,12 @@
"php": "^8.2.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^3.70.2",
- "illuminate/view": "^11.44.1",
- "larastan/larastan": "^3.1.0",
+ "friendsofphp/php-cs-fixer": "^3.75.0",
+ "illuminate/view": "^11.44.7",
+ "larastan/larastan": "^3.4.0",
"laravel-zero/framework": "^11.36.1",
"mockery/mockery": "^1.6.12",
- "nunomaduro/termwind": "^2.3",
+ "nunomaduro/termwind": "^2.3.1",
"pestphp/pest": "^2.36.0"
},
"bin": [
@@ -10795,20 +10927,20 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
- "time": "2025-03-11T03:22:21+00:00"
+ "time": "2025-05-08T08:38:12+00:00"
},
{
"name": "laravel/telescope",
- "version": "v5.5.0",
+ "version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/telescope.git",
- "reference": "2594b20b946155ba767002d8af971e33e1095637"
+ "reference": "440908cb856cfbef9323244f7978ad4bf8cd2daa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/telescope/zipball/2594b20b946155ba767002d8af971e33e1095637",
- "reference": "2594b20b946155ba767002d8af971e33e1095637",
+ "url": "https://api.github.com/repos/laravel/telescope/zipball/440908cb856cfbef9323244f7978ad4bf8cd2daa",
+ "reference": "440908cb856cfbef9323244f7978ad4bf8cd2daa",
"shasum": ""
},
"require": {
@@ -10862,9 +10994,9 @@
],
"support": {
"issues": "https://github.com/laravel/telescope/issues",
- "source": "https://github.com/laravel/telescope/tree/v5.5.0"
+ "source": "https://github.com/laravel/telescope/tree/v5.7.0"
},
- "time": "2025-02-11T15:01:27+00:00"
+ "time": "2025-03-27T17:25:52+00:00"
},
{
"name": "mockery/mockery",
@@ -10951,16 +11083,16 @@
},
{
"name": "myclabs/deep-copy",
- "version": "1.13.0",
+ "version": "1.13.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "024473a478be9df5fdaca2c793f2232fe788e414"
+ "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
- "reference": "024473a478be9df5fdaca2c793f2232fe788e414",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c",
+ "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c",
"shasum": ""
},
"require": {
@@ -10999,7 +11131,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1"
},
"funding": [
{
@@ -11007,42 +11139,43 @@
"type": "tidelift"
}
],
- "time": "2025-02-12T12:17:51+00:00"
+ "time": "2025-04-29T12:36:36+00:00"
},
{
"name": "nunomaduro/collision",
- "version": "v8.6.1",
+ "version": "v8.8.0",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/collision.git",
- "reference": "86f003c132143d5a2ab214e19933946409e0cae7"
+ "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nunomaduro/collision/zipball/86f003c132143d5a2ab214e19933946409e0cae7",
- "reference": "86f003c132143d5a2ab214e19933946409e0cae7",
+ "url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8",
+ "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8",
"shasum": ""
},
"require": {
- "filp/whoops": "^2.16.0",
+ "filp/whoops": "^2.18.0",
"nunomaduro/termwind": "^2.3.0",
"php": "^8.2.0",
- "symfony/console": "^7.2.1"
+ "symfony/console": "^7.2.5"
},
"conflict": {
- "laravel/framework": "<11.39.1 || >=13.0.0",
- "phpunit/phpunit": "<11.5.3 || >=12.0.0"
+ "laravel/framework": "<11.44.2 || >=13.0.0",
+ "phpunit/phpunit": "<11.5.15 || >=13.0.0"
},
"require-dev": {
- "larastan/larastan": "^2.9.12",
- "laravel/framework": "^11.39.1",
- "laravel/pint": "^1.20.0",
- "laravel/sail": "^1.40.0",
- "laravel/sanctum": "^4.0.7",
- "laravel/tinker": "^2.10.0",
- "orchestra/testbench-core": "^9.9.2",
- "pestphp/pest": "^3.7.3",
- "sebastian/environment": "^6.1.0 || ^7.2.0"
+ "brianium/paratest": "^7.8.3",
+ "larastan/larastan": "^3.2",
+ "laravel/framework": "^11.44.2 || ^12.6",
+ "laravel/pint": "^1.21.2",
+ "laravel/sail": "^1.41.0",
+ "laravel/sanctum": "^4.0.8",
+ "laravel/tinker": "^2.10.1",
+ "orchestra/testbench-core": "^9.12.0 || ^10.1",
+ "pestphp/pest": "^3.8.0",
+ "sebastian/environment": "^7.2.0 || ^8.0"
},
"type": "library",
"extra": {
@@ -11105,7 +11238,7 @@
"type": "patreon"
}
],
- "time": "2025-01-23T13:41:43+00:00"
+ "time": "2025-04-03T14:33:09+00:00"
},
{
"name": "phar-io/manifest",
@@ -11550,16 +11683,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "11.5.12",
+ "version": "11.5.20",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "d42785840519401ed2113292263795eb4c0f95da"
+ "reference": "e6bdea63ecb7a8287d2cdab25bdde3126e0cfe6f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d42785840519401ed2113292263795eb4c0f95da",
- "reference": "d42785840519401ed2113292263795eb4c0f95da",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e6bdea63ecb7a8287d2cdab25bdde3126e0cfe6f",
+ "reference": "e6bdea63ecb7a8287d2cdab25bdde3126e0cfe6f",
"shasum": ""
},
"require": {
@@ -11569,7 +11702,7 @@
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.13.0",
+ "myclabs/deep-copy": "^1.13.1",
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.2",
@@ -11579,14 +11712,14 @@
"phpunit/php-text-template": "^4.0.1",
"phpunit/php-timer": "^7.0.1",
"sebastian/cli-parser": "^3.0.2",
- "sebastian/code-unit": "^3.0.2",
+ "sebastian/code-unit": "^3.0.3",
"sebastian/comparator": "^6.3.1",
"sebastian/diff": "^6.0.2",
"sebastian/environment": "^7.2.0",
"sebastian/exporter": "^6.3.0",
"sebastian/global-state": "^7.0.2",
"sebastian/object-enumerator": "^6.0.1",
- "sebastian/type": "^5.1.0",
+ "sebastian/type": "^5.1.2",
"sebastian/version": "^5.0.2",
"staabm/side-effects-detector": "^1.0.5"
},
@@ -11631,7 +11764,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.12"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.20"
},
"funding": [
{
@@ -11642,12 +11775,20 @@
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
- "time": "2025-03-07T07:31:03+00:00"
+ "time": "2025-05-11T06:39:52+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -11708,16 +11849,16 @@
},
{
"name": "sebastian/code-unit",
- "version": "3.0.2",
+ "version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
- "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca"
+ "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca",
- "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64",
+ "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64",
"shasum": ""
},
"require": {
@@ -11753,7 +11894,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"security": "https://github.com/sebastianbergmann/code-unit/security/policy",
- "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2"
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3"
},
"funding": [
{
@@ -11761,7 +11902,7 @@
"type": "github"
}
],
- "time": "2024-12-12T09:59:06+00:00"
+ "time": "2025-03-19T07:56:08+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@@ -12466,16 +12607,16 @@
},
{
"name": "sebastian/type",
- "version": "5.1.0",
+ "version": "5.1.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
- "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac"
+ "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac",
- "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e",
+ "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e",
"shasum": ""
},
"require": {
@@ -12511,7 +12652,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"security": "https://github.com/sebastianbergmann/type/security/policy",
- "source": "https://github.com/sebastianbergmann/type/tree/5.1.0"
+ "source": "https://github.com/sebastianbergmann/type/tree/5.1.2"
},
"funding": [
{
@@ -12519,7 +12660,7 @@
"type": "github"
}
],
- "time": "2024-09-17T13:12:04+00:00"
+ "time": "2025-03-18T13:35:50+00:00"
},
{
"name": "sebastian/version",
diff --git a/config/image.php b/config/image.php
index eb77c9089..dd6df3137 100644
--- a/config/image.php
+++ b/config/image.php
@@ -7,14 +7,12 @@ return [
| Image Driver
|--------------------------------------------------------------------------
|
- | Intervention Image supports "GD Library" and "Imagick" to process images
- | internally. You may choose one of them according to your PHP
+ | Intervention Image supports "GD Library", "Imagick" and "libvips" to process
+ | images internally. You may choose one of them according to your PHP
| configuration. By default PHP's "GD Library" implementation is used.
|
- | Supported: "gd", "imagick"
+ | Supported: "gd", "imagick", "libvips"
|
*/
-
'driver' => env('IMAGE_DRIVER', 'gd'),
-
];
diff --git a/config/remote-auth.php b/config/remote-auth.php
index 182bb99a7..353e59c14 100644
--- a/config/remote-auth.php
+++ b/config/remote-auth.php
@@ -54,4 +54,79 @@ return [
'limit' => env('PF_LOGIN_WITH_MASTODON_MAX_USES_LIMIT', 3)
]
],
+
+ 'oidc' => [
+ /*
+ * Enable OIDC authentication
+ *
+ * Enable Sign-in with OpenID Connect (OIDC) authentication providers
+ */
+ 'enabled' => env('PF_OIDC_ENABLED', false),
+
+ /*
+ * Client ID
+ *
+ * The client ID provided by your OIDC provider
+ */
+ 'clientId' => env('PF_OIDC_CLIENT_ID', false),
+
+ /*
+ * Client Secret
+ *
+ * The client secret provided by your OIDC provider
+ */
+ 'clientSecret' => env('PF_OIDC_CLIENT_SECRET', false),
+
+ /*
+ * OAuth Scopes
+ *
+ * The scopes to request from the OIDC provider, typically including
+ * 'openid' (required), 'profile', and 'email' for basic user information
+ */
+ 'scopes' => env('PF_OIDC_SCOPES', 'openid profile email'),
+
+ /*
+ * Authorization URL
+ *
+ * The endpoint used to start the OIDC authentication flow
+ */
+ 'authorizeURL' => env('PF_OIDC_AUTHORIZE_URL', ''),
+
+ /*
+ * Token URL
+ *
+ * The endpoint used to exchange the authorization code for an access token
+ */
+ 'tokenURL' => env('PF_OIDC_TOKEN_URL', ''),
+
+ /*
+ * Profile URL
+ *
+ * The endpoint used to retrieve user information with a valid access token
+ */
+ 'profileURL' => env('PF_OIDC_PROFILE_URL', ''),
+
+ /*
+ * Logout URL
+ *
+ * The endpoint used to log the user out of the OIDC provider
+ */
+ 'logoutURL' => env('PF_OIDC_LOGOUT_URL', ''),
+
+ /*
+ * Username Field
+ *
+ * The field from the OIDC profile response to use as the username
+ * Default is 'preferred_username' but can be changed based on your provider
+ */
+ 'field_username' => env('PF_OIDC_USERNAME_FIELD', "preferred_username"),
+
+ /*
+ * ID Field
+ *
+ * The field from the OIDC profile response to use as the unique identifier
+ * Default is 'sub' (subject) which is standard in OIDC implementations
+ */
+ 'field_id' => env('PF_OIDC_FIELD_ID', 'sub'),
+ ],
];
diff --git a/database/migrations/2025_01_30_061434_create_user_oidc_mapping_table.php b/database/migrations/2025_01_30_061434_create_user_oidc_mapping_table.php
new file mode 100644
index 000000000..0986d9aa9
--- /dev/null
+++ b/database/migrations/2025_01_30_061434_create_user_oidc_mapping_table.php
@@ -0,0 +1,30 @@
+bigIncrements('id');
+ $table->bigInteger('user_id')->unsigned()->index();
+ $table->string('oidc_id')->unique()->index();
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('user_oidc_mappings');
+ }
+};
diff --git a/public/_lang/de.json b/public/_lang/de.json
index e6ac7c47b..75e07aabc 100644
--- a/public/_lang/de.json
+++ b/public/_lang/de.json
@@ -53,6 +53,7 @@
"language": "Sprache",
"privacy": "Privatsph\u00e4re",
"terms": "AGB",
+ "legalNotice": "Impressum",
"backToPreviousDesign": "Zur\u00fcck zum vorherigen Design"
},
"directMessages": {
diff --git a/public/_lang/en.json b/public/_lang/en.json
index 1a2399b6f..f82a418ae 100644
--- a/public/_lang/en.json
+++ b/public/_lang/en.json
@@ -26,7 +26,9 @@
"clickHere": "click here",
"sensitive": "Sensitive",
"sensitiveContent": "Sensitive Content",
- "sensitiveContentWarning": "This post may contain sensitive content"
+ "sensitiveContentWarning": "This post may contain sensitive content",
+ "loading": "Loading...",
+ "continue": "Continue"
},
"site": {
"terms": "Terms of Use",
@@ -49,11 +51,13 @@
"appearance": "Appearance",
"compose": "Create New",
"logout": "Logout",
+ "createStory": "Create Story",
"about": "About",
"help": "Help",
"language": "Language",
"privacy": "Privacy",
"terms": "Terms",
+ "legalNotice": "Legal Notice",
"backToPreviousDesign": "Go back to previous design"
},
"directMessages": {
@@ -185,7 +189,34 @@
"unpinPostConfirm": "Are you sure you want to unpin this post?"
},
"story": {
- "add": "Add Story"
+ "add": "Add Story",
+ "myStory": "My Story",
+ "viewMyStory": "View My Story",
+ "goBack": "Go Back",
+ "delete": "Delete",
+ "crop": "Crop",
+ "error": "An error occurred, please try again later.",
+ "cropping": "Cropping",
+ "storyDuration": "Story Duration",
+ "seconds": "seconds",
+ "processing": "Processing",
+ "shareWithFollowers": "Share moments with followers that last 24 hours",
+ "cancel": "Cancel",
+ "viewedBy": "Viewed by",
+ "next": "Next",
+ "zoom": "Pan around and pinch to zoom",
+ "options": "Options",
+ "allowReplies": "Allow Replies",
+ "allowReactions": "Allow reactions",
+ "limit": "You have reached the limit for new stories",
+ "reactionSent": "Reaction sent",
+ "replySent": "Reply sent",
+ "expiresIn": "Expires in",
+ "viewers": "Viewers",
+ "report": "Report",
+ "close": "Close",
+ "myStories": "My Stories",
+ "seeAll": "See All"
},
"timeline": {
"peopleYouMayKnow": "People you may know",
@@ -219,5 +250,79 @@
"grid": "Grid",
"masonry": "Masonry",
"feed": "Feed"
+ },
+ "settings": {
+ "filters": {
+ "title": "Filters",
+ "manage_your_custom_filters": "Manage your custom filters.",
+ "customize_your_experience": "Customize your experience with powerful content filters that screen for specific words or phrases throughout your entire account - including home and public timelines, and hashtag feeds.",
+ "add_new_filter": "Add New Filter",
+ "limit_message": "You can add up to :filters_num filters that can have up to :keywords_num keywords.",
+ "learn_more_help_center": "Learn more in our Help Center.",
+ "no_filters": "You don't have any content filters yet",
+ "no_filters_message": "Filters help you hide content containing specific words or phrases from your timelines.",
+ "create_first_filter": "Create Your First Filter",
+ "no_matching_filters": "You don't have any content filters that match :searchQuery.",
+ "no_matching_filters_message": "Filters help you hide content containing specific words or phrases from your timelines.",
+ "create_new_filter": "Create new Filter",
+ "filter_title": "Filter Title",
+ "edit_filter": "Edit Filter",
+ "create_filter": "Create Filter",
+ "advance_mode": "Advanced Mode",
+ "simple_mode": "Simple Mode",
+ "keywords": "Keywords",
+ "legend": "Legend",
+ "whole_word": "Whole word",
+ "partial_word": "Partial word",
+ "duplicate_not_allowed": "Duplicate keywords are not allowed",
+ "filter_action": "Filter Action",
+ "hide_media_blur": "Hide media behind a blurbash",
+ "show_warning": "Show warning before displaying content",
+ "hide_content_completely": "Hide content completely",
+ "apply_filters_to": "Apply filters to",
+ "home_timeline": "Home Timeline",
+ "notifications": "Notifications",
+ "public_timeline": "Public Timeline",
+ "hashtags": "Hashtag",
+ "groups": "Groups",
+ "conversations": "Conversations",
+ "duration": "Duration",
+ "forever": "Forever",
+ "30_minutes": "30 minutes",
+ "1_hour": "1 hour",
+ "6_hours": "6 hours",
+ "12_hours": "12 hours",
+ "1_day": "1 day",
+ "1_week": "1 week",
+ "cutom": "Custom..",
+ "enter_duration_in_seconds": "Enter duration in seconds",
+ "save_changes": "Save Changes",
+ "name_your_filter": "Name your filter",
+ "give_your_filter_a_name": "Give your filter a name that will help you remember what content it filters.",
+ "my_filter_name": "My Filter Name",
+ "filter_duration": "Filter Duration",
+ "add_filter_keywords": "Add filter keywords",
+ "add_word_or_phrase": "Add words or phrases you want to filter.
Content containing these words will be filtered according to your settings.",
+ "whole_word_match": "Whole word match - filters exact matches only (e.g. \"book\" won't match \"bookstore\")",
+ "partial_word_match": "Partial word match - filters any content containing this text (e.g. \"book\" will match \"bookstore\")",
+ "add_another_keyword": "Add another keyword",
+ "please_remove_duplicate_keywords": "Please remove duplicate keywords before continuing",
+ "choose_filter_action": "Choose filter action",
+ "choose_filter_action_description": "How would you like to handle content that matches your filter?",
+ "hide_completely": "Completely hide content that matches",
+ "choose_where_to_apply": "Choose Where to Apply",
+ "choose_where_to_apply_description": "Select which sections of the application should use this filter.",
+ "review_your_filter": "Review your filter",
+ "review_your_filter_description": "Here's a summary of the filter you've created.",
+ "no_keywords_specified": "No keywords specified",
+ "action": "Action",
+ "expires": "Expires",
+ "never_expires": "Never Expires",
+ "titleAdvance": "Title",
+ "context": "Context",
+ "review": "Review",
+ "add_keyword": "Add a keyword...",
+ "enter_filter_title": "Enter filter title"
+ }
}
}
\ No newline at end of file
diff --git a/public/_lang/it.json b/public/_lang/it.json
index 66a4c927e..f2e4ba241 100644
--- a/public/_lang/it.json
+++ b/public/_lang/it.json
@@ -23,7 +23,7 @@
"proceed": "Procedi",
"next": "Avanti",
"close": "Chiudi",
- "clickHere": "cclicca qui",
+ "clickHere": "clicca qui",
"sensitive": "Sensibile",
"sensitiveContent": "Contenuto Sensibile",
"sensitiveContentWarning": "Questo post potrebbe contenere contenuti sensibili"
@@ -63,7 +63,7 @@
"notifications": {
"liked": "ha messo like a",
"commented": "ha commentato il tuo",
- "reacted": "ha reagito a",
+ "reacted": "ha reagito al tuo",
"shared": "ha condiviso il tuo",
"tagged": "ti ha taggato in",
"updatedA": "ha aggiornato un",
diff --git a/public/_lang/nl.json b/public/_lang/nl.json
index d8d468338..52839973f 100644
--- a/public/_lang/nl.json
+++ b/public/_lang/nl.json
@@ -75,16 +75,16 @@
"applicationApproved": "werd goedgekeurd!",
"applicationRejected": "werd afgekeurd. Je kunt over 6 maanden opnieuw aanmelden.",
"dm": "dm",
- "groupPost": "groepspost",
+ "groupPost": "groepsbericht",
"modlog": "modlogboek",
- "post": "post",
+ "post": "bericht",
"story": "verhaal",
"noneFound": "Geen notificaties gevonden"
},
"post": {
"shareToFollowers": "Deel met volgers",
"shareToOther": "Deel met anderen",
- "noLikes": "Nog geen leuks",
+ "noLikes": "Nog geen likes",
"uploading": "Uploaden"
},
"profile": {
@@ -99,10 +99,10 @@
"followRequested": "Volgen verzocht",
"joined": "Lid geworden",
"emptyCollections": "We kunnen geen collecties vinden",
- "emptyPosts": "We kunnen geen posts vinden"
+ "emptyPosts": "We kunnen geen berichten vinden"
},
"menu": {
- "viewPost": "Post bekijken",
+ "viewPost": "Berichten bekijken",
"viewProfile": "Profiel bekijken",
"moderationTools": "Moderatiegereedschappen",
"report": "Rapporteren",
@@ -123,13 +123,13 @@
"impersonation": "Impersonatie",
"scamOrFraud": "Oplichting of fraude",
"confirmReport": "Bevestig Rapport",
- "confirmReportText": "Weet je zeker dat je deze post wilt rapporteren?",
+ "confirmReportText": "Weet je zeker dat je dit bericht wilt rapporteren?",
"reportSent": "Rapport verzonden!",
"reportSentText": "We hebben uw rapport met succes ontvangen.",
- "reportSentError": "Er is een probleem opgetreden bij het rapporteren van deze post.",
- "modAddCWConfirm": "Weet u zeker dat u een waarschuwing voor inhoud wilt toevoegen aan deze post?",
+ "reportSentError": "Er is een probleem opgetreden bij het rapporteren van dit bericht.",
+ "modAddCWConfirm": "Weet u zeker dat u een waarschuwing voor inhoud wilt toevoegen aan dit bericht?",
"modCWSuccess": "Inhoudswaarschuwing succesvol toegevoegd",
- "modRemoveCWConfirm": "Weet u zeker dat u de waarschuwing voor inhoud wilt verwijderen van deze post?",
+ "modRemoveCWConfirm": "Weet u zeker dat u de inhoudswaarschuwing wilt verwijderen van dit bericht?",
"modRemoveCWSuccess": "Succesvol de inhoudswaarschuwing verwijderd",
"modUnlistConfirm": "Weet je zeker dat je deze post uit de lijst wilt halen?",
"modUnlistSuccess": "Post met succes uit de lijst gehaald",
diff --git a/public/_lang/pt.json b/public/_lang/pt.json
index 705062fb2..7f49b6130 100644
--- a/public/_lang/pt.json
+++ b/public/_lang/pt.json
@@ -3,17 +3,17 @@
"comment": "Comentar",
"commented": "Comentado",
"comments": "Coment\u00e1rios",
- "like": "Gosto",
- "liked": "Gostei",
- "likes": "Gostos",
+ "like": "Curtir",
+ "liked": "Curtiu",
+ "likes": "Curtidas",
"share": "Compartilhar",
"shared": "Compartilhado",
- "shares": "Partilhas",
- "unshare": "Despartilhar",
+ "shares": "Compartilhamentos",
+ "unshare": "Remover compartilhamento",
"bookmark": "Favorito",
"cancel": "Cancelar",
"copyLink": "Copiar link",
- "delete": "Eliminar",
+ "delete": "Excluir",
"error": "Erro",
"errorMsg": "Algo correu mal. Por favor, tente novamente mais tarde.",
"oops": "Opa!",
@@ -26,7 +26,9 @@
"clickHere": "clique aqui",
"sensitive": "Sens\u00edvel",
"sensitiveContent": "Conte\u00fado sens\u00edvel",
- "sensitiveContentWarning": "Este post pode conter conte\u00fado sens\u00edvel"
+ "sensitiveContentWarning": "Este post pode conter conte\u00fado sens\u00edvel",
+ "loading": "Carregando...",
+ "continue": "Continuar"
},
"site": {
"terms": "Termos de Uso",
@@ -34,11 +36,11 @@
},
"navmenu": {
"search": "Pesquisa",
- "admin": "Painel de Administra\u00e7\u00e3o",
+ "admin": "Painel Administrativo",
"homeFeed": "Inicio",
"localFeed": "Feed local",
"globalFeed": "Feed global",
- "discover": "Descobrir",
+ "discover": "Explorar",
"directMessages": "Mensagens Diretas",
"notifications": "Notifica\u00e7\u00f5es",
"groups": "Grupos",
@@ -49,6 +51,7 @@
"appearance": "Apar\u00eancia",
"compose": "Criar novo",
"logout": "Terminar Sess\u00e3o",
+ "createStory": "Criar Story",
"about": "Sobre",
"help": "Ajuda",
"language": "Idioma",
@@ -146,11 +149,11 @@
"unarchive": "Retirar do arquivo",
"embed": "Incorporar",
"selectOneOption": "Selecione uma das seguintes op\u00e7\u00f5es",
- "unlistFromTimelines": "Remover das cronologias",
+ "unlistFromTimelines": "Remover das Timelines",
"addCW": "Adicionar aviso de conte\u00fado",
"removeCW": "Remover aviso de conte\u00fado",
"markAsSpammer": "Marcar como Spammer",
- "markAsSpammerText": "Remover das cronologias e adicionar um aviso de conte\u00fado \u00e0s publica\u00e7\u00f5es existentes e futuras",
+ "markAsSpammerText": "Remover das timelines e adicionar um aviso de conte\u00fado \u00e0s publica\u00e7\u00f5es existentes e futuras",
"spam": "Lixo Eletr\u00f4nico",
"sensitive": "Conte\u00fado Sens\u00edvel",
"abusive": "Abusivo ou prejudicial",
@@ -185,7 +188,34 @@
"unpinPostConfirm": "Tem certeza de que deseja desafixar esta publica\u00e7\u00e3o?"
},
"story": {
- "add": "Adicionar Story"
+ "add": "Adicionar Story",
+ "myStory": "Minha Story",
+ "viewMyStory": "Ver Minha Story",
+ "goBack": "Voltar",
+ "delete": "Excluir",
+ "crop": "Cortar",
+ "error": "Ocorreu um erro, por favor tente novamente mais tarde.",
+ "cropping": "Cortando",
+ "storyDuration": "Dura\u00e7\u00e3o da Story",
+ "seconds": "segundos",
+ "processing": "Processando",
+ "shareWithFollowers": "Compartilhe momentos com seguidores que duram 24 horas",
+ "cancel": "Cancelar",
+ "viewdBy": "Visualizado por",
+ "next": "Pr\u00f3ximo",
+ "zoom": "Mova e pin\u00e7a para dar zoom",
+ "options": "Op\u00e7\u00f5es",
+ "allowReplies": "Permitir Respostas",
+ "allowReactions": "Permitir Rea\u00e7\u00f5es",
+ "limit": "Voc\u00ea atingiu o limite para novas stories",
+ "reactionSent": "Rea\u00e7\u00e3o enviada",
+ "replySent": "Resposta enviada",
+ "expiresIn": "Expira em",
+ "viewers": "Visualizadores",
+ "report": "Denunciar",
+ "close": "Fechar",
+ "myStories": "My Stories",
+ "seeAll": "Ver todas as stories"
},
"timeline": {
"peopleYouMayKnow": "Pessoas que talvez conhe\u00e7a",
@@ -219,5 +249,79 @@
"grid": "Grade",
"masonry": "Mansory",
"feed": "Feed"
+ },
+ "settings": {
+ "filters": {
+ "title": "Filtros",
+ "manage_your_custom_filters": "Gerencie seus filtros personalizados.",
+ "customize_your_experience": "Personalize sua experi\u00eancia com filtros de conte\u00fado poderosos que verificam palavras ou frases espec\u00edficas em toda a sua conta - incluindo linhas do tempo pessoais e p\u00fablicas, e feeds de hashtags.",
+ "add_new_filter": "Adicionar Novo Filtro",
+ "limit_message": "Voc\u00ea pode adicionar at\u00e9 :filters_num filtros que podem ter at\u00e9 :keywords_num palavras-chave.",
+ "learn_more_help_center": "Saiba mais no nosso Centro de Ajuda.",
+ "no_filters": "Voc\u00ea ainda n\u00e3o tem nenhum filtro de conte\u00fado",
+ "no_filters_message": "Os filtros ajudam voc\u00ea a ocultar conte\u00fado que cont\u00e9m palavras ou frases espec\u00edficas das suas linhas do tempo.",
+ "create_first_filter": "Crie Seu Primeiro Filtro",
+ "no_matching_filters": "Voc\u00ea n\u00e3o tem nenhum filtro de conte\u00fado que corresponda a :searchQuery.",
+ "no_matching_filters_message": "Os filtros ajudam voc\u00ea a ocultar conte\u00fado que cont\u00e9m palavras ou frases espec\u00edficas das suas linhas do tempo.",
+ "create_new_filter": "Criar Novo Filtro",
+ "filter_title": "T\u00edtulo do Filtro",
+ "edit_filter": "Editar Filtro",
+ "create_filter": "Criar Filtro",
+ "advance_mode": "Modo Avan\u00e7ado",
+ "simple_mode": "Modo Simples",
+ "keywords": "Palavras-chave",
+ "legend": "Legenda",
+ "whole_word": "Palavra inteira",
+ "partial_word": "Palavra parcial",
+ "duplicate_not_allowed": "Palavras-chave duplicadas n\u00e3o s\u00e3o permitidas",
+ "filter_action": "A\u00e7\u00e3o do Filtro",
+ "hide_media_blur": "Ocultar m\u00eddia atr\u00e1s de um desfoque",
+ "show_warning": "Mostrar aviso antes de exibir o conte\u00fado",
+ "hide_content_completely": "Ocultar conte\u00fado completamente",
+ "apply_filters_to": "Aplicar filtros a",
+ "home_timeline": "Linha do Tempo Pessoal",
+ "notifications": "Notifica\u00e7\u00f5es",
+ "public_timeline": "Linha do Tempo P\u00fablica",
+ "hashtags": "Hashtags",
+ "groups": "Grupos",
+ "conversations": "Conversas",
+ "duration": "Dura\u00e7\u00e3o",
+ "forever": "Para Sempre",
+ "30_minutes": "30 minutos",
+ "1_hour": "1 hora",
+ "6_hours": "6 horas",
+ "12_hours": "12 horas",
+ "1_day": "1 dia",
+ "1_week": "1 semana",
+ "cutom": "Personalizado...",
+ "enter_duration_in_seconds": "Insira a dura\u00e7\u00e3o em segundos",
+ "save_changes": "Salvar Altera\u00e7\u00f5es",
+ "name_your_filter": "Nomeie seu filtro",
+ "give_your_filter_a_name": "D\u00ea ao seu filtro um nome que o ajude a lembrar o que ele filtra.",
+ "my_filter_name": "Nome do Meu Filtro",
+ "filter_duration": "Dura\u00e7\u00e3o do Filtro",
+ "add_filter_keywords": "Adicionar palavras-chave ao filtro",
+ "add_word_or_phrase": "Adicione palavras ou frases que voc\u00ea deseja filtrar.
Conte\u00fado contendo essas palavras ser\u00e1 filtrado de acordo com suas configura\u00e7\u00f5es.",
+ "whole_word_match": "Correspond\u00eancia de palavra inteira - filtra apenas correspond\u00eancias exatas (ex.: \"livro\" n\u00e3o corresponder\u00e1 a \"livraria\")",
+ "partial_word_match": "Correspond\u00eancia de palavra parcial - filtra qualquer conte\u00fado que contenha este texto (ex.: \"livro\" corresponder\u00e1 a \"livraria\")",
+ "add_another_keyword": "Adicionar outra palavra-chave",
+ "please_remove_duplicate_keywords": "Por favor, remova palavras-chave duplicadas antes de continuar",
+ "choose_filter_action": "Escolha a a\u00e7\u00e3o do filtro",
+ "choose_filter_action_description": "Como voc\u00ea gostaria de lidar com o conte\u00fado que corresponde ao seu filtro?",
+ "hide_completely": "Ocultar completamente o conte\u00fado que corresponde",
+ "choose_where_to_apply": "Escolha Onde Aplicar",
+ "choose_where_to_apply_description": "Selecione quais se\u00e7\u00f5es do aplicativo devem usar este filtro.",
+ "review_your_filter": "Revise seu filtro",
+ "review_your_filter_description": "Aqui est\u00e1 um resumo do filtro que voc\u00ea criou.",
+ "no_keywords_specified": "Nenhuma palavra-chave especificada",
+ "action": "A\u00e7\u00e3o",
+ "expires": "Expira",
+ "never_expires": "Nunca Expira",
+ "titleAdvance": "T\u00edtulo",
+ "context": "Contexto",
+ "review": "Revis\u00e3o",
+ "add_keyword": "Adicionar uma palavra-chave...",
+ "enter_filter_title": "Insira o t\u00edtulo do filtro"
+ }
}
}
\ No newline at end of file
diff --git a/public/_lang/tr.json b/public/_lang/tr.json
index 49d1ce183..a887279a0 100644
--- a/public/_lang/tr.json
+++ b/public/_lang/tr.json
@@ -98,7 +98,7 @@
"editProfile": "Profili D\u00fczenle",
"followRequested": "Takip \u0130ste\u011fi",
"joined": "Kat\u0131ld\u0131",
- "emptyCollections": "Herhangi bir koleksiyon bulunmuyor",
+ "emptyCollections": "Herhangi bir derleme bulunmuyor",
"emptyPosts": "Herhangi bir g\u00f6nderi bulunmuyor"
},
"menu": {
diff --git a/public/_lang/zh.json b/public/_lang/zh.json
index d0d6c25c8..ac4343efe 100644
--- a/public/_lang/zh.json
+++ b/public/_lang/zh.json
@@ -1,170 +1,170 @@
{
"common": {
- "comment": "\u8a55\u8ad6",
- "commented": "\u5df2\u8a55\u8ad6",
- "comments": "\u689d\u610f\u898b\u8a55\u8ad6",
- "like": "\u6309\u8b9a",
- "liked": "\u5df2\u6309\u8b9a",
- "likes": "\u500b\u4eba\u5df2\u6309\u8b9a",
+ "comment": "\u8bc4\u8bba",
+ "commented": "\u5df2\u8bc4\u8bba",
+ "comments": "\u8bc4\u8bba",
+ "like": "\u8d5e",
+ "liked": "\u5df2\u8d5e",
+ "likes": "\u70b9\u8d5e",
"share": "\u5206\u4eab",
- "shared": "\u5df2\u5206\u4eab",
- "shares": "\u6b21\u5206\u4eab",
+ "shared": "\u5df2\u5206\u4eab\u7684",
+ "shares": "\u5206\u4eab",
"unshare": "\u53d6\u6d88\u5206\u4eab",
- "bookmark": "\u66f8\u7c64",
+ "bookmark": "\u6536\u85cf",
"cancel": "\u53d6\u6d88",
- "copyLink": "\u8907\u88fd\u9023\u7d50",
+ "copyLink": "\u590d\u5236\u94fe\u63a5",
"delete": "\u5220\u9664",
- "error": "\u932f\u8aa4",
- "errorMsg": "\u51fa\u4e86\u9ede\u5c0f\u554f\u984c\uff0c\u8acb\u7a0d\u5f8c\u91cd\u8a66\u3002",
- "oops": "\u5443\u2026",
- "other": "\u5176\u4ed6",
- "readMore": "\u7e7c\u7e8c\u8b80\u4e0b\u53bb",
+ "error": "\u9519\u8bef",
+ "errorMsg": "\u51fa\u9519\u4e86\u3002\u8bf7\u7a0d\u540e\u518d\u8bd5\u3002",
+ "oops": "\u54ce\u5440\uff01",
+ "other": "\u5176\u5b83",
+ "readMore": "\u9605\u8bfb\u66f4\u591a",
"success": "\u6210\u529f",
- "proceed": "\u7e7c\u7e8c",
- "next": "\u4e0b\u4e00\u500b",
- "close": "\u95dc\u9589",
- "clickHere": "\u9ede\u64ca\u6b64\u8655",
- "sensitive": "\u654f\u611f\u5167\u5bb9",
- "sensitiveContent": "\u654f\u611f\u5167\u5bb9",
- "sensitiveContentWarning": "\u9019\u7bc7\u6587\u53ef\u80fd\u5305\u542b\u654f\u611f\u5167\u5bb9"
+ "proceed": "\u7ee7\u7eed",
+ "next": "\u4e0b\u4e00\u4e2a",
+ "close": "\u5173\u95ed",
+ "clickHere": "\u70b9\u51fb\u6b64\u5904",
+ "sensitive": "\u654f\u611f",
+ "sensitiveContent": "\u654f\u611f\u5185\u5bb9",
+ "sensitiveContentWarning": "\u6b64\u5e16\u6587\u53ef\u80fd\u5305\u542b\u654f\u611f\u5185\u5bb9"
},
"site": {
- "terms": "\u4f7f\u7528\u689d\u6b3e",
- "privacy": "\u96b1\u79c1\u6b0a\u653f\u7b56"
+ "terms": "\u4f7f\u7528\u6761\u6b3e",
+ "privacy": "\u9690\u79c1\u653f\u7b56"
},
"navmenu": {
- "search": "\u641c\u5c0b",
- "admin": "\u7ba1\u7406\u5100\u8868\u677f",
- "homeFeed": "\u9996\u9801\u52d5\u614b",
- "localFeed": "\u7ad9\u5167\u52d5\u614b",
- "globalFeed": "\u806f\u90a6\u52d5\u614b",
+ "search": "\u641c\u7d22",
+ "admin": "\u7ba1\u7406\u9762\u677f",
+ "homeFeed": "\u4e3b\u9875",
+ "localFeed": "\u672c\u7ad9\u52a8\u6001",
+ "globalFeed": "\u8de8\u7ad9\u52a8\u6001",
"discover": "\u63a2\u7d22",
- "directMessages": "\u79c1\u4eba\u8a0a\u606f",
+ "directMessages": "\u79c1\u4fe1",
"notifications": "\u901a\u77e5",
- "groups": "\u7fa4\u7d44",
- "stories": "\u9650\u6642\u52d5\u614b",
- "profile": "\u500b\u4eba\u6a94\u6848",
- "drive": "Drive",
- "settings": "\u8a2d\u5b9a",
- "compose": "\u65b0\u589e",
+ "groups": "\u7fa4\u7ec4",
+ "stories": "\u6545\u4e8b",
+ "profile": "\u4e2a\u4eba\u8d44\u6599",
+ "drive": "\u7f51\u76d8",
+ "settings": "\u8bbe\u7f6e",
+ "compose": "\u521b\u5efa",
"logout": "\u767b\u51fa",
- "about": "\u95dc\u65bc",
- "help": "\u8aac\u660e",
- "language": "\u8a9e\u8a00",
- "privacy": "\u96b1\u79c1\u6b0a",
- "terms": "\u689d\u6b3e",
- "backToPreviousDesign": "\u56de\u5230\u5148\u524d\u7684\u8a2d\u8a08"
+ "about": "\u5173\u4e8e",
+ "help": "\u5e2e\u52a9",
+ "language": "\u8bed\u8a00",
+ "privacy": "\u9690\u79c1",
+ "terms": "\u4f7f\u7528\u6761\u6b3e",
+ "backToPreviousDesign": "\u8fd4\u56de\u4e0a\u4e00\u4e2a\u8bbe\u8ba1"
},
"directMessages": {
- "inbox": "\u6536\u4ef6\u593e",
- "sent": "\u5bc4\u4ef6\u593e",
- "requests": "\u8acb\u6c42"
+ "inbox": "\u6536\u4ef6\u7bb1",
+ "sent": "\u5df2\u53d1\u9001",
+ "requests": "\u8bf7\u6c42"
},
"notifications": {
- "liked": "\u559c\u6b61\u4f60\u7684",
- "commented": "\u8a55\u8ad6\u4e86\u4f60\u7684",
- "reacted": "\u53cd\u61c9\u4e86\u4f60\u7684",
- "shared": "\u5206\u4eab\u4e86\u4f60\u7684",
- "tagged": "tagged you in a",
- "updatedA": "updated a",
- "sentA": "sent a",
- "followed": "\u5df2\u95dc\u6ce8",
- "mentioned": "\u88ab\u63d0\u53ca",
+ "liked": "\u70b9\u8d5e\u4e86\u4f60\u7684",
+ "commented": "\u8bc4\u8bba\u4e86\u4f60\u7684",
+ "reacted": "\u56de\u5e94\u4e86\u4f60\u7684",
+ "shared": "\u8f6c\u53d1\u4e86\u4f60\u7684",
+ "tagged": "\u5728\u5e16\u5b50\u4e2d\u6807\u8bb0\u4e86\u4f60",
+ "updatedA": "\u66f4\u65b0\u4e86\u4e00\u4e2a",
+ "sentA": "\u53d1\u9001\u4e86\u4e00\u4e2a",
+ "followed": "\u5df2\u5173\u6ce8",
+ "mentioned": "\u63d0\u53ca\u4e86",
"you": "\u4f60",
- "yourApplication": "\u60a8\u7684\u52a0\u5165\u7533\u8acb",
- "applicationApproved": "\u88ab\u6279\u51c6\u4e86\uff01",
- "applicationRejected": "\u88ab\u62d2\u7d55\u3002\u60a8\u53ef\u4ee5\u5728 6 \u500b\u6708\u5f8c\u518d\u6b21\u7533\u8acb\u52a0\u5165\u3002",
- "dm": "\u76f4\u63a5\u8a0a\u606f",
- "groupPost": "group post",
- "modlog": "modlog",
- "post": "post",
- "story": "story",
- "noneFound": "No notifications found"
+ "yourApplication": "\u60a8\u60f3\u8981\u52a0\u5165",
+ "applicationApproved": "\u7684\u7533\u8bf7\u88ab\u6279\u51c6\u4e86\uff01",
+ "applicationRejected": "\u7684\u7533\u8bf7\u88ab\u62d2\u7edd\u3002\u60a8\u53ef\u4ee5\u5728 6 \u4e2a\u6708\u540e\u91cd\u65b0\u7533\u8bf7\u52a0\u5165\u3002",
+ "dm": "\u79c1\u4fe1",
+ "groupPost": "\u7fa4\u7ec4\u8d34\u6587",
+ "modlog": "\u7ba1\u7406\u65e5\u5fd7",
+ "post": "\u5e16\u6587",
+ "story": "\u6545\u4e8b",
+ "noneFound": "\u6682\u65e0\u901a\u77e5"
},
"post": {
- "shareToFollowers": "Share to followers",
- "shareToOther": "Share to other",
- "noLikes": "No likes yet",
- "uploading": "\u4e0a\u50b3\u4e2d"
+ "shareToFollowers": "\u5206\u4eab\u7ed9\u5173\u6ce8\u8005",
+ "shareToOther": "\u4e0e\u4ed6\u4eba\u5206\u4eab",
+ "noLikes": "\u5c1a\u65e0\u70b9\u8d5e",
+ "uploading": "\u4e0a\u4f20\u4e2d"
},
"profile": {
- "posts": "Posts",
- "followers": "\u8ddf\u96a8\u8005",
- "following": "\u8ffd\u8e64\u4e2d",
- "admin": "\u7ba1\u7406\u54e1",
- "collections": "Collections",
- "follow": "\u8ffd\u8e64",
- "unfollow": "\u53d6\u6d88\u8ffd\u8e64",
- "editProfile": "\u7de8\u8f2f\u500b\u4eba\u6a94\u6848",
- "followRequested": "\u8ffd\u8e64\u8acb\u6c42",
- "joined": "Joined",
- "emptyCollections": "We can't seem to find any collections",
- "emptyPosts": "We can't seem to find any posts"
+ "posts": "\u5e16\u5b50",
+ "followers": "\u5173\u6ce8\u8005",
+ "following": "\u6b63\u5728\u5173\u6ce8",
+ "admin": "\u7ba1\u7406\u5458",
+ "collections": "\u5f71\u96c6",
+ "follow": "\u5173\u6ce8",
+ "unfollow": "\u53d6\u6d88\u5173\u6ce8",
+ "editProfile": "\u7f16\u8f91\u4e2a\u4eba\u8d44\u6599",
+ "followRequested": "\u5df2\u53d1\u9001\u5173\u6ce8\u8bf7\u6c42",
+ "joined": "\u5df2\u52a0\u5165",
+ "emptyCollections": "\u6211\u4eec\u4f3c\u4e4e\u627e\u4e0d\u5230\u4efb\u4f55\u5f71\u96c6",
+ "emptyPosts": "\u6211\u4eec\u4f3c\u4e4e\u672a\u80fd\u627e\u5230\u4efb\u4f55\u5e16\u6587"
},
"menu": {
- "viewPost": "View Post",
- "viewProfile": "View Profile",
- "moderationTools": "Moderation Tools",
- "report": "\u6aa2\u8209",
+ "viewPost": "\u67e5\u770b\u5e16\u6587",
+ "viewProfile": "\u67e5\u770b\u4e2a\u4eba\u8d44\u6599",
+ "moderationTools": "\u7ba1\u7406\u5de5\u5177",
+ "report": "\u4e3e\u62a5",
"archive": "\u5c01\u5b58",
"unarchive": "\u53d6\u6d88\u5c01\u5b58",
"embed": "\u5d4c\u5165",
- "selectOneOption": "\u9078\u64c7\u4ee5\u4e0b\u9078\u9805\u4e4b\u4e00",
- "unlistFromTimelines": "\u4e0d\u5728\u6642\u9593\u8ef8\u4e2d\u4e0a\u986f\u793a",
- "addCW": "\u589e\u52a0\u5167\u5bb9\u8b66\u544a",
- "removeCW": "\u79fb\u9664\u5167\u5bb9\u8b66\u544a",
- "markAsSpammer": "\u6a19\u8a18\u70ba\u5783\u573e\u8a0a\u606f\u4f86\u6e90\u8005",
- "markAsSpammerText": "\u5c0d\u8a08\u6709\u53ca\u672a\u4f86\u8cbc\u6587\u8a2d\u5b9a\u6210\u4e0d\u5217\u51fa\u548c\u589e\u52a0\u5167\u5bb9\u8b66\u544a",
- "spam": "\u5783\u573e\u8a0a\u606f",
- "sensitive": "\u654f\u611f\u5167\u5bb9",
- "abusive": "\u8fb1\u7f75\u6216\u6709\u5bb3",
- "underageAccount": "\u672a\u6210\u5e74\u5e33\u865f",
- "copyrightInfringement": "\u4fb5\u72af\u7248\u6b0a",
- "impersonation": "\u5047\u5192\u5e33\u865f",
- "scamOrFraud": "\u8a50\u9a19\u5167\u5bb9",
- "confirmReport": "\u78ba\u8a8d\u6aa2\u8209",
- "confirmReportText": "\u4f60\u78ba\u5b9a\u8981\u6aa2\u8209\u9019\u7bc7\u8cbc\u6587\uff1f",
- "reportSent": "\u6aa2\u8209\u5df2\u9001\u51fa\uff01",
- "reportSentText": "\u6211\u5011\u5df2\u7d93\u6536\u5230\u4f60\u7684\u6aa2\u8209\u3002",
- "reportSentError": "\u6aa2\u8209\u6b64\u8cbc\u6587\u6642\u51fa\u73fe\u554f\u984c\u3002",
- "modAddCWConfirm": "\u60a8\u78ba\u5b9a\u8981\u70ba\u6b64\u8cbc\u6587\u6dfb\u52a0\u5167\u5bb9\u8b66\u544a\u55ce\uff1f",
- "modCWSuccess": "\u6210\u529f\u6dfb\u52a0\u5167\u5bb9\u8b66\u544a",
- "modRemoveCWConfirm": "\u60a8\u78ba\u5b9a\u8981\u522a\u9664\u6b64\u8cbc\u6587\u4e0a\u7684\u5167\u5bb9\u8b66\u544a\u55ce\uff1f",
- "modRemoveCWSuccess": "\u5df2\u6210\u529f\u522a\u9664\u5167\u5bb9\u8b66\u544a",
- "modUnlistConfirm": "Are you sure you want to unlist this post?",
- "modUnlistSuccess": "Successfully unlisted post",
- "modMarkAsSpammerConfirm": "\u60a8\u78ba\u5b9a\u8981\u5c07\u6b64\u4f7f\u7528\u8005\u6a19\u8a18\u70ba\u5783\u573e\u8a0a\u606f\u767c\u9001\u8005\u55ce\uff1f\u6240\u6709\u73fe\u6709\u548c\u672a\u4f86\u7684\u8cbc\u6587\u5c07\u6539\u70ba\u975e\u516c\u958b\uff0c\u4e26\u5c07\u52a0\u4e0a\u5167\u5bb9\u8b66\u544a\u3002",
- "modMarkAsSpammerSuccess": "\u5df2\u6210\u529f\u5c07\u5e33\u6236\u6a19\u8a18\u70ba\u5783\u573e\u8a0a\u606f\u767c\u9001\u8005",
- "toFollowers": "\u7d66\u95dc\u6ce8\u8005",
- "showCaption": "\u986f\u793a\u6587\u5b57\u8aaa\u660e",
- "showLikes": "\u986f\u793a\u559c\u6b61",
- "compactMode": "\u7dca\u6e4a\u6a21\u5f0f",
- "embedConfirmText": "\u4f7f\u7528\u6b64\u5d4c\u5165\u5f0f\u5167\u5bb9\u5373\u8868\u793a\u60a8\u540c\u610f\u6211\u5011\u7684",
- "deletePostConfirm": "\u4f60\u78ba\u5b9a\u8981\u522a\u9664\u6b64\u8cbc\u6587\uff1f",
- "archivePostConfirm": "\u60a8\u78ba\u5b9a\u8981\u5c01\u5b58\u6b64\u8cbc\u6587\u55ce\uff1f",
- "unarchivePostConfirm": "\u60a8\u78ba\u5b9a\u8981\u89e3\u9664\u5c01\u5b58\u6b64\u8cbc\u6587\u55ce\uff1f"
+ "selectOneOption": "\u8bf7\u4ece\u4e0b\u5217\u9009\u9879\u4e2d\u9009\u62e9\u4e00\u4e2a",
+ "unlistFromTimelines": "\u4ece\u65f6\u95f4\u7ebf\u4e2d\u9690\u85cf",
+ "addCW": "\u6dfb\u52a0\u5185\u5bb9\u8b66\u544a",
+ "removeCW": "\u79fb\u9664\u5185\u5bb9\u8b66\u544a",
+ "markAsSpammer": "\u6807\u8bb0\u4e3a\u9a9a\u6270\u4fe1\u606f\u53d1\u9001\u8005",
+ "markAsSpammerText": "\u5c06\u6240\u6709\u76ee\u524d\u53ca\u672a\u6765\u7684\u5e16\u5b50\u9690\u85cf\u5e76\u6dfb\u52a0\u5185\u5bb9\u8b66\u544a",
+ "spam": "\u9a9a\u6270\u4fe1\u606f",
+ "sensitive": "\u654f\u611f\u5185\u5bb9",
+ "abusive": "\u6076\u610f\u6216\u6709\u5bb3\u7684",
+ "underageAccount": "\u672a\u6210\u5e74\u8d26\u6237",
+ "copyrightInfringement": "\u7248\u6743\u4fb5\u72af",
+ "impersonation": "\u5192\u5145\u4ed6\u4eba",
+ "scamOrFraud": "\u9a9a\u6270\u6216\u6b3a\u8bc8\u884c\u4e3a",
+ "confirmReport": "\u786e\u8ba4\u4e3e\u62a5",
+ "confirmReportText": "\u60a8\u786e\u5b9a\u8981\u4e3e\u62a5\u8fd9\u7bc7\u5e16\u6587\u5417\uff1f",
+ "reportSent": "\u4e3e\u62a5\u5df2\u53d1\u9001\uff01",
+ "reportSentText": "\u6211\u4eec\u5df2\u6210\u529f\u6536\u5230\u60a8\u7684\u4e3e\u62a5\u3002",
+ "reportSentError": "\u4e3e\u62a5\u8fd9\u4e2a\u5e16\u5b50\u65f6\u51fa\u73b0\u95ee\u9898\u3002",
+ "modAddCWConfirm": "\u60a8\u786e\u5b9a\u8981\u4e3a\u8fd9\u4e2a\u5e16\u6587\u6dfb\u52a0\u5185\u5bb9\u8b66\u544a\uff1f",
+ "modCWSuccess": "\u5185\u5bb9\u8b66\u544a\u5df2\u6210\u529f\u6dfb\u52a0",
+ "modRemoveCWConfirm": "\u60a8\u786e\u5b9a\u8981\u79fb\u9664\u8fd9\u4e2a\u5e16\u6587\u4e0a\u7684\u5185\u5bb9\u8b66\u544a\u5417\uff1f",
+ "modRemoveCWSuccess": "\u5185\u5bb9\u8b66\u544a\u5df2\u88ab\u6210\u529f\u79fb\u9664",
+ "modUnlistConfirm": "\u60a8\u786e\u5b9a\u8981\u9690\u85cf\u8fd9\u4e2a\u5e16\u6587\u5417\uff1f",
+ "modUnlistSuccess": "\u5e16\u6587\u5df2\u88ab\u6210\u529f\u9690\u85cf",
+ "modMarkAsSpammerConfirm": "\u60a8\u786e\u5b9a\u8981\u5c06\u6b64\u7528\u6237\u6807\u8bb0\u4e3a\u5783\u573e\u4fe1\u606f\u53d1\u9001\u8005\uff1f\u6240\u6709\u6b64\u7528\u6237\u7684\u73b0\u6709\u548c\u672a\u6765\u7684\u5e16\u5b50\u90fd\u5c06\u88ab\u9690\u85cf\uff0c\u5e76\u6dfb\u52a0\u5185\u5bb9\u8b66\u544a\u3002",
+ "modMarkAsSpammerSuccess": "\u6210\u529f\u5730\u5c06\u5e10\u6237\u6807\u8bb0\u4e3a\u5783\u573e\u4fe1\u606f\u53d1\u9001\u8005",
+ "toFollowers": "\u81f3\u5173\u6ce8\u8005",
+ "showCaption": "\u663e\u793a\u6807\u9898",
+ "showLikes": "\u663e\u793a\u70b9\u8d5e",
+ "compactMode": "\u7d27\u51d1\u6a21\u5f0f",
+ "embedConfirmText": "\u4f7f\u7528\u8fd9\u6bb5\u5d4c\u5165\u5185\u5bb9\u4ee3\u8868\u60a8\u5c06\u540c\u610f\u6211\u4eec\u7684",
+ "deletePostConfirm": "\u60a8\u786e\u5b9a\u8981\u5220\u9664\u8be5\u8d34\u5417\uff1f",
+ "archivePostConfirm": "\u60a8\u786e\u5b9a\u8981\u5c01\u5b58\u6b64\u8d34\u6587\u5417\uff1f",
+ "unarchivePostConfirm": "\u60a8\u786e\u5b9a\u8981\u53d6\u6d88\u5c01\u5b58\u6b64\u8d34\u6587\u5417\uff1f"
},
"story": {
- "add": "\u65b0\u589e\u6545\u4e8b"
+ "add": "\u6dfb\u52a0\u6545\u4e8b"
},
"timeline": {
- "peopleYouMayKnow": "\u4f60\u53ef\u80fd\u8a8d\u8b58",
+ "peopleYouMayKnow": "\u60a8\u53ef\u80fd\u8ba4\u8bc6\u7684\u4eba",
"onboarding": {
- "welcome": "\u6b61\u8fce",
- "thisIsYourHomeFeed": "This is your home feed, a chronological feed of posts from accounts you follow.",
- "letUsHelpYouFind": "Let us help you find some interesting people to follow",
- "refreshFeed": "\u66f4\u65b0\u6211\u7684\u6e90"
+ "welcome": "\u6b22\u8fce",
+ "thisIsYourHomeFeed": "\u8fd9\u662f\u4f60\u7684\u4e3b\u9875\u65f6\u95f4\u7ebf\uff0c\u5b83\u4f1a\u6309\u65f6\u95f4\u987a\u5e8f\u6392\u5217\u4f60\u6240\u5173\u6ce8\u7684\u8d26\u6237\u7684\u5e16\u5b50\u3002",
+ "letUsHelpYouFind": "\u8ba9\u6211\u4eec\u5e2e\u4f60\u627e\u4e00\u4e9b\u6709\u8da3\u7684\u4eba\u6765\u5173\u6ce8",
+ "refreshFeed": "\u5237\u65b0\u52a8\u6001\u5217\u8868"
}
},
"hashtags": {
- "emptyFeed": "\u6211\u5011\u4f3c\u4e4e\u627e\u4e0d\u5230\u6b64\u4e3b\u984c\u6a19\u7c64\u7684\u4efb\u4f55\u8cbc\u6587"
+ "emptyFeed": "\u6211\u4eec\u4f3c\u4e4e\u627e\u4e0d\u5230\u8fd9\u4e2a\u6807\u7b7e\u7684\u4efb\u4f55\u5e16\u5b50"
},
"report": {
- "report": "\u6aa2\u8209",
- "selectReason": "\u9078\u64c7\u4e00\u500b\u7406\u7531",
- "reported": "\u5df2\u6aa2\u8209",
- "sendingReport": "\u9001\u51fa\u6aa2\u8209",
- "thanksMsg": "\u611f\u8b1d\u4f60\u7684\u6aa2\u8209\u8b93\u4e16\u754c\u66f4\u7f8e\u597d\uff01",
- "contactAdminMsg": "\u5982\u679c\u4f60\u60f3\u8981\u63d0\u4f9b\u66f4\u591a\u6709\u95dc\u672c\u6b21\u6aa2\u8209\u7684\u5167\u5bb9\u7d66\u7ba1\u7406\u54e1"
+ "report": "\u4e3e\u62a5",
+ "selectReason": "\u9009\u62e9\u7406\u7531",
+ "reported": "\u5df2\u4e3e\u62a5",
+ "sendingReport": "\u6b63\u5728\u63d0\u4ea4\u4e3e\u62a5",
+ "thanksMsg": "\u611f\u8c22\u4f60\u7684\u4e3e\u62a5\uff0c\u8fd9\u6709\u52a9\u4e8e\u7ef4\u62a4\u6211\u4eec\u793e\u533a\u7684\u5b89\u5168\uff01",
+ "contactAdminMsg": "\u5982\u679c\u4f60\u60f3\u5c31\u8fd9\u4e2a\u5e16\u5b50\u8054\u7cfb\u7ba1\u7406\u5458\u6216\u7ba1\u7406\u5458\u4e3e\u62a5"
}
}
\ No newline at end of file
diff --git a/public/js/app.js b/public/js/app.js
index 0b9432931..bc808462e 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -1,2 +1,2 @@
/*! For license information please see app.js.LICENSE.txt */
-(self.webpackChunkpixelfed=self.webpackChunkpixelfed||[]).push([[5847],{7640:(e,t,o)=>{"use strict";o.r(t)},9901:function(){function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}!function(){var t="object"===("undefined"==typeof window?"undefined":e(window))?window:"object"===("undefined"==typeof self?"undefined":e(self))?self:this,o=t.BlobBuilder||t.WebKitBlobBuilder||t.MSBlobBuilder||t.MozBlobBuilder;t.URL=t.URL||t.webkitURL||function(e,t){return(t=document.createElement("a")).href=e,t};var r=t.Blob,a=URL.createObjectURL,n=URL.revokeObjectURL,s=t.Symbol&&t.Symbol.toStringTag,i=!1,c=!1,u=!!t.ArrayBuffer,d=o&&o.prototype.append&&o.prototype.getBlob;try{i=2===new Blob(["ä"]).size,c=2===new Blob([new Uint8Array([1,2])]).size}catch(e){}function p(e){return e.map((function(e){if(e.buffer instanceof ArrayBuffer){var t=e.buffer;if(e.byteLength!==t.byteLength){var o=new Uint8Array(e.byteLength);o.set(new Uint8Array(t,e.byteOffset,e.byteLength)),t=o.buffer}return t}return e}))}function f(e,t){t=t||{};var r=new o;return p(e).forEach((function(e){r.append(e)})),t.type?r.getBlob(t.type):r.getBlob()}function m(e,t){return new r(p(e),t||{})}t.Blob&&(f.prototype=Blob.prototype,m.prototype=Blob.prototype);var h="function"==typeof TextEncoder?TextEncoder.prototype.encode.bind(new TextEncoder):function(e){for(var o=0,r=e.length,a=t.Uint8Array||Array,n=0,s=Math.max(32,r+(r>>1)+7),i=new a(s>>3<<3);o=55296&&l<=56319){if(o=55296&&l<=56319)continue}if(n+4>i.length){s+=8,s=(s*=1+o/e.length*2)>>3<<3;var u=new Uint8Array(s);u.set(i),i=u}if(4294967168&l){if(4294965248&l)if(4294901760&l){if(4292870144&l)continue;i[n++]=l>>18&7|240,i[n++]=l>>12&63|128,i[n++]=l>>6&63|128}else i[n++]=l>>12&15|224,i[n++]=l>>6&63|128;else i[n++]=l>>6&31|192;i[n++]=63&l|128}else i[n++]=l}return i.slice(0,n)},y="function"==typeof TextDecoder?TextDecoder.prototype.decode.bind(new TextDecoder):function(e){for(var t=e.length,o=[],r=0;r239?4:l>223?3:l>191?2:1;if(r+u<=t)switch(u){case 1:l<128&&(c=l);break;case 2:128==(192&(a=e[r+1]))&&(i=(31&l)<<6|63&a)>127&&(c=i);break;case 3:a=e[r+1],n=e[r+2],128==(192&a)&&128==(192&n)&&(i=(15&l)<<12|(63&a)<<6|63&n)>2047&&(i<55296||i>57343)&&(c=i);break;case 4:a=e[r+1],n=e[r+2],s=e[r+3],128==(192&a)&&128==(192&n)&&128==(192&s)&&(i=(15&l)<<18|(63&a)<<12|(63&n)<<6|63&s)>65535&&i<1114112&&(c=i)}null===c?(c=65533,u=1):c>65535&&(c-=65536,o.push(c>>>10&1023|55296),c=56320|1023&c),o.push(c),r+=u}var d=o.length,p="";for(r=0;r>2,u=(3&a)<<4|s>>4,d=(15&s)<<2|l>>6,p=63&l;i||(p=64,n||(d=64)),o.push(t[c],t[u],t[d],t[p])}return o.join("")}var r=Object.create||function(e){function t(){}return t.prototype=e,new t};if(u)var s=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],i=ArrayBuffer.isView||function(e){return e&&s.indexOf(Object.prototype.toString.call(e))>-1};function c(o,r){r=null==r?{}:r;for(var a=0,n=(o=o||[]).length;a=t.size&&o.close()}))}})}}catch(e){try{new ReadableStream({}),b=function(e){var t=0;e=this;return new ReadableStream({pull:function(o){return e.slice(t,t+524288).arrayBuffer().then((function(r){t+=r.byteLength;var a=new Uint8Array(r);o.enqueue(a),t==e.size&&o.close()}))}})}}catch(e){try{new Response("").body.getReader().read(),b=function(){return new Response(this).body}}catch(e){b=function(){throw new Error("Include https://github.com/MattiasBuelens/web-streams-polyfill")}}}}v.arrayBuffer||(v.arrayBuffer=function(){var e=new FileReader;return e.readAsArrayBuffer(this),w(e)}),v.text||(v.text=function(){var e=new FileReader;return e.readAsText(this),w(e)}),v.stream||(v.stream=b)}(),function(e){"use strict";var t,o=e.Uint8Array,r=e.HTMLCanvasElement,a=r&&r.prototype,n=/\s*;\s*base64\s*(?:;|$)/i,s="toDataURL",i=function(e){for(var r,a,n=e.length,s=new o(n/4*3|0),i=0,l=0,c=[0,0],u=0,d=0;n--;)a=e.charCodeAt(i++),255!==(r=t[a-43])&&undefined!==r&&(c[1]=c[0],c[0]=a,d=d<<6|r,4===++u&&(s[l++]=d>>>16,61!==c[1]&&(s[l++]=d>>>8),61!==c[0]&&(s[l++]=d),u=0));return s};o&&(t=new o([62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,0,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51])),!r||a.toBlob&&a.toBlobHD||(a.toBlob||(a.toBlob=function(e,t){if(t||(t="image/png"),this.mozGetAsFile)e(this.mozGetAsFile("canvas",t));else if(this.msToBlob&&/^\s*image\/png\s*(?:$|;)/i.test(t))e(this.msToBlob());else{var r,a=Array.prototype.slice.call(arguments,1),l=this[s].apply(this,a),c=l.indexOf(","),u=l.substring(c+1),d=n.test(l.substring(0,c));Blob.fake?((r=new Blob).encoding=d?"base64":"URI",r.data=u,r.size=u.length):o&&(r=d?new Blob([i(u)],{type:t}):new Blob([decodeURIComponent(u)],{type:t})),e(r)}}),!a.toBlobHD&&a.toDataURLHD?a.toBlobHD=function(){s="toDataURLHD";var e=this.toBlob();return s="toDataURL",e}:a.toBlobHD=a.toBlob)}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content||this)},51595:(e,t,o)=>{"use strict";o.r(t)},55994:(e,t,o)=>{"use strict";o.r(t)},57048:e=>{"use strict";e.exports=JSON.parse('{"common":{"comment":"Comment","commented":"Commented","comments":"Comments","like":"Like","liked":"Liked","likes":"Likes","share":"Share","shared":"Shared","shares":"Shares","unshare":"Unshare","bookmark":"Bookmark","cancel":"Cancel","copyLink":"Copy Link","delete":"Delete","error":"Error","errorMsg":"Something went wrong. Please try again later.","oops":"Oops!","other":"Other","readMore":"Read more","success":"Success","proceed":"Proceed","next":"Next","close":"Close","clickHere":"click here","sensitive":"Sensitive","sensitiveContent":"Sensitive Content","sensitiveContentWarning":"This post may contain sensitive content"},"site":{"terms":"Terms of Use","privacy":"Privacy Policy"},"navmenu":{"search":"Search","admin":"Admin Dashboard","homeFeed":"Home Feed","localFeed":"Local Feed","globalFeed":"Global Feed","discover":"Discover","directMessages":"Direct Messages","notifications":"Notifications","groups":"Groups","stories":"Stories","profile":"Profile","drive":"Drive","settings":"Settings","appearance":"Appearance","compose":"Create New","logout":"Logout","about":"About","help":"Help","language":"Language","privacy":"Privacy","terms":"Terms","backToPreviousDesign":"Go back to previous design"},"directMessages":{"inbox":"Inbox","sent":"Sent","requests":"Requests"},"notifications":{"title":"Notifications","liked":"liked your","commented":"commented on your","reacted":"reacted to your","shared":"shared your","tagged":"tagged you in a","updatedA":"updated a","sentA":"sent a","followed":"followed","mentioned":"mentioned","you":"you","yourApplication":"Your application to join","applicationApproved":"was approved!","applicationRejected":"was rejected. You can re-apply to join in 6 months.","dm":"dm","groupPost":"group post","modlog":"modlog","post":"post","story":"story","noneFound":"No notifications found","youRecent":"You recent","hasUnlisted":"has been unlisted","cannotDisplay":"We cannot display this notification at this time.","followRequest":"Follow Requests","filteringResults":"Filtering results may not include older notifications","mentions":"Mentions","mentionsDescription":"Replies to your posts and posts you were mentioned in","likes":"Likes","likesDescription":"Accounts that liked your posts","followers":"Followers","followersDescription":"Accounts that followed you","reblogs":"Reblogs","reblogsDescription":"Accounts that shared or reblogged your posts","dms":"DMs","dmsDescription":"Direct messages you have with other accounts","accept":"Accept","reject":"Reject"},"post":{"shareToFollowers":"Share to followers","shareToOther":"Share to other","noLikes":"No likes yet","uploading":"Uploading"},"profile":{"posts":"Posts","followers":"Followers","following":"Following","admin":"Admin","collections":"Collections","follow":"Follow","unfollow":"Unfollow","editProfile":"Edit Profile","followRequested":"Follow Requested","joined":"Joined","emptyCollections":"We can\'t seem to find any collections","emptyPosts":"We can\'t seem to find any posts","blocking":"You are blocking this account","sponsor":"Donate","followYou":"Follows You","archives":"Archives","bookmarks":"Bookmarks","likes":"Likes","muted":"Muted","blocked":"Blocked","myPortifolio":"My Portfolio","private":"This profile is private","public":"Public","draft":"Draft","emptyLikes":"We can\'t seem to find any posts you have liked","emptyBookmarks":"We can\'t seem to find any posts you have bookmarked","emptyArchives":"We can\'t seem to find any archived posts","untitled":"Untitled","noDescription":"No description available"},"menu":{"viewPost":"View Post","viewProfile":"View Profile","moderationTools":"Moderation Tools","report":"Report","archive":"Archive","unarchive":"Unarchive","embed":"Embed","selectOneOption":"Select one of the following options","unlistFromTimelines":"Unlist from Timelines","addCW":"Add Content Warning","removeCW":"Remove Content Warning","markAsSpammer":"Mark as Spammer","markAsSpammerText":"Unlist + CW existing and future posts","spam":"Spam","sensitive":"Sensitive Content","abusive":"Abusive or Harmful","underageAccount":"Underage Account","copyrightInfringement":"Copyright Infringement","impersonation":"Impersonation","scamOrFraud":"Scam or Fraud","confirmReport":"Confirm Report","confirmReportText":"Are you sure you want to report this post?","reportSent":"Report Sent!","reportSentText":"We have successfully received your report.","reportSentError":"There was an issue reporting this post.","modAddCWConfirm":"Are you sure you want to add a content warning to this post?","modCWSuccess":"Successfully added content warning","modRemoveCWConfirm":"Are you sure you want to remove the content warning on this post?","modRemoveCWSuccess":"Successfully removed content warning","modUnlistConfirm":"Are you sure you want to unlist this post?","modUnlistSuccess":"Successfully unlisted post","modMarkAsSpammerConfirm":"Are you sure you want to mark this user as a spammer? All existing and future posts will be unlisted on timelines and a content warning will be applied.","modMarkAsSpammerSuccess":"Successfully marked account as spammer","toFollowers":"to Followers","showCaption":"Show Caption","showLikes":"Show Likes","compactMode":"Compact Mode","embedConfirmText":"By using this embed, you agree to our","deletePostConfirm":"Are you sure you want to delete this post?","archivePostConfirm":"Are you sure you want to archive this post?","unarchivePostConfirm":"Are you sure you want to unarchive this post?","pin":"Pin","unpin":"Unpin","pinPostConfirm":"Are you sure you want to pin this post?","unpinPostConfirm":"Are you sure you want to unpin this post?"},"story":{"add":"Add Story"},"timeline":{"peopleYouMayKnow":"People you may know","onboarding":{"welcome":"Welcome","thisIsYourHomeFeed":"This is your home feed, a chronological feed of posts from accounts you follow.","letUsHelpYouFind":"Let us help you find some interesting people to follow","refreshFeed":"Refresh my feed"}},"hashtags":{"emptyFeed":"We can\'t seem to find any posts for this hashtag"},"report":{"report":"Report","selectReason":"Select a reason","reported":"Reported","sendingReport":"Sending report","thanksMsg":"Thanks for the report, people like you help keep our community safe!","contactAdminMsg":"If you\'d like to contact an administrator about this post or report"},"appearance":{"theme":"Theme","profileLayout":"Profile Layout","compactPreviews":"Compact Media Previews","loadComments":"Load Comments","hideStats":"Hide Counts & Stats","auto":"Auto","lightMode":"Light mode","darkMode":"Dark mode","grid":"Grid","masonry":"Masonry","feed":"Feed"}}')},71751:(e,t,o)=>{"use strict";o.r(t);var r=o(64765),a=(o(74692),o(74692));o(9901),window._=o(2543),window.Popper=o(48851).default,window.pixelfed=window.pixelfed||{},window.$=o(74692),o(52754),window.axios=o(86425),window.axios.defaults.headers.common["X-Requested-With"]="XMLHttpRequest",o(63899),window.blurhash=o(95341);var n=document.head.querySelector('meta[name="csrf-token"]');n?window.axios.defaults.headers.common["X-CSRF-TOKEN"]=n.content:console.error("CSRF token not found."),window.App=window.App||{},window.App.redirect=function(){document.querySelectorAll("a").forEach((function(e,t){var o=e.getAttribute("href");if(o&&o.length>5&&o.startsWith("https://")){var r=new URL(o);r.host!==window.location.host&&"/i/redirect"!==r.pathname&&e.setAttribute("href","/i/redirect?url="+encodeURIComponent(o))}}))},window.App.boot=function(){Vue.use(r.default);var e={en:o(57048),pt:o(85147)},t=document.querySelector("html").getAttribute("lang"),a=new r.default({locale:t,fallbackLocale:"en",messages:e});new Vue({el:"#content",i18n:a})},window.addEventListener("load",(function(){"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js")})),window.App.util={compose:{post:function(){var e=window.location.pathname;["/","/timeline/public"].includes(e)?a("#composeModal").modal("show"):window.location.href="/?a=co"},circle:function(){console.log("Unsupported method.")},collection:function(){console.log("Unsupported method.")},loop:function(){console.log("Unsupported method.")},story:function(){console.log("Unsupported method.")}},time:function(){return new Date},version:1,format:{count:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"en-GB",o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"compact";return e<1?0:new Intl.NumberFormat(t,{notation:o,compactDisplay:"short"}).format(e)},timeAgo:function(e){var t=new Date(e),o=new Date,r=Math.floor((o-t)/1e3),a=Math.floor(r/31557600);return a>=1?a+"y":(a=Math.floor(r/604800))>=1?a+"w":(a=Math.floor(r/86400))>=1?a+"d":(a=Math.floor(r/3600))>=1?a+"h":(a=Math.floor(r/60))>=1?a+"m":Math.floor(r)+"s"},timeAhead:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],o=Date.parse(e)-Date.parse(new Date),r=Math.floor(o/1e3),a=Math.floor(r/63072e3);return a>=1?a+(t?"y":" years"):(a=Math.floor(r/604800))>=1?a+(t?"w":" weeks"):(a=Math.floor(r/86400))>=1?a+(t?"d":" days"):(a=Math.floor(r/3600))>=1?a+(t?"h":" hours"):(a=Math.floor(r/60))>=1?a+(t?"m":" minutes"):Math.floor(r)+(t?"s":" seconds")},rewriteLinks:function(e){var t=e.innerText;return e.href.startsWith(window.location.origin)?e.href:t=1==t.startsWith("#")?"/discover/tags/"+t.substr(1)+"?src=rph":1==t.startsWith("@")?"/"+e.innerText+"?src=rpp":"/i/redirect?url="+encodeURIComponent(t)}},filters:[["1984","filter-1977"],["Azen","filter-aden"],["Astairo","filter-amaro"],["Grassbee","filter-ashby"],["Bookrun","filter-brannan"],["Borough","filter-brooklyn"],["Farms","filter-charmes"],["Hairsadone","filter-clarendon"],["Cleana ","filter-crema"],["Catpatch","filter-dogpatch"],["Earlyworm","filter-earlybird"],["Plaid","filter-gingham"],["Kyo","filter-ginza"],["Yefe","filter-hefe"],["Goddess","filter-helena"],["Yards","filter-hudson"],["Quill","filter-inkwell"],["Rankine","filter-kelvin"],["Juno","filter-juno"],["Mark","filter-lark"],["Chill","filter-lofi"],["Van","filter-ludwig"],["Apache","filter-maven"],["May","filter-mayfair"],["Ceres","filter-moon"],["Knoxville","filter-nashville"],["Felicity","filter-perpetua"],["Sandblast","filter-poprocket"],["Daisy","filter-reyes"],["Elevate","filter-rise"],["Nevada","filter-sierra"],["Futura","filter-skyline"],["Sleepy","filter-slumber"],["Steward","filter-stinson"],["Savoy","filter-sutro"],["Blaze","filter-toaster"],["Apricot","filter-valencia"],["Gloming","filter-vesper"],["Walter","filter-walden"],["Poplar","filter-willow"],["Xenon","filter-xpro-ii"]],filterCss:{"filter-1977":"sepia(.5) hue-rotate(-30deg) saturate(1.4)","filter-aden":"sepia(.2) brightness(1.15) saturate(1.4)","filter-amaro":"sepia(.35) contrast(1.1) brightness(1.2) saturate(1.3)","filter-ashby":"sepia(.5) contrast(1.2) saturate(1.8)","filter-brannan":"sepia(.4) contrast(1.25) brightness(1.1) saturate(.9) hue-rotate(-2deg)","filter-brooklyn":"sepia(.25) contrast(1.25) brightness(1.25) hue-rotate(5deg)","filter-charmes":"sepia(.25) contrast(1.25) brightness(1.25) saturate(1.35) hue-rotate(-5deg)","filter-clarendon":"sepia(.15) contrast(1.25) brightness(1.25) hue-rotate(5deg)","filter-crema":"sepia(.5) contrast(1.25) brightness(1.15) saturate(.9) hue-rotate(-2deg)","filter-dogpatch":"sepia(.35) saturate(1.1) contrast(1.5)","filter-earlybird":"sepia(.25) contrast(1.25) brightness(1.15) saturate(.9) hue-rotate(-5deg)","filter-gingham":"contrast(1.1) brightness(1.1)","filter-ginza":"sepia(.25) contrast(1.15) brightness(1.2) saturate(1.35) hue-rotate(-5deg)","filter-hefe":"sepia(.4) contrast(1.5) brightness(1.2) saturate(1.4) hue-rotate(-10deg)","filter-helena":"sepia(.5) contrast(1.05) brightness(1.05) saturate(1.35)","filter-hudson":"sepia(.25) contrast(1.2) brightness(1.2) saturate(1.05) hue-rotate(-15deg)","filter-inkwell":"brightness(1.25) contrast(.85) grayscale(1)","filter-kelvin":"sepia(.15) contrast(1.5) brightness(1.1) hue-rotate(-10deg)","filter-juno":"sepia(.35) contrast(1.15) brightness(1.15) saturate(1.8)","filter-lark":"sepia(.25) contrast(1.2) brightness(1.3) saturate(1.25)","filter-lofi":"saturate(1.1) contrast(1.5)","filter-ludwig":"sepia(.25) contrast(1.05) brightness(1.05) saturate(2)","filter-maven":"sepia(.35) contrast(1.05) brightness(1.05) saturate(1.75)","filter-mayfair":"contrast(1.1) brightness(1.15) saturate(1.1)","filter-moon":"brightness(1.4) contrast(.95) saturate(0) sepia(.35)","filter-nashville":"sepia(.25) contrast(1.5) brightness(.9) hue-rotate(-15deg)","filter-perpetua":"contrast(1.1) brightness(1.25) saturate(1.1)","filter-poprocket":"sepia(.15) brightness(1.2)","filter-reyes":"sepia(.75) contrast(.75) brightness(1.25) saturate(1.4)","filter-rise":"sepia(.25) contrast(1.25) brightness(1.2) saturate(.9)","filter-sierra":"sepia(.25) contrast(1.5) brightness(.9) hue-rotate(-15deg)","filter-skyline":"sepia(.15) contrast(1.25) brightness(1.25) saturate(1.2)","filter-slumber":"sepia(.35) contrast(1.25) saturate(1.25)","filter-stinson":"sepia(.35) contrast(1.25) brightness(1.1) saturate(1.25)","filter-sutro":"sepia(.4) contrast(1.2) brightness(.9) saturate(1.4) hue-rotate(-10deg)","filter-toaster":"sepia(.25) contrast(1.5) brightness(.95) hue-rotate(-15deg)","filter-valencia":"sepia(.25) contrast(1.1) brightness(1.1)","filter-vesper":"sepia(.35) contrast(1.15) brightness(1.2) saturate(1.3)","filter-walden":"sepia(.35) contrast(.8) brightness(1.25) saturate(1.4)","filter-willow":"brightness(1.2) contrast(.85) saturate(.05) sepia(.2)","filter-xpro-ii":"sepia(.45) contrast(1.25) brightness(1.75) saturate(1.3) hue-rotate(-5deg)"},emoji:["😂","💯","❤️","🙌","👏","👌","😍","😯","😢","😅","😁","🙂","😎","😀","🤣","😃","😄","😆","😉","😊","😋","😘","😗","😙","😚","🤗","🤩","🤔","🤨","😐","😑","😶","🙄","😏","😣","😥","😮","🤐","😪","😫","😴","😌","😛","😜","😝","🤤","😒","😓","😔","😕","🙃","🤑","😲","🙁","😖","😞","😟","😤","😭","😦","😧","😨","😩","🤯","😬","😰","😱","😳","🤪","😵","😡","😠","🤬","😷","🤒","🤕","🤢","🤮","🤧","😇","🤠","🤡","🤥","🤫","🤭","🧐","🤓","😈","👿","👹","👺","💀","👻","👽","🤖","💩","😺","😸","😹","😻","😼","😽","🙀","😿","😾","🤲","👐","🤝","👍","👎","👊","✊","🤛","🤜","🤞","✌️","🤟","🤘","👈","👉","👆","👇","☝️","✋","🤚","🖐","🖖","👋","🤙","💪","🖕","✍️","🙏","💍","💄","💋","👄","👅","👂","👃","👣","👁","👀","🧠","🗣","👤","👥"],embed:{post:function(e){var t=e+"/embed?";return t+=!(arguments.length>1&&void 0!==arguments[1])||arguments[1]?"caption=true&":"caption=false&",t+=arguments.length>2&&void 0!==arguments[2]&&arguments[2]?"likes=true&":"likes=false&",'
diff --git a/resources/assets/components/partials/profile/ProfileSidebar.vue b/resources/assets/components/partials/profile/ProfileSidebar.vue
index 877b1f0ec..d245184e7 100644
--- a/resources/assets/components/partials/profile/ProfileSidebar.vue
+++ b/resources/assets/components/partials/profile/ProfileSidebar.vue
@@ -1,107 +1,123 @@
-
-
+
-
-
+
+
-
+
{{ profile.website }}
-
+
-
+
-
+
{{ $t('profile.joined') }} {{ getJoinedDate() }}
-
+
{{ $t('profile.joined') }} {{ getJoinedDate() }}
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/assets/components/partials/sidebar.vue b/resources/assets/components/partials/sidebar.vue
index 6e7933f0d..7997abb3c 100644
--- a/resources/assets/components/partials/sidebar.vue
+++ b/resources/assets/components/partials/sidebar.vue
@@ -1,24 +1,26 @@
-