diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b3551621..8d3a49de9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -125,8 +125,12 @@ - Updated CollectionController, limit unpublished collections to owner. ([a0061eb5](https://github.com/pixelfed/pixelfed/commit/a0061eb5)) - Updated AP Inbox, fixes #3332. ([f8931dc7](https://github.com/pixelfed/pixelfed/commit/f8931dc7)) - Updated AdminReportController, add account delete button. ([563817a9](https://github.com/pixelfed/pixelfed/commit/563817a9)) -- Updated ApiV1Controller, added /api/v2/media endpoint, fixes #3405 ([f07cc14c](https://github.com/pixelfed/pixelfed/commit/f07cc14c)) -- Updated AP fanout, added Content-Type and User-Agent for activity delivery ([@noellabo](https://github.com/noellabo)) ([209c125](https://github.com/pixelfed/pixelfed/commit/209c125)) +- Updated ApiV1Controller, added /api/v2/media endpoint, fixes #3405. ([f07cc14c](https://github.com/pixelfed/pixelfed/commit/f07cc14c)) +- Updated AP fanout, added Content-Type and User-Agent for activity delivery. ([@noellabo](https://github.com/noellabo)) ([209c125](https://github.com/pixelfed/pixelfed/commit/209c125)) +- Updated DirectMessageController to support new Metro 2.0 UI DMs. ([a4659fd2](https://github.com/pixelfed/pixelfed/commit/a4659fd2)) +- Updated Like model, bump max likes per day from 100 to 200. ([71ba5fed](https://github.com/pixelfed/pixelfed/commit/71ba5fed)) +- Updated HashtagService, use sorted set for followed tags. ([153eb6ba](https://github.com/pixelfed/pixelfed/commit/153eb6ba)) +- Updated Discover component, fixed post side effects (fixes #3409). ([fe5a92b2](https://github.com/pixelfed/pixelfed/commit/fe5a92b2)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.2 (2022-01-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.1...v0.11.2) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 888f61add..b7929f34c 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -1061,7 +1061,7 @@ class ApiV1Controller extends Controller abort_if( Like::whereProfileId($user->profile_id) ->where('created_at', '>', now()->subDay()) - ->count() >= 100, + ->count() >= Like::MAX_PER_DAY, 429 ); diff --git a/app/Http/Controllers/DirectMessageController.php b/app/Http/Controllers/DirectMessageController.php index 8b48f0ec5..8de1694f6 100644 --- a/app/Http/Controllers/DirectMessageController.php +++ b/app/Http/Controllers/DirectMessageController.php @@ -19,6 +19,8 @@ use App\Services\MediaBlocklistService; use App\Jobs\StatusPipeline\NewStatusPipeline; use Illuminate\Support\Str; use App\Util\ActivityPub\Helpers; +use App\Services\AccountService; +use App\Services\StatusService; use App\Services\WebfingerService; use App\Models\Conversation; @@ -435,8 +437,10 @@ class DirectMessageController extends Controller ->get(); } - - $res = $res->map(function($s) use ($uid){ + $res = $res->filter(function($s) { + return $s && $s->status; + }) + ->map(function($s) use ($uid) { return [ 'id' => (string) $s->id, 'hidden' => (bool) $s->is_hidden, @@ -449,7 +453,8 @@ class DirectMessageController extends Controller 'reportId' => (string) $s->status_id, 'meta' => json_decode($s->meta,true) ]; - }); + }) + ->values(); $w = [ 'id' => (string) $r->id, @@ -458,10 +463,10 @@ class DirectMessageController extends Controller 'avatar' => $r->avatarUrl(), 'url' => $r->url(), 'muted' => UserFilter::whereUserId($uid) - ->whereFilterableId($r->id) - ->whereFilterableType('App\Profile') - ->whereFilterType('dm.mute') - ->first() ? true : false, + ->whereFilterableId($r->id) + ->whereFilterableType('App\Profile') + ->whereFilterType('dm.mute') + ->first() ? true : false, 'isLocal' => (bool) !$r->domain, 'domain' => $r->domain, 'timeAgo' => $r->created_at->diffForHumans(null, true, true), @@ -482,17 +487,62 @@ class DirectMessageController extends Controller $pid = $request->user()->profile_id; $dm = DirectMessage::whereFromId($pid) - ->whereStatusId($sid) - ->firstOrFail(); + ->whereStatusId($sid) + ->firstOrFail(); $status = Status::whereProfileId($pid) - ->findOrFail($dm->status_id); + ->findOrFail($dm->status_id); - if($dm->recipient->domain) { + $recipient = AccountService::get($dm->to_id); + + if(!$recipient) { + return response('', 422); + } + + if($recipient['local'] == false) { $dmc = $dm; $this->remoteDelete($dmc); } + if(Conversation::whereStatusId($sid)->count()) { + $latest = DirectMessage::where(['from_id' => $dm->from_id, 'to_id' => $dm->to_id]) + ->orWhere(['to_id' => $dm->from_id, 'from_id' => $dm->to_id]) + ->latest() + ->first(); + + if($latest->status_id == $sid) { + Conversation::where(['to_id' => $dm->from_id, 'from_id' => $dm->to_id]) + ->update([ + 'updated_at' => $latest->updated_at, + 'status_id' => $latest->status_id, + 'type' => $latest->type, + 'is_hidden' => false + ]); + + Conversation::where(['to_id' => $dm->to_id, 'from_id' => $dm->from_id]) + ->update([ + 'updated_at' => $latest->updated_at, + 'status_id' => $latest->status_id, + 'type' => $latest->type, + 'is_hidden' => false + ]); + } else { + Conversation::where([ + 'status_id' => $sid, + 'to_id' => $dm->from_id, + 'from_id' => $dm->to_id + ])->delete(); + + Conversation::where([ + 'status_id' => $sid, + 'from_id' => $dm->from_id, + 'to_id' => $dm->to_id + ])->delete(); + } + } + + StatusService::del($status->id, true); + $status->delete(); $dm->delete(); diff --git a/app/Http/Controllers/DiscoverController.php b/app/Http/Controllers/DiscoverController.php index 2277e8ee9..d6e9f1338 100644 --- a/app/Http/Controllers/DiscoverController.php +++ b/app/Http/Controllers/DiscoverController.php @@ -16,7 +16,11 @@ use App\{ }; use Auth, DB, Cache; use Illuminate\Http\Request; +use App\Services\BookmarkService; use App\Services\ConfigCacheService; +use App\Services\HashtagService; +use App\Services\LikeService; +use App\Services\ReblogService; use App\Services\StatusHashtagService; use App\Services\SnowflakeService; use App\Services\StatusService; @@ -76,10 +80,8 @@ class DiscoverController extends Controller $tag = $request->input('hashtag'); $hashtag = Hashtag::whereName($tag)->firstOrFail(); - if($user && $page == 1) { - $res['follows'] = HashtagFollow::whereUserId($user->id) - ->whereHashtagId($hashtag->id) - ->exists(); + if($user) { + $res['follows'] = HashtagService::isFollowing($user->profile_id, $hashtag->id); } $res['hashtag'] = [ 'name' => $hashtag->name, @@ -88,6 +90,12 @@ class DiscoverController extends Controller if($user) { $tags = StatusHashtagService::get($hashtag->id, $page, $end); $res['tags'] = collect($tags) + ->map(function($tag) use($user) { + $tag['status']['favourited'] = (bool) LikeService::liked($user->profile_id, $tag['status']['id']); + $tag['status']['reblogged'] = (bool) ReblogService::get($user->profile_id, $tag['status']['id']); + $tag['status']['bookmarked'] = (bool) BookmarkService::get($user->profile_id, $tag['status']['id']); + return $tag; + }) ->filter(function($tag) { if(!StatusService::get($tag['status']['id'])) { return false; diff --git a/app/Http/Controllers/HashtagFollowController.php b/app/Http/Controllers/HashtagFollowController.php index 585248abb..4554bb963 100644 --- a/app/Http/Controllers/HashtagFollowController.php +++ b/app/Http/Controllers/HashtagFollowController.php @@ -9,6 +9,7 @@ use App\{ HashtagFollow, Status }; +use App\Services\HashtagService; class HashtagFollowController extends Controller { @@ -37,9 +38,11 @@ class HashtagFollowController extends Controller if($hashtagFollow->wasRecentlyCreated) { $state = 'created'; + HashtagService::follow($profile->id, $hashtag->id); // todo: send to HashtagFollowService } else { $state = 'deleted'; + HashtagService::unfollow($profile->id, $hashtag->id); $hashtagFollow->delete(); } diff --git a/app/Http/Controllers/LikeController.php b/app/Http/Controllers/LikeController.php index 8a56ae0e8..c17b61663 100644 --- a/app/Http/Controllers/LikeController.php +++ b/app/Http/Controllers/LikeController.php @@ -33,6 +33,12 @@ class LikeController extends Controller $like = Like::whereProfileId($profile->id)->whereStatusId($status->id)->firstOrFail(); UnlikePipeline::dispatch($like); } else { + abort_if( + Like::whereProfileId($user->profile_id) + ->where('created_at', '>', now()->subDay()) + ->count() >= Like::MAX_PER_DAY, + 429 + ); $count = $status->likes_count > 4 ? $status->likes_count : $status->likes()->count(); $like = Like::firstOrCreate([ 'profile_id' => $user->profile_id, diff --git a/app/Jobs/StoryPipeline/StoryFanout.php b/app/Jobs/StoryPipeline/StoryFanout.php index 12f37cbf0..e34bdb23a 100644 --- a/app/Jobs/StoryPipeline/StoryFanout.php +++ b/app/Jobs/StoryPipeline/StoryFanout.php @@ -81,7 +81,6 @@ class StoryFanout implements ShouldQueue foreach($audience as $url) { $version = config('pixelfed.version'); $appUrl = config('app.url'); - $proxy = config(''); $headers = HttpSignature::sign($profile, $url, $activity, [ 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', 'User-Agent' => "(Pixelfed/{$version}; +{$appUrl})", diff --git a/app/Like.php b/app/Like.php index 8b45b60cb..678ce953f 100644 --- a/app/Like.php +++ b/app/Like.php @@ -9,6 +9,8 @@ class Like extends Model { use SoftDeletes; + const MAX_PER_DAY = 200; + /** * The attributes that should be mutated to dates. * diff --git a/app/Services/HashtagService.php b/app/Services/HashtagService.php index 6a40595d3..de58fae59 100644 --- a/app/Services/HashtagService.php +++ b/app/Services/HashtagService.php @@ -2,12 +2,16 @@ namespace App\Services; -use Cache; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Redis; use App\Hashtag; use App\StatusHashtag; +use App\HashtagFollow; class HashtagService { + const FOLLOW_KEY = 'pf:services:hashtag:following:'; + public static function get($id) { return Cache::remember('services:hashtag:by_id:' . $id, 3600, function() use($id) { @@ -29,4 +33,35 @@ class HashtagService { }); } + public static function isFollowing($pid, $hid) + { + $res = Redis::zscore(self::FOLLOW_KEY . $pid, $hid); + if($res) { + return true; + } + + $synced = Cache::get(self::FOLLOW_KEY . $pid . ':synced'); + if(!$synced) { + $tags = HashtagFollow::whereProfileId($pid) + ->get() + ->each(function($tag) use($pid) { + self::follow($pid, $tag->hashtag_id); + }); + Cache::set(self::FOLLOW_KEY . $pid . ':synced', true, 1209600); + + return (bool) Redis::zscore(self::FOLLOW_KEY . $pid, $hid) > 1; + } + + return false; + } + + public static function follow($pid, $hid) + { + return Redis::zadd(self::FOLLOW_KEY . $pid, $hid, $hid); + } + + public static function unfollow($pid, $hid) + { + return Redis::zrem(self::FOLLOW_KEY . $pid, $hid); + } } diff --git a/public/js/compose-0esirpejd.js b/public/js/compose-0esirpejd.js deleted file mode 100644 index 02538cd2f..000000000 Binary files a/public/js/compose-0esirpejd.js and /dev/null differ diff --git a/public/js/compose-nza92p6rg.js b/public/js/compose-nza92p6rg.js new file mode 100644 index 000000000..55241a1d8 Binary files /dev/null and b/public/js/compose-nza92p6rg.js differ diff --git a/public/js/daci-0esirpejd.js b/public/js/daci-0esirpejd.js deleted file mode 100644 index 44d78dc29..000000000 Binary files a/public/js/daci-0esirpejd.js and /dev/null differ diff --git a/public/js/daci-nza92p6rg.js b/public/js/daci-nza92p6rg.js new file mode 100644 index 000000000..09b161257 Binary files /dev/null and b/public/js/daci-nza92p6rg.js differ diff --git a/public/js/dffc-0esirpejd.js b/public/js/dffc-0esirpejd.js deleted file mode 100644 index fc3b1f36c..000000000 Binary files a/public/js/dffc-0esirpejd.js and /dev/null differ diff --git a/public/js/dffc-nza92p6rg.js b/public/js/dffc-nza92p6rg.js new file mode 100644 index 000000000..481875b82 Binary files /dev/null and b/public/js/dffc-nza92p6rg.js differ diff --git a/public/js/dmyh-0esirpejd.js b/public/js/dmyh-0esirpejd.js deleted file mode 100644 index 8d2f24918..000000000 Binary files a/public/js/dmyh-0esirpejd.js and /dev/null differ diff --git a/public/js/dmyh-nza92p6rg.js b/public/js/dmyh-nza92p6rg.js new file mode 100644 index 000000000..dbc23d430 Binary files /dev/null and b/public/js/dmyh-nza92p6rg.js differ diff --git a/public/js/dmym-0esirpejd.js b/public/js/dmym-0esirpejd.js deleted file mode 100644 index 13836e64a..000000000 Binary files a/public/js/dmym-0esirpejd.js and /dev/null differ diff --git a/public/js/dmym-nza92p6rg.js b/public/js/dmym-nza92p6rg.js new file mode 100644 index 000000000..be4091875 Binary files /dev/null and b/public/js/dmym-nza92p6rg.js differ diff --git a/public/js/dsfc-0esirpejd.js b/public/js/dsfc-0esirpejd.js deleted file mode 100644 index 89090ac86..000000000 Binary files a/public/js/dsfc-0esirpejd.js and /dev/null differ diff --git a/public/js/dsfc-nza92p6rg.js b/public/js/dsfc-nza92p6rg.js new file mode 100644 index 000000000..0b315b592 Binary files /dev/null and b/public/js/dsfc-nza92p6rg.js differ diff --git a/public/js/dssc-0esirpejd.js b/public/js/dssc-0esirpejd.js deleted file mode 100644 index 6159dc135..000000000 Binary files a/public/js/dssc-0esirpejd.js and /dev/null differ diff --git a/public/js/dssc-nza92p6rg.js b/public/js/dssc-nza92p6rg.js new file mode 100644 index 000000000..dcfe93afe Binary files /dev/null and b/public/js/dssc-nza92p6rg.js differ diff --git a/public/js/home-0esirpejd.js b/public/js/home-0esirpejd.js deleted file mode 100644 index 9d848bd57..000000000 Binary files a/public/js/home-0esirpejd.js and /dev/null differ diff --git a/public/js/home-nza92p6rg.js b/public/js/home-nza92p6rg.js new file mode 100644 index 000000000..3cd4eb5db Binary files /dev/null and b/public/js/home-nza92p6rg.js differ diff --git a/public/js/installer.js b/public/js/installer.js deleted file mode 100644 index 1c0b4aa2f..000000000 Binary files a/public/js/installer.js and /dev/null differ diff --git a/public/js/installer.js.LICENSE.txt b/public/js/installer.js.LICENSE.txt deleted file mode 100644 index ba8e2aeda..000000000 --- a/public/js/installer.js.LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -/*! @source http://purl.eligrey.com/github/canvas-toBlob.js/blob/master/canvas-toBlob.js */ diff --git a/public/js/manifest.js b/public/js/manifest.js index 99839a700..ec75bf142 100644 Binary files a/public/js/manifest.js and b/public/js/manifest.js differ diff --git a/public/js/post-0esirpejd.js b/public/js/post-0esirpejd.js deleted file mode 100644 index 07c6dae1a..000000000 Binary files a/public/js/post-0esirpejd.js and /dev/null differ diff --git a/public/js/post-nza92p6rg.js b/public/js/post-nza92p6rg.js new file mode 100644 index 000000000..1f53e7dd6 Binary files /dev/null and b/public/js/post-nza92p6rg.js differ diff --git a/public/js/profile-0esirpejd.js b/public/js/profile-0esirpejd.js deleted file mode 100644 index a727686a2..000000000 Binary files a/public/js/profile-0esirpejd.js and /dev/null differ diff --git a/public/js/profile-nza92p6rg.js b/public/js/profile-nza92p6rg.js new file mode 100644 index 000000000..9facdb0be Binary files /dev/null and b/public/js/profile-nza92p6rg.js differ diff --git a/public/js/spa.js b/public/js/spa.js index 0f8a15ff2..f2620406f 100644 Binary files a/public/js/spa.js and b/public/js/spa.js differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index b0d5fc607..e48565e5a 100644 Binary files a/public/mix-manifest.json and b/public/mix-manifest.json differ