Jelajahi Sumber

Update LikeController, add UndoLikePipeline and federate Undo Like activities

Daniel Supernault 4 tahun lalu
induk
melakukan
8ac8fcad3f

+ 3 - 5
app/Http/Controllers/LikeController.php

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers;
 
 use App\Jobs\LikePipeline\LikePipeline;
+use App\Jobs\LikePipeline\UnlikePipeline;
 use App\Like;
 use App\Status;
 use App\User;
@@ -28,15 +29,12 @@ class LikeController extends Controller
 		$profile = $user->profile;
 		$status = Status::findOrFail($request->input('item'));
 
-		$count = $status->likes()->count();
 
 		if ($status->likes()->whereProfileId($profile->id)->count() !== 0) {
 			$like = Like::whereProfileId($profile->id)->whereStatusId($status->id)->firstOrFail();
-			$like->forceDelete();
-			$count--;
-			$status->likes_count = $count;
-			$status->save();
+			UnlikePipeline::dispatch($like);
 		} else {
+			$count = $status->likes_count > 4 ? $status->likes_count : $status->likes()->count();
 			$like = Like::firstOrCreate([
 				'profile_id' => $user->profile_id,
 				'status_id' => $status->id

+ 109 - 0
app/Jobs/LikePipeline/UnlikePipeline.php

@@ -0,0 +1,109 @@
+<?php
+
+namespace App\Jobs\LikePipeline;
+
+use Cache, Log;
+use Illuminate\Support\Facades\Redis;
+use App\{Like, Notification};
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use App\Util\ActivityPub\Helpers;
+use League\Fractal;
+use League\Fractal\Serializer\ArraySerializer;
+use App\Transformer\ActivityPub\Verb\UndoLike as LikeTransformer;
+use App\Services\StatusService;
+
+class UnlikePipeline implements ShouldQueue
+{
+	use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+	protected $like;
+
+	/**
+	 * Delete the job if its models no longer exist.
+	 *
+	 * @var bool
+	 */
+	public $deleteWhenMissingModels = true;
+
+	public $timeout = 5;
+	public $tries = 1;
+
+	/**
+	 * Create a new job instance.
+	 *
+	 * @return void
+	 */
+	public function __construct(Like $like)
+	{
+		$this->like = $like;
+	}
+
+	/**
+	 * Execute the job.
+	 *
+	 * @return void
+	 */
+	public function handle()
+	{
+		$like = $this->like;
+
+		$status = $this->like->status;
+		$actor = $this->like->actor;
+
+		if (!$status) {
+			// Ignore notifications to deleted statuses
+			return;
+		}
+
+		$count = $status->likes_count > 1 ? $status->likes_count : $status->likes()->count();
+		$status->likes_count = $count - 1;
+		$status->save();
+
+		StatusService::del($status->id);
+
+		if($actor->id !== $status->profile_id && $status->url && $actor->domain == null) {
+			$this->remoteLikeDeliver();
+		}
+
+		$exists = Notification::whereProfileId($status->profile_id)
+				  ->whereActorId($actor->id)
+				  ->whereAction('like')
+				  ->whereItemId($status->id)
+				  ->whereItemType('App\Status')
+				  ->first();
+
+		if($exists) {
+			$exists->delete();
+		}
+
+		$like = Like::whereProfileId($actor->id)->whereStatusId($status->id)->first();
+
+		if(!$like) {
+			return;
+		}
+
+		$like->forceDelete();
+
+		return;
+	}
+
+	public function remoteLikeDeliver()
+	{
+		$like = $this->like;
+		$status = $this->like->status;
+		$actor = $this->like->actor;
+
+		$fractal = new Fractal\Manager();
+		$fractal->setSerializer(new ArraySerializer());
+		$resource = new Fractal\Resource\Item($like, new LikeTransformer());
+		$activity = $fractal->createData($resource)->toArray();
+
+		$url = $status->profile->sharedInbox ?? $status->profile->inbox_url;
+
+		Helpers::sendSignedObject($actor, $url, $activity);
+	}
+}

+ 25 - 0
app/Transformer/ActivityPub/Verb/UndoLike.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Transformer\ActivityPub\Verb;
+
+use App\Like as LikeModel;
+use League\Fractal;
+
+class UndoLike extends Fractal\TransformerAbstract
+{
+	public function transform(LikeModel $like)
+	{
+		return [
+			'@context'  => 'https://www.w3.org/ns/activitystreams',
+			'id'		=> $like->actor->permalink('#likes/'.$like->id.'/undo'),
+			'type' 		=> 'Undo',
+			'actor'		=> $like->actor->permalink(),
+			'object'	=> [
+				'id'		=> $like->actor->permalink('#likes/'.$like->id),
+				'type' 		=> 'Like',
+				'actor'		=> $like->actor->permalink(),
+				'object' 	=> $like->status->url()
+			]
+		];
+	}
+}