2021-04-02 19:20:02 +02:00
|
|
|
<?php
|
|
|
|
|
2021-06-08 11:52:11 +02:00
|
|
|
declare(strict_types=1);
|
|
|
|
|
2021-04-02 19:20:02 +02:00
|
|
|
/**
|
2022-02-19 17:06:11 +01:00
|
|
|
* @copyright 2021 Ad Aures
|
2021-04-02 19:20:02 +02:00
|
|
|
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
|
|
|
* @link https://castopod.org/
|
|
|
|
*/
|
|
|
|
|
2021-08-23 13:05:16 +02:00
|
|
|
namespace Modules\Fediverse\Controllers;
|
2021-04-02 19:20:02 +02:00
|
|
|
|
|
|
|
use CodeIgniter\Controller;
|
2021-05-19 18:35:13 +02:00
|
|
|
use CodeIgniter\Exceptions\PageNotFoundException;
|
|
|
|
use CodeIgniter\HTTP\RedirectResponse;
|
|
|
|
use CodeIgniter\HTTP\ResponseInterface;
|
2021-04-02 19:20:02 +02:00
|
|
|
use CodeIgniter\I18n\Time;
|
2022-03-15 15:05:19 +01:00
|
|
|
use Exception;
|
2021-08-23 13:05:16 +02:00
|
|
|
use Modules\Fediverse\Config\Fediverse;
|
2023-08-29 14:58:20 +02:00
|
|
|
use Modules\Fediverse\Entities\Activity;
|
2021-08-23 13:05:16 +02:00
|
|
|
use Modules\Fediverse\Entities\Actor;
|
|
|
|
use Modules\Fediverse\Entities\Post;
|
|
|
|
use Modules\Fediverse\Objects\OrderedCollectionObject;
|
|
|
|
use Modules\Fediverse\Objects\OrderedCollectionPage;
|
2021-04-02 19:20:02 +02:00
|
|
|
|
|
|
|
class ActorController extends Controller
|
|
|
|
{
|
2021-05-06 16:00:48 +02:00
|
|
|
/**
|
|
|
|
* @var string[]
|
|
|
|
*/
|
2021-08-27 12:58:22 +02:00
|
|
|
protected $helpers = ['fediverse'];
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-05-18 19:16:36 +02:00
|
|
|
protected Actor $actor;
|
2021-05-19 18:35:13 +02:00
|
|
|
|
2021-08-27 12:58:22 +02:00
|
|
|
protected Fediverse $config;
|
2021-04-02 19:20:02 +02:00
|
|
|
|
|
|
|
public function __construct()
|
|
|
|
{
|
2023-08-27 15:26:06 +02:00
|
|
|
$this->config = config(Fediverse::class);
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
|
|
|
|
2021-05-14 19:59:35 +02:00
|
|
|
public function _remap(string $method, string ...$params): mixed
|
2021-04-02 19:20:02 +02:00
|
|
|
{
|
2021-06-09 14:40:22 +02:00
|
|
|
if (count($params) < 1) {
|
|
|
|
throw PageNotFoundException::forPageNotFound();
|
|
|
|
}
|
|
|
|
|
2021-05-06 16:00:48 +02:00
|
|
|
if (
|
2023-08-29 14:58:20 +02:00
|
|
|
! ($actor = model('ActorModel', false)->getActorByUsername($params[0])) instanceof Actor
|
2021-05-06 16:00:48 +02:00
|
|
|
) {
|
|
|
|
throw PageNotFoundException::forPageNotFound();
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
2021-06-09 14:40:22 +02:00
|
|
|
|
|
|
|
$this->actor = $actor;
|
2021-04-02 19:20:02 +02:00
|
|
|
unset($params[0]);
|
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->{$method}(...$params);
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
|
|
|
|
2021-05-28 19:04:54 +02:00
|
|
|
public function index(): ResponseInterface
|
2021-04-02 19:20:02 +02:00
|
|
|
{
|
|
|
|
$actorObjectClass = $this->config->actorObject;
|
|
|
|
$actorObject = new $actorObjectClass($this->actor);
|
|
|
|
|
|
|
|
return $this->response
|
|
|
|
->setContentType('application/activity+json')
|
|
|
|
->setBody($actorObject->toJSON());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles incoming requests from fediverse servers
|
|
|
|
*/
|
2021-05-06 16:00:48 +02:00
|
|
|
public function inbox(): ResponseInterface
|
2021-04-02 19:20:02 +02:00
|
|
|
{
|
|
|
|
// get json body and parse it
|
|
|
|
$payload = $this->request->getJSON();
|
|
|
|
|
|
|
|
// retrieve payload actor from database or create it if it doesn't exist
|
|
|
|
$payloadActor = get_or_create_actor_from_uri($payload->actor);
|
|
|
|
|
|
|
|
// store activity to database
|
2022-02-05 12:40:30 +01:00
|
|
|
$activityId = model('ActivityModel', false)
|
2021-05-19 18:35:13 +02:00
|
|
|
->newActivity(
|
|
|
|
$payload->type,
|
|
|
|
$payloadActor->id,
|
|
|
|
$this->actor->id,
|
|
|
|
null,
|
|
|
|
json_encode($payload, JSON_THROW_ON_ERROR),
|
|
|
|
);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
|
|
|
// switch/case on activity type
|
2021-05-18 19:16:36 +02:00
|
|
|
/** @phpstan-ignore-next-line */
|
2021-04-02 19:20:02 +02:00
|
|
|
switch ($payload->type) {
|
|
|
|
case 'Create':
|
2021-05-19 18:35:13 +02:00
|
|
|
if ($payload->object->type === 'Note') {
|
|
|
|
if (! $payload->object->inReplyTo) {
|
|
|
|
return $this->response->setStatusCode(501)
|
|
|
|
->setJSON([]);
|
2021-05-06 16:00:48 +02:00
|
|
|
}
|
2021-06-08 11:52:11 +02:00
|
|
|
|
2022-02-05 12:40:30 +01:00
|
|
|
$replyToPost = model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->getPostByUri($payload->object->inReplyTo);
|
2021-06-08 11:52:11 +02:00
|
|
|
|
|
|
|
$reply = null;
|
2023-08-29 14:58:20 +02:00
|
|
|
if ($replyToPost instanceof Post) {
|
2021-06-08 11:52:11 +02:00
|
|
|
// TODO: strip content from html to retrieve message
|
|
|
|
// remove all html tags and reconstruct message with mentions?
|
2022-02-02 11:25:28 +01:00
|
|
|
$message = get_message_from_object($payload->object);
|
|
|
|
|
2021-08-13 13:07:29 +02:00
|
|
|
$reply = new Post([
|
2023-06-12 16:47:38 +02:00
|
|
|
'uri' => $payload->object->id,
|
|
|
|
'actor_id' => $payloadActor->id,
|
2021-08-13 13:07:29 +02:00
|
|
|
'in_reply_to_id' => $replyToPost->id,
|
2023-06-12 16:47:38 +02:00
|
|
|
'message' => $message,
|
|
|
|
'published_at' => Time::parse($payload->object->published),
|
2021-05-19 18:35:13 +02:00
|
|
|
]);
|
2021-06-08 11:52:11 +02:00
|
|
|
}
|
|
|
|
|
2023-04-14 13:11:53 +02:00
|
|
|
if ($reply instanceof Post) {
|
2022-02-05 12:40:30 +01:00
|
|
|
$postId = model('PostModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->addReply($reply, true, false);
|
|
|
|
|
2022-02-05 12:40:30 +01:00
|
|
|
model('ActivityModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->update($activityId, [
|
2021-08-13 13:07:29 +02:00
|
|
|
'post_id' => $postId,
|
2021-06-08 11:52:11 +02:00
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(200)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
2022-03-04 15:33:48 +01:00
|
|
|
|
2021-05-06 16:00:48 +02:00
|
|
|
// return not handled undo error (501 = not implemented)
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(501)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
case 'Delete':
|
2022-02-05 12:40:30 +01:00
|
|
|
$postToDelete = model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->getPostByUri($payload->object->id);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2023-08-29 14:58:20 +02:00
|
|
|
if ($postToDelete instanceof Post) {
|
2022-02-05 12:40:30 +01:00
|
|
|
model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->removePost($postToDelete, false);
|
2021-06-08 11:52:11 +02:00
|
|
|
}
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(200)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
case 'Follow':
|
|
|
|
// add to followers table
|
2022-02-05 12:40:30 +01:00
|
|
|
model('FollowModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->addFollower($payloadActor, $this->actor, false);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
|
|
|
// Automatically accept follow by returning accept activity
|
|
|
|
accept_follow($this->actor, $payloadActor, $payload->id);
|
|
|
|
|
|
|
|
// TODO: return 202 (Accepted) followed!
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(202)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
|
|
|
case 'Like':
|
2021-08-13 13:07:29 +02:00
|
|
|
// get favourited post
|
2022-02-05 12:40:30 +01:00
|
|
|
$post = model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->getPostByUri($payload->object);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2023-08-29 14:58:20 +02:00
|
|
|
if ($post instanceof Post) {
|
2021-06-08 11:52:11 +02:00
|
|
|
// Like side-effect
|
2022-02-05 12:40:30 +01:00
|
|
|
model('FavouriteModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->addFavourite($payloadActor, $post, false);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2022-02-05 12:40:30 +01:00
|
|
|
model('ActivityModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->update($activityId, [
|
2021-08-13 13:07:29 +02:00
|
|
|
'post_id' => $post->id,
|
2021-06-08 11:52:11 +02:00
|
|
|
]);
|
|
|
|
}
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(200)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
case 'Announce':
|
2022-02-05 12:40:30 +01:00
|
|
|
$post = model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->getPostByUri($payload->object);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2023-08-29 14:58:20 +02:00
|
|
|
if ($post instanceof Post) {
|
2022-02-05 12:40:30 +01:00
|
|
|
model('ActivityModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->update($activityId, [
|
2021-08-13 13:07:29 +02:00
|
|
|
'post_id' => $post->id,
|
2021-06-08 11:52:11 +02:00
|
|
|
]);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2022-02-05 12:40:30 +01:00
|
|
|
model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->reblog($payloadActor, $post, false);
|
2021-06-08 11:52:11 +02:00
|
|
|
}
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(200)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
case 'Undo':
|
|
|
|
// switch/case on the type of activity to undo
|
2021-05-18 19:16:36 +02:00
|
|
|
/** @phpstan-ignore-next-line */
|
2021-04-02 19:20:02 +02:00
|
|
|
switch ($payload->object->type) {
|
|
|
|
case 'Follow':
|
|
|
|
// revert side-effect by removing follow from database
|
2022-02-05 12:40:30 +01:00
|
|
|
model('FollowModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->removeFollower($payloadActor, $this->actor, false);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
|
|
|
// TODO: undo has been accepted! (202 - Accepted)
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(202)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
case 'Like':
|
2022-02-05 12:40:30 +01:00
|
|
|
$post = model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->getPostByUri($payload->object->object);
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2023-08-29 14:58:20 +02:00
|
|
|
if ($post instanceof Post) {
|
2021-06-08 11:52:11 +02:00
|
|
|
// revert side-effect by removing favourite from database
|
2022-02-05 12:40:30 +01:00
|
|
|
model('FavouriteModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->removeFavourite($payloadActor, $post, false);
|
2021-05-19 18:35:13 +02:00
|
|
|
|
2022-02-05 12:40:30 +01:00
|
|
|
model('ActivityModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->update($activityId, [
|
2021-08-13 13:07:29 +02:00
|
|
|
'post_id' => $post->id,
|
2021-06-08 11:52:11 +02:00
|
|
|
]);
|
|
|
|
}
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(200)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
case 'Announce':
|
2022-02-05 12:40:30 +01:00
|
|
|
$post = model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->getPostByUri($payload->object->object);
|
2021-06-08 11:52:11 +02:00
|
|
|
|
2021-08-13 13:07:29 +02:00
|
|
|
$reblogPost = null;
|
2023-08-29 14:58:20 +02:00
|
|
|
if ($post instanceof Post) {
|
2022-02-05 12:40:30 +01:00
|
|
|
$reblogPost = model('PostModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->where([
|
2023-06-12 16:47:38 +02:00
|
|
|
'actor_id' => $payloadActor->id,
|
2021-06-08 11:52:11 +02:00
|
|
|
'reblog_of_id' => service('uuid')
|
2021-08-13 13:07:29 +02:00
|
|
|
->fromString($post->id)
|
2021-06-08 11:52:11 +02:00
|
|
|
->getBytes(),
|
|
|
|
])
|
|
|
|
->first();
|
|
|
|
}
|
|
|
|
|
2021-08-13 13:07:29 +02:00
|
|
|
if ($reblogPost !== null) {
|
2022-02-05 12:40:30 +01:00
|
|
|
model('PostModel', false)
|
2021-08-13 13:07:29 +02:00
|
|
|
->undoReblog($reblogPost, false);
|
2021-06-08 11:52:11 +02:00
|
|
|
|
2022-02-05 12:40:30 +01:00
|
|
|
model('ActivityModel', false)
|
2021-06-08 11:52:11 +02:00
|
|
|
->update($activityId, [
|
2021-08-13 13:07:29 +02:00
|
|
|
'post_id' => $post->id,
|
2021-06-08 11:52:11 +02:00
|
|
|
]);
|
|
|
|
}
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(200)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
default:
|
|
|
|
// return not handled undo error (501 = not implemented)
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(501)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
2021-05-19 18:35:13 +02:00
|
|
|
// no break
|
2021-04-02 19:20:02 +02:00
|
|
|
default:
|
|
|
|
// return not handled activity error (501 = not implemented)
|
2021-05-19 18:35:13 +02:00
|
|
|
return $this->response->setStatusCode(501)
|
|
|
|
->setJSON([]);
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-28 19:04:54 +02:00
|
|
|
public function outbox(): ResponseInterface
|
2021-04-02 19:20:02 +02:00
|
|
|
{
|
|
|
|
// get published activities by publication date
|
2022-02-05 12:40:30 +01:00
|
|
|
$actorActivity = model('ActivityModel', false)
|
2021-04-02 19:20:02 +02:00
|
|
|
->where('actor_id', $this->actor->id)
|
2022-04-14 16:33:53 +02:00
|
|
|
->where('`created_at` <= UTC_TIMESTAMP()', null, false)
|
2021-04-02 19:20:02 +02:00
|
|
|
->orderBy('created_at', 'DESC');
|
|
|
|
|
2021-06-10 15:18:58 +02:00
|
|
|
$pageNumber = (int) $this->request->getGet('page');
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-06-10 15:18:58 +02:00
|
|
|
if ($pageNumber < 1) {
|
2021-04-02 19:20:02 +02:00
|
|
|
$actorActivity->paginate(12);
|
|
|
|
$pager = $actorActivity->pager;
|
|
|
|
$collection = new OrderedCollectionObject(null, $pager);
|
|
|
|
} else {
|
2021-06-08 11:52:11 +02:00
|
|
|
$paginatedActivity = $actorActivity->paginate(12, 'default', $pageNumber);
|
2021-04-02 19:20:02 +02:00
|
|
|
$pager = $actorActivity->pager;
|
|
|
|
$orderedItems = [];
|
|
|
|
foreach ($paginatedActivity as $activity) {
|
2021-05-06 16:00:48 +02:00
|
|
|
$orderedItems[] = $activity->payload;
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
2022-03-04 15:33:48 +01:00
|
|
|
|
2021-04-02 19:20:02 +02:00
|
|
|
$collection = new OrderedCollectionPage($pager, $orderedItems);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->response
|
|
|
|
->setContentType('application/activity+json')
|
|
|
|
->setBody($collection->toJSON());
|
|
|
|
}
|
|
|
|
|
2021-05-28 19:04:54 +02:00
|
|
|
public function followers(): ResponseInterface
|
2021-04-02 19:20:02 +02:00
|
|
|
{
|
|
|
|
// get followers for a specific actor
|
2022-02-05 12:40:30 +01:00
|
|
|
$followers = model('ActorModel', false)
|
2023-08-26 15:03:01 +02:00
|
|
|
->join('fediverse_follows', 'fediverse_follows.actor_id = id', 'inner')
|
|
|
|
->where('fediverse_follows.target_actor_id', $this->actor->id)
|
|
|
|
->orderBy('fediverse_follows.created_at', 'DESC');
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-06-10 15:18:58 +02:00
|
|
|
$pageNumber = (int) $this->request->getGet('page');
|
2021-04-02 19:20:02 +02:00
|
|
|
|
2021-06-10 15:18:58 +02:00
|
|
|
if ($pageNumber < 1) {
|
2021-04-02 19:20:02 +02:00
|
|
|
$followers->paginate(12);
|
|
|
|
$pager = $followers->pager;
|
|
|
|
$followersCollection = new OrderedCollectionObject(null, $pager);
|
|
|
|
} else {
|
2021-06-08 11:52:11 +02:00
|
|
|
$paginatedFollowers = $followers->paginate(12, 'default', $pageNumber);
|
2021-04-02 19:20:02 +02:00
|
|
|
$pager = $followers->pager;
|
|
|
|
|
|
|
|
$orderedItems = [];
|
|
|
|
foreach ($paginatedFollowers as $follower) {
|
2021-05-06 16:00:48 +02:00
|
|
|
$orderedItems[] = $follower->uri;
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
2022-03-04 15:33:48 +01:00
|
|
|
|
2021-06-08 11:52:11 +02:00
|
|
|
$followersCollection = new OrderedCollectionPage($pager, $orderedItems);
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $this->response
|
|
|
|
->setContentType('application/activity+json')
|
|
|
|
->setBody($followersCollection->toJSON());
|
|
|
|
}
|
|
|
|
|
2022-10-17 16:17:50 +02:00
|
|
|
public function attemptFollow(): RedirectResponse
|
2021-04-02 19:20:02 +02:00
|
|
|
{
|
|
|
|
$rules = [
|
2023-06-12 16:47:38 +02:00
|
|
|
'handle' => 'regex_match[/^@?(?P<username>[\w\.\-]+)@(?P<host>[\w\.\-]+)(?P<port>:[\d]+)?$/]',
|
2021-04-02 19:20:02 +02:00
|
|
|
];
|
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
if (! $this->validate($rules)) {
|
2021-04-02 19:20:02 +02:00
|
|
|
return redirect()
|
|
|
|
->back()
|
|
|
|
->withInput()
|
|
|
|
->with('errors', $this->validator->getErrors());
|
|
|
|
}
|
|
|
|
|
2023-08-29 17:42:52 +02:00
|
|
|
$validData = $this->validator->getValidated();
|
|
|
|
|
2021-04-02 19:20:02 +02:00
|
|
|
helper('text');
|
|
|
|
|
|
|
|
// get webfinger data from actor
|
2021-08-27 12:58:22 +02:00
|
|
|
// parse actor id to get actor and domain
|
2021-04-02 19:20:02 +02:00
|
|
|
// check if actor and domain exist
|
|
|
|
|
2023-08-29 17:42:52 +02:00
|
|
|
$handle = $validData['handle'];
|
2022-03-15 15:05:19 +01:00
|
|
|
$parts = split_handle($handle);
|
|
|
|
|
|
|
|
try {
|
|
|
|
$data = get_webfinger_data($parts['username'], $parts['domain']);
|
|
|
|
} catch (Exception) {
|
2021-04-02 19:20:02 +02:00
|
|
|
return redirect()
|
|
|
|
->back()
|
|
|
|
->withInput()
|
2021-08-27 12:58:22 +02:00
|
|
|
->with('error', lang('Fediverse.follow.accountNotFound'));
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$ostatusKey = array_search(
|
|
|
|
'http://ostatus.org/schema/1.0/subscribe',
|
|
|
|
array_column($data->links, 'rel'),
|
2021-05-19 18:35:13 +02:00
|
|
|
true,
|
2021-04-02 19:20:02 +02:00
|
|
|
);
|
|
|
|
|
2021-05-19 18:35:13 +02:00
|
|
|
if (! $ostatusKey) {
|
2021-04-02 19:20:02 +02:00
|
|
|
// TODO: error, couldn't subscribe to activitypub account
|
|
|
|
// The instance doesn't allow its users to follow others
|
2022-03-15 15:05:19 +01:00
|
|
|
return redirect()
|
|
|
|
->back()
|
|
|
|
->withInput()
|
|
|
|
->with('error', lang('Fediverse.follow.remoteFollowNotAllowed'));
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return redirect()->to(
|
2022-10-17 16:17:50 +02:00
|
|
|
str_replace('{uri}', urlencode($this->actor->uri), (string) $data->links[$ostatusKey]->template),
|
2021-04-02 19:20:02 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-05-28 19:04:54 +02:00
|
|
|
public function activity(string $activityId): ResponseInterface
|
2021-04-02 19:20:02 +02:00
|
|
|
{
|
|
|
|
if (
|
2023-08-29 14:58:20 +02:00
|
|
|
! ($activity = model('ActivityModel', false)->getActivityById($activityId)) instanceof Activity
|
2021-04-02 19:20:02 +02:00
|
|
|
) {
|
2021-05-06 16:00:48 +02:00
|
|
|
throw PageNotFoundException::forPageNotFound();
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $this->response
|
|
|
|
->setContentType('application/activity+json')
|
2021-05-06 16:00:48 +02:00
|
|
|
->setBody(json_encode($activity->payload, JSON_THROW_ON_ERROR));
|
2021-04-02 19:20:02 +02:00
|
|
|
}
|
|
|
|
}
|