Update AP Inbox

This commit is contained in:
Daniel Supernault 2021-09-03 21:21:17 -06:00
parent c7a5715a60
commit 3c8c23a143
No known key found for this signature in database
GPG key ID: 0DEF1C662C9033F7
2 changed files with 302 additions and 15 deletions

View file

@ -563,9 +563,12 @@ class Helpers {
$profile = Profile::whereRemoteUrl($res['id'])->first(); $profile = Profile::whereRemoteUrl($res['id'])->first();
if(!$profile) { if(!$profile) {
Instance::firstOrCreate([ $instance = Instance::firstOrCreate([
'domain' => $domain 'domain' => $domain
]); ]);
if($instance->wasRecentlyCreated == true) {
\App\Jobs\InstancePipeline\FetchNodeinfoPipeline::dispatch($instance)->onQueue('low');
}
$profileLockKey = 'helpers:profile-lock:' . hash('sha256', $res['id']); $profileLockKey = 'helpers:profile-lock:' . hash('sha256', $res['id']);
$profile = Cache::lock($profileLockKey)->get(function () use($domain, $webfinger, $res, $runJobs) { $profile = Cache::lock($profileLockKey)->get(function () use($domain, $webfinger, $res, $runJobs) {
return DB::transaction(function() use($domain, $webfinger, $res, $runJobs) { return DB::transaction(function() use($domain, $webfinger, $res, $runJobs) {

View file

@ -2,7 +2,7 @@
namespace App\Util\ActivityPub; namespace App\Util\ActivityPub;
use Cache, DB, Log, Purify, Redis, Validator; use Cache, DB, Log, Purify, Redis, Storage, Validator;
use App\{ use App\{
Activity, Activity,
DirectMessage, DirectMessage,
@ -14,6 +14,8 @@ use App\{
Profile, Profile,
Status, Status,
StatusHashtag, StatusHashtag,
Story,
StoryView,
UserFilter UserFilter
}; };
use Carbon\Carbon; use Carbon\Carbon;
@ -22,6 +24,8 @@ use Illuminate\Support\Str;
use App\Jobs\LikePipeline\LikePipeline; use App\Jobs\LikePipeline\LikePipeline;
use App\Jobs\FollowPipeline\FollowPipeline; use App\Jobs\FollowPipeline\FollowPipeline;
use App\Jobs\DeletePipeline\DeleteRemoteProfilePipeline; use App\Jobs\DeletePipeline\DeleteRemoteProfilePipeline;
use App\Jobs\StoryPipeline\StoryExpire;
use App\Jobs\StoryPipeline\StoryFetch;
use App\Util\ActivityPub\Validator\Accept as AcceptValidator; use App\Util\ActivityPub\Validator\Accept as AcceptValidator;
use App\Util\ActivityPub\Validator\Add as AddValidator; use App\Util\ActivityPub\Validator\Add as AddValidator;
@ -31,6 +35,7 @@ use App\Util\ActivityPub\Validator\Like as LikeValidator;
use App\Util\ActivityPub\Validator\UndoFollow as UndoFollowValidator; use App\Util\ActivityPub\Validator\UndoFollow as UndoFollowValidator;
use App\Services\PollService; use App\Services\PollService;
use App\Services\FollowerService;
class Inbox class Inbox
{ {
@ -49,16 +54,7 @@ class Inbox
public function handle() public function handle()
{ {
$this->handleVerb(); $this->handleVerb();
// if(!Activity::where('data->id', $this->payload['id'])->exists()) {
// (new Activity())->create([
// 'to_id' => $this->profile->id,
// 'data' => json_encode($this->payload)
// ]);
// }
return; return;
} }
public function handleVerb() public function handleVerb()
@ -107,6 +103,18 @@ class Inbox
$this->handleUndoActivity(); $this->handleUndoActivity();
break; break;
case 'View':
$this->handleViewActivity();
break;
case 'Story:Reaction':
$this->handleStoryReactionActivity();
break;
case 'Story:Reply':
$this->handleStoryReplyActivity();
break;
default: default:
// TODO: decide how to handle invalid verbs. // TODO: decide how to handle invalid verbs.
break; break;
@ -138,6 +146,30 @@ class Inbox
public function handleAddActivity() public function handleAddActivity()
{ {
// stories ;) // stories ;)
if(!isset(
$this->payload['actor'],
$this->payload['object']
)) {
return;
}
$actor = $this->payload['actor'];
$obj = $this->payload['object'];
if(!Helpers::validateUrl($actor)) {
return;
}
if(!isset($obj['type'])) {
return;
}
switch($obj['type']) {
case 'Story':
StoryFetch::dispatch($this->payload)->onQueue('story');
break;
}
} }
public function handleCreateActivity() public function handleCreateActivity()
@ -212,8 +244,8 @@ class Inbox
if( isset($activity['inReplyTo']) && if( isset($activity['inReplyTo']) &&
isset($activity['name']) && isset($activity['name']) &&
!isset($activity['content']) && !isset($activity['content']) &&
!isset($activity['attachment'] && !isset($activity['attachment']) &&
Helpers::validateLocalUrl($activity['inReplyTo'])) Helpers::validateLocalUrl($activity['inReplyTo'])
) { ) {
$this->handlePollVote(); $this->handlePollVote();
return; return;
@ -496,7 +528,6 @@ class Inbox
public function handleAcceptActivity() public function handleAcceptActivity()
{ {
$actor = $this->payload['object']['actor']; $actor = $this->payload['object']['actor'];
$obj = $this->payload['object']['object']; $obj = $this->payload['object']['object'];
$type = $this->payload['object']['type']; $type = $this->payload['object']['type'];
@ -556,7 +587,7 @@ class Inbox
return; return;
} else { } else {
$type = $this->payload['object']['type']; $type = $this->payload['object']['type'];
$typeCheck = in_array($type, ['Person', 'Tombstone']); $typeCheck = in_array($type, ['Person', 'Tombstone', 'Story']);
if(!Helpers::validateUrl($actor) || !Helpers::validateUrl($obj['id']) || !$typeCheck) { if(!Helpers::validateUrl($actor) || !Helpers::validateUrl($obj['id']) || !$typeCheck) {
return; return;
} }
@ -596,6 +627,13 @@ class Inbox
return; return;
break; break;
case 'Story':
$story = Story::whereObjectId($id)
->first();
if($story) {
StoryExpire::dispatch($story)->onQueue('story');
}
default: default:
return; return;
break; break;
@ -705,4 +743,250 @@ class Inbox
} }
return; return;
} }
public function handleViewActivity()
{
if(!isset(
$this->payload['actor'],
$this->payload['object']
)) {
return;
}
$actor = $this->payload['actor'];
$obj = $this->payload['object'];
if(!Helpers::validateUrl($actor)) {
return;
}
if(!$obj || !is_array($obj)) {
return;
}
if(!isset($obj['type']) || !isset($obj['object']) || $obj['type'] != 'Story') {
return;
}
if(!Helpers::validateLocalUrl($obj['object'])) {
return;
}
$profile = Helpers::profileFetch($actor);
$storyId = Str::of($obj['object'])->explode('/')->last();
$story = Story::whereActive(true)
->whereLocal(true)
->find($storyId);
if(!$story) {
return;
}
if(!FollowerService::follows($profile->id, $story->profile_id)) {
return;
}
$view = StoryView::firstOrCreate([
'story_id' => $story->id,
'profile_id' => $profile->id
]);
if($view->wasRecentlyCreated == true) {
$story->view_count++;
$story->save();
}
}
public function handleStoryReactionActivity()
{
if(!isset(
$this->payload['actor'],
$this->payload['id'],
$this->payload['inReplyTo'],
$this->payload['content']
)) {
return;
}
$id = $this->payload['id'];
$actor = $this->payload['actor'];
$storyUrl = $this->payload['inReplyTo'];
$to = $this->payload['to'];
$text = Purify::clean($this->payload['content']);
if(parse_url($id, PHP_URL_HOST) !== parse_url($actor, PHP_URL_HOST)) {
return;
}
if(!Helpers::validateUrl($id) || !Helpers::validateUrl($actor)) {
return;
}
if(!Helpers::validateLocalUrl($storyUrl)) {
return;
}
if(!Helpers::validateLocalUrl($to)) {
return;
}
if(Status::whereObjectUrl($id)->exists()) {
return;
}
$storyId = Str::of($storyUrl)->explode('/')->last();
$targetProfile = Helpers::profileFetch($to);
$story = Story::whereProfileId($targetProfile->id)
->find($storyId);
if(!$story) {
return;
}
if($story->can_react == false) {
return;
}
$actorProfile = Helpers::profileFetch($actor);
if(!FollowerService::follows($actorProfile->id, $targetProfile->id)) {
return;
}
$status = new Status;
$status->profile_id = $actorProfile->id;
$status->type = 'story:reaction';
$status->caption = $text;
$status->rendered = $text;
$status->scope = 'direct';
$status->visibility = 'direct';
$status->in_reply_to_profile_id = $story->profile_id;
$status->entities = json_encode([
'story_id' => $story->id,
'reaction' => $text
]);
$status->save();
$dm = new DirectMessage;
$dm->to_id = $story->profile_id;
$dm->from_id = $actorProfile->id;
$dm->type = 'story:react';
$dm->status_id = $status->id;
$dm->meta = json_encode([
'story_username' => $targetProfile->username,
'story_actor_username' => $actorProfile->username,
'story_id' => $story->id,
'story_media_url' => url(Storage::url($story->path)),
'reaction' => $text
]);
$dm->save();
$n = new Notification;
$n->profile_id = $dm->to_id;
$n->actor_id = $dm->from_id;
$n->item_id = $dm->id;
$n->item_type = 'App\DirectMessage';
$n->action = 'story:react';
$n->message = "{$actorProfile->username} reacted to your story";
$n->rendered = "{$actorProfile->username} reacted to your story";
$n->save();
}
public function handleStoryReplyActivity()
{
if(!isset(
$this->payload['actor'],
$this->payload['id'],
$this->payload['inReplyTo'],
$this->payload['content']
)) {
return;
}
$id = $this->payload['id'];
$actor = $this->payload['actor'];
$storyUrl = $this->payload['inReplyTo'];
$to = $this->payload['to'];
$text = Purify::clean($this->payload['content']);
if(parse_url($id, PHP_URL_HOST) !== parse_url($actor, PHP_URL_HOST)) {
return;
}
if(!Helpers::validateUrl($id) || !Helpers::validateUrl($actor)) {
return;
}
if(!Helpers::validateLocalUrl($storyUrl)) {
return;
}
if(!Helpers::validateLocalUrl($to)) {
return;
}
if(Status::whereObjectUrl($id)->exists()) {
return;
}
$storyId = Str::of($storyUrl)->explode('/')->last();
$targetProfile = Helpers::profileFetch($to);
$story = Story::whereProfileId($targetProfile->id)
->find($storyId);
if(!$story) {
return;
}
if($story->can_react == false) {
return;
}
$actorProfile = Helpers::profileFetch($actor);
if(!FollowerService::follows($actorProfile->id, $targetProfile->id)) {
return;
}
$status = new Status;
$status->profile_id = $actorProfile->id;
$status->type = 'story:reply';
$status->caption = $text;
$status->rendered = $text;
$status->scope = 'direct';
$status->visibility = 'direct';
$status->in_reply_to_profile_id = $story->profile_id;
$status->entities = json_encode([
'story_id' => $story->id,
'caption' => $text
]);
$status->save();
$dm = new DirectMessage;
$dm->to_id = $story->profile_id;
$dm->from_id = $actorProfile->id;
$dm->type = 'story:comment';
$dm->status_id = $status->id;
$dm->meta = json_encode([
'story_username' => $targetProfile->username,
'story_actor_username' => $actorProfile->username,
'story_id' => $story->id,
'story_media_url' => url(Storage::url($story->path)),
'caption' => $text
]);
$dm->save();
$n = new Notification;
$n->profile_id = $dm->to_id;
$n->actor_id = $dm->from_id;
$n->item_id = $dm->id;
$n->item_type = 'App\DirectMessage';
$n->action = 'story:comment';
$n->message = "{$actorProfile->username} commented on story";
$n->rendered = "{$actorProfile->username} commented on story";
$n->save();
}
} }