now using jobs when posting activities

This commit is contained in:
Ghostie 2025-01-06 18:42:48 -05:00
parent 1740649ff7
commit 563c520aee
5 changed files with 131 additions and 76 deletions

View File

@ -54,3 +54,6 @@
- [x] Fix that weird json encoding in the object field of an activity
- [ ] The profile attachments are not working, they are not being federalised somehow (the interests thingy)
- [ ] Endpoints for getting notes (/ap/v1/note/{note})
- [ ] Fix hashtags on post update
- [x] Use jobs when posting activities
- [ ] Sign the get activities for mastodon when secure mode is enable

View File

@ -173,8 +173,9 @@ class APOutboxController extends Controller
"object" => $object_actor->id,
]);
if (!$response || $response->getStatusCode () < 200 || $response->getStatusCode () >= 300)
return response ()->json ([ "error" => "failed to post activity" ], 500);
// TODO: Check if it was successfully sent
/* if (!$response || $response->getStatusCode () < 200 || $response->getStatusCode () >= 300)
return response ()->json ([ "error" => "failed to post activity" ], 500); */
return [
"success" => "followed"
@ -197,8 +198,9 @@ class APOutboxController extends Controller
$unfollow_activity = TypeActivity::craft_undo ($follow_activity, $user->actor ()->first ());
$response = TypeActivity::post_activity ($unfollow_activity, $user->actor ()->first (), $object_actor);
if (!$response || $response->getStatusCode () < 200 || $response->getStatusCode () >= 300)
return response ()->json ([ "error" => "failed to post activity" ], 500);
// TODO: Check if it was successfully sent
/* if (!$response || $response->getStatusCode () < 200 || $response->getStatusCode () >= 300)
return response ()->json ([ "error" => "failed to post activity" ], 500); */
$follow_activity->delete ();
return [
@ -243,8 +245,9 @@ class APOutboxController extends Controller
$response = TypeActivity::post_activity ($like_activity, $actor, $object->get_actor ()->first ());
if (!$response || $response->getStatusCode () < 200 || $response->getStatusCode () >= 300)
return response ()->json ([ "error" => "failed to post activity" ], 500);
// TODO: Check if it was successfully sent
/* if (!$response || $response->getStatusCode () < 200 || $response->getStatusCode () >= 300)
return response ()->json ([ "error" => "failed to post activity" ], 500); */
return [
"success" => "liked"

View File

@ -0,0 +1,101 @@
<?php
namespace App\Jobs;
use App\Models\Actor;
use GuzzleHttp\Client;
use App\Models\Activity;
use App\Types\TypeActivity;
use Illuminate\Support\Facades\Log;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class PostActivityJob implements ShouldQueue
{
use Queueable;
public $tries = 3;
protected $activity;
protected $actor;
protected $target;
protected $should_sign;
/**
* Create a new job instance.
*/
public function __construct(Activity $activity, Actor $actor, $target, $should_sign = false)
{
$this->activity = $activity;
$this->actor = $actor;
$this->target = $target;
$this->should_sign = $should_sign;
}
/**
* Execute the job.
*/
public function handle(): void
{
$crafted_activity = TypeActivity::craft_response($this->activity);
if ($this->should_sign)
{
$crafted_activity ["to"] = [
"https://www.w3.org/ns/activitystreams#Public",
];
$crafted_activity ["cc"] = [
$this->actor->following
];
$key = TypeActivity::get_private_key($this->actor);
$activity_json = json_encode($crafted_activity, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$signature = TypeActivity::sign($activity_json, $key);
$crafted_activity ["signature"] = [
"type" => "RsaSignature2017",
"creator" => $this->actor->actor_id . "#main-key",
"created" => gmdate("Y-m-d\TH:i:s\Z"),
"signatureValue" => base64_encode($signature)
];
$activity_json = json_encode($crafted_activity, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
$activity_json = json_encode($crafted_activity, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$activity_json = mb_convert_encoding($activity_json, "UTF-8");
$headers = TypeActivity::craft_signed_headers($activity_json, $this->actor, $this->target);
if (!$headers)
{
throw new \Exception("Failed to craft headers");
}
$target_inbox = null;
if ($this->target instanceof Actor)
{
$target_inbox = $this->target->inbox;
}
else
{
$target_inbox = $this->target;
}
$client = new Client ();
$response = $client->post($target_inbox, [
"headers" => $headers,
"body" => $activity_json,
"debug" => true
]);
}
public function failed (\Exception $exception)
{
Log::error("Failed to post activity: " . $exception->getMessage());
}
}

View File

@ -6,6 +6,8 @@ use App\Models\Actor;
use App\Models\Activity;
use App\Models\Instance;
use App\Jobs\PostActivityJob;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
@ -194,74 +196,11 @@ class TypeActivity {
public static function post_activity (Activity $activity, Actor $source, $target, $should_sign = false)
{
$crafted_activity = TypeActivity::craft_response ($activity);
PostActivityJob::dispatch ($activity, $source, $target, $should_sign);
if ($should_sign)
{
$crafted_activity["to"] = [
"https://www.w3.org/ns/activitystreams#Public"
return [
"success" => "activity posted"
];
$crafted_activity["cc"] = [
$source->following
];
$key = TypeActivity::get_private_key ($source);
$activity_json = json_encode ($crafted_activity, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION);
$signature = TypeActivity::sign ($activity_json, $key);
$crafted_activity ["signature"] = [
"type" => "RsaSignature2017",
"creator" => $source->actor_id . "#main-key",
"created" => gmdate ("Y-m-d\TH:i:s\Z"),
"signatureValue" => base64_encode ($signature)
];
$activity_json = json_encode ($crafted_activity, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION);
}
$activity_json = json_encode ($crafted_activity, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION);
$activity_json = mb_convert_encoding ($activity_json, "UTF-8");
$headers = TypeActivity::craft_signed_headers ($activity_json, $source, $target);
if (!$headers)
{
Log::error ("Failed to craft headers");
return null;
}
try {
$target_inbox = null;
if ($target instanceof Actor)
{
$target_inbox = $target->inbox;
}
else
{
$target_inbox = $target;
}
$client = new Client ();
$response = $client->post ($target_inbox, [
"headers" => $headers,
"body" => $activity_json,
"debug" => true
]);
}
catch (RequestException $e)
{
$response = $e->getResponse ();
if ($response)
{
Log::error ("Failed to post activity: " . $response->getBody ());
}
Log::error ("Failed to post activity: " . $e->getMessage ());
return null;
}
return $response;
}
public static function post_to_instances (Activity $activity, Actor $source)
@ -272,11 +211,12 @@ class TypeActivity {
if (!$instance->inbox)
continue;
$response = TypeActivity::post_activity ($activity, $source, $instance->inbox, true);
if (!$response || $response->getStatusCode () < 200 || $response->getStatusCode () >= 300)
TypeActivity::post_activity ($activity, $source, $instance->inbox, true);
// TODO: Check if it was successfully posted
/* if (!$response || $response->getStatusCode () < 200 || $response->getStatusCode () >= 300)
{
Log::info ("failed to post activity to " . $instance->inbox);
}
} */
}
}

View File

@ -59,29 +59,37 @@
@if (!auth ()->user ()->is ($user))
<div class="f-col">
@if (auth ()->user ()->actor->friends_with ($actor))
<a href="#">
<form action="{{ route ('user.unfriend') }}" onclick="this.submit ()" method="post" style="cursor: pointer">
@csrf
<input type="hidden" name="object" value="{{ $actor->actor_id }}">
<img loading="lazy" src="/resources/icons/delete.png" alt=""> Remove Friend
</form>
</a>
@elseif (in_array ($actor->actor_id, auth ()->user ()->received_requests ()))
<a href="#">
<form action="{{ route ('user.friend') }}" onclick="this.submit ()" method="post" style="cursor: pointer">
@csrf
<input type="hidden" name="object" value="{{ $actor->actor_id }}">
<img loading="lazy" src="/resources/icons/add.png" alt=""> Accept Friend Request
</form>
</a>
@elseif (in_array ($actor->actor_id, auth ()->user ()->sent_requests ()))
<a href="#">
<form action="{{ route ('user.unfriend') }}" onclick="this.submit ()" method="post" style="cursor: pointer">
@csrf
<input type="hidden" name="object" value="{{ $actor->actor_id }}">
<img loading="lazy" src="/resources/icons/hourglass.png" alt=""> Cancel Request
</form>
</a>
@else
<a href="#">
<form action="{{ route ('user.friend') }}" onclick="this.submit ()" method="post" style="cursor: pointer">
@csrf
<input type="hidden" name="object" value="{{ $actor->actor_id }}">
<img loading="lazy" src="/resources/icons/add.png" alt=""> Add to Friends
</form>
</a>
@endif
</div>
@else