From 79d73c508c4467b3b637f5b367a89f45439a2186 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 19 Nov 2024 02:24:00 -0700 Subject: [PATCH 1/6] Update Inbox --- app/Util/ActivityPub/Inbox.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Util/ActivityPub/Inbox.php b/app/Util/ActivityPub/Inbox.php index dd9b1578b..8cca59cfc 100644 --- a/app/Util/ActivityPub/Inbox.php +++ b/app/Util/ActivityPub/Inbox.php @@ -417,8 +417,8 @@ class Inbox return; } - $msg = $activity['content']; - $msgText = strip_tags($activity['content']); + $msg = Purify::clean($activity['content']); + $msgText = strip_tags($msg); if (Str::startsWith($msgText, '@'.$profile->username)) { $len = strlen('@'.$profile->username); From 0917953dbc5269a74abf5bf0cbd43d3e29fe9630 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 19 Nov 2024 02:29:11 -0700 Subject: [PATCH 2/6] Update Status, remove unused method --- app/Status.php | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/app/Status.php b/app/Status.php index d665464ae..8b69c199c 100644 --- a/app/Status.php +++ b/app/Status.php @@ -308,46 +308,6 @@ class Status extends Model return $this->comments()->orderBy('created_at', 'desc')->take(3); } - public function toActivityPubObject() - { - if($this->local == false) { - return; - } - $profile = $this->profile; - $to = $this->scopeToAudience('to'); - $cc = $this->scopeToAudience('cc'); - return [ - '@context' => 'https://www.w3.org/ns/activitystreams', - 'id' => $this->permalink(), - 'type' => 'Create', - 'actor' => $profile->permalink(), - 'published' => str_replace('+00:00', 'Z', $this->created_at->format(DATE_RFC3339_EXTENDED)), - 'to' => $to, - 'cc' => $cc, - 'object' => [ - 'id' => $this->url(), - 'type' => 'Note', - 'summary' => null, - 'inReplyTo' => null, - 'published' => str_replace('+00:00', 'Z', $this->created_at->format(DATE_RFC3339_EXTENDED)), - 'url' => $this->url(), - 'attributedTo' => $this->profile->url(), - 'to' => $to, - 'cc' => $cc, - 'sensitive' => (bool) $this->is_nsfw, - 'content' => $this->rendered, - 'attachment' => $this->media->map(function($media) { - return [ - 'type' => 'Document', - 'mediaType' => $media->mime, - 'url' => $media->url(), - 'name' => null - ]; - })->toArray() - ] - ]; - } - public function scopeToAudience($audience) { if(!in_array($audience, ['to', 'cc']) || $this->local == false) { From fb8dbb95dbc9be91d3e95da11a5be7a538bdd124 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 19 Nov 2024 02:53:39 -0700 Subject: [PATCH 3/6] Update Status caption render logic --- app/Http/Resources/StatusStateless.php | 92 +++---- .../ActivityPub/StatusTransformer.php | 87 +++--- .../ActivityPub/Verb/CreateNote.php | 258 +++++++++--------- app/Transformer/ActivityPub/Verb/Note.php | 244 +++++++++-------- app/Transformer/ActivityPub/Verb/Question.php | 191 ++++++------- .../ActivityPub/Verb/UpdateNote.php | 239 ++++++++-------- .../Api/Mastodon/v1/StatusTransformer.php | 78 +++--- .../Api/StatusStatelessTransformer.php | 115 ++++---- app/Transformer/Api/StatusTransformer.php | 123 ++++----- 9 files changed, 719 insertions(+), 708 deletions(-) diff --git a/app/Http/Resources/StatusStateless.php b/app/Http/Resources/StatusStateless.php index df451cc53..0a7bbe8d4 100644 --- a/app/Http/Resources/StatusStateless.php +++ b/app/Http/Resources/StatusStateless.php @@ -2,18 +2,17 @@ namespace App\Http\Resources; -use Illuminate\Http\Resources\Json\JsonResource; -use Cache; +use App\Models\CustomEmoji; use App\Services\AccountService; use App\Services\HashidService; use App\Services\LikeService; use App\Services\MediaService; use App\Services\MediaTagService; -use App\Services\StatusHashtagService; -use App\Services\StatusLabelService; -use App\Services\StatusMentionService; use App\Services\PollService; -use App\Models\CustomEmoji; +use App\Services\StatusHashtagService; +use App\Services\StatusMentionService; +use App\Util\Lexer\Autolink; +use Illuminate\Http\Resources\Json\JsonResource; class StatusStateless extends JsonResource { @@ -28,49 +27,50 @@ class StatusStateless extends JsonResource $status = $this; $taggedPeople = MediaTagService::get($status->id); $poll = $status->type === 'poll' ? PollService::get($status->id) : null; + $autoLink = $status->caption ? Autolink::create()->autolink($status->caption) : null; return [ - '_v' => 1, - 'id' => (string) $status->id, + '_v' => 1, + 'id' => (string) $status->id, //'gid' => $status->group_id ? (string) $status->group_id : null, - 'shortcode' => HashidService::encode($status->id), - 'uri' => $status->url(), - 'url' => $status->url(), - 'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, - 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null, - 'reblog' => null, - 'content' => $status->rendered ?? $status->caption, - 'content_text' => $status->caption, - 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), - 'emojis' => CustomEmoji::scan($status->caption), - 'reblogs_count' => $status->reblogs_count ?? 0, - 'favourites_count' => $status->likes_count ?? 0, - 'reblogged' => null, - 'favourited' => null, - 'muted' => null, - 'sensitive' => (bool) $status->is_nsfw, - 'spoiler_text' => $status->cw_summary ?? '', - 'visibility' => $status->scope ?? $status->visibility, - 'application' => [ - 'name' => 'web', - 'website' => null - ], - 'language' => null, - 'mentions' => StatusMentionService::get($status->id), - 'pf_type' => $status->type ?? $status->setType(), - 'reply_count' => (int) $status->reply_count, - 'comments_disabled' => (bool) $status->comments_disabled, - 'thread' => false, - 'replies' => [], - 'parent' => [], - 'place' => $status->place, - 'local' => (bool) $status->local, - 'taggedPeople' => $taggedPeople, - 'liked_by' => LikeService::likedBy($status), - 'media_attachments' => MediaService::get($status->id), - 'account' => AccountService::get($status->profile_id, true), - 'tags' => StatusHashtagService::statusTags($status->id), - 'poll' => $poll + 'shortcode' => HashidService::encode($status->id), + 'uri' => $status->url(), + 'url' => $status->url(), + 'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, + 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null, + 'reblog' => null, + 'content' => $autoLink, + 'content_text' => $status->caption, + 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), + 'emojis' => CustomEmoji::scan($status->caption), + 'reblogs_count' => $status->reblogs_count ?? 0, + 'favourites_count' => $status->likes_count ?? 0, + 'reblogged' => null, + 'favourited' => null, + 'muted' => null, + 'sensitive' => (bool) $status->is_nsfw, + 'spoiler_text' => $status->cw_summary ?? '', + 'visibility' => $status->scope ?? $status->visibility, + 'application' => [ + 'name' => 'web', + 'website' => null, + ], + 'language' => null, + 'mentions' => StatusMentionService::get($status->id), + 'pf_type' => $status->type ?? $status->setType(), + 'reply_count' => (int) $status->reply_count, + 'comments_disabled' => (bool) $status->comments_disabled, + 'thread' => false, + 'replies' => [], + 'parent' => [], + 'place' => $status->place, + 'local' => (bool) $status->local, + 'taggedPeople' => $taggedPeople, + 'liked_by' => LikeService::likedBy($status), + 'media_attachments' => MediaService::get($status->id), + 'account' => AccountService::get($status->profile_id, true), + 'tags' => StatusHashtagService::statusTags($status->id), + 'poll' => $poll, ]; } } diff --git a/app/Transformer/ActivityPub/StatusTransformer.php b/app/Transformer/ActivityPub/StatusTransformer.php index f5d5ea531..c0c378c7b 100644 --- a/app/Transformer/ActivityPub/StatusTransformer.php +++ b/app/Transformer/ActivityPub/StatusTransformer.php @@ -2,59 +2,62 @@ namespace App\Transformer\ActivityPub; -use App\Status; -use League\Fractal; use App\Services\MediaService; +use App\Status; +use App\Util\Lexer\Autolink; +use League\Fractal; class StatusTransformer extends Fractal\TransformerAbstract { public function transform(Status $status) { + $content = $status->caption ? Autolink::create()->autolink($status->caption) : null; + return [ - '@context' => [ - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - [ - 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', - 'featured' => [ - 'https://pixelfed.org/ns#featured' => ['@type' => '@id'], - ], + '@context' => [ + 'https://www.w3.org/ns/activitystreams', + 'https://w3id.org/security/v1', + [ + 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', + 'featured' => [ + 'https://pixelfed.org/ns#featured' => ['@type' => '@id'], + ], + ], ], - ], - 'id' => $status->url(), + 'id' => $status->url(), - // TODO: handle other types - 'type' => 'Note', + // TODO: handle other types + 'type' => 'Note', - // XXX: CW Title - 'summary' => null, - 'content' => $status->rendered ?? $status->caption, - 'inReplyTo' => null, + // XXX: CW Title + 'summary' => null, + 'content' => $content, + 'inReplyTo' => null, - // TODO: fix date format - 'published' => $status->created_at->toAtomString(), - 'url' => $status->url(), - 'attributedTo' => $status->profile->permalink(), - 'to' => [ - // TODO: handle proper scope - 'https://www.w3.org/ns/activitystreams#Public', - ], - 'cc' => [ - // TODO: add cc's - $status->profile->permalink('/followers'), - ], - 'sensitive' => (bool) $status->is_nsfw, - 'atomUri' => $status->url(), - 'inReplyToAtomUri' => null, - 'attachment' => MediaService::activitypub($status->id), - 'tag' => [], - 'location' => $status->place_id ? [ - 'type' => 'Place', - 'name' => $status->place->name, - 'longitude' => $status->place->long, - 'latitude' => $status->place->lat, - 'country' => $status->place->country + // TODO: fix date format + 'published' => $status->created_at->toAtomString(), + 'url' => $status->url(), + 'attributedTo' => $status->profile->permalink(), + 'to' => [ + // TODO: handle proper scope + 'https://www.w3.org/ns/activitystreams#Public', + ], + 'cc' => [ + // TODO: add cc's + $status->profile->permalink('/followers'), + ], + 'sensitive' => (bool) $status->is_nsfw, + 'atomUri' => $status->url(), + 'inReplyToAtomUri' => null, + 'attachment' => MediaService::activitypub($status->id), + 'tag' => [], + 'location' => $status->place_id ? [ + 'type' => 'Place', + 'name' => $status->place->name, + 'longitude' => $status->place->long, + 'latitude' => $status->place->lat, + 'country' => $status->place->country, ] : null, - ]; + ]; } } diff --git a/app/Transformer/ActivityPub/Verb/CreateNote.php b/app/Transformer/ActivityPub/Verb/CreateNote.php index 55fdfa8f4..287393572 100644 --- a/app/Transformer/ActivityPub/Verb/CreateNote.php +++ b/app/Transformer/ActivityPub/Verb/CreateNote.php @@ -2,140 +2,144 @@ namespace App\Transformer\ActivityPub\Verb; -use App\Status; -use League\Fractal; use App\Models\CustomEmoji; +use App\Status; +use App\Util\Lexer\Autolink; use Illuminate\Support\Str; +use League\Fractal; class CreateNote extends Fractal\TransformerAbstract { - public function transform(Status $status) - { - $mentions = $status->mentions->map(function ($mention) { - $webfinger = $mention->emailUrl(); - $name = Str::startsWith($webfinger, '@') ? - $webfinger : - '@' . $webfinger; - return [ - 'type' => 'Mention', - 'href' => $mention->permalink(), - 'name' => $name - ]; - })->toArray(); + public function transform(Status $status) + { + $mentions = $status->mentions->map(function ($mention) { + $webfinger = $mention->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@'.$webfinger; - if($status->in_reply_to_id != null) { - $parent = $status->parent()->profile; - if($parent) { - $webfinger = $parent->emailUrl(); - $name = Str::startsWith($webfinger, '@') ? - $webfinger : - '@' . $webfinger; - $reply = [ - 'type' => 'Mention', - 'href' => $parent->permalink(), - 'name' => $name - ]; - $mentions = array_merge($reply, $mentions); - } - } + return [ + 'type' => 'Mention', + 'href' => $mention->permalink(), + 'name' => $name, + ]; + })->toArray(); - $hashtags = $status->hashtags->map(function ($hashtag) { - return [ - 'type' => 'Hashtag', - 'href' => $hashtag->url(), - 'name' => "#{$hashtag->name}", - ]; - })->toArray(); + if ($status->in_reply_to_id != null) { + $parent = $status->parent()->profile; + if ($parent) { + $webfinger = $parent->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@'.$webfinger; + $reply = [ + 'type' => 'Mention', + 'href' => $parent->permalink(), + 'name' => $name, + ]; + $mentions = array_merge($reply, $mentions); + } + } - $emojis = CustomEmoji::scan($status->caption, true) ?? []; - $emoji = array_merge($emojis, $mentions); - $tags = array_merge($emoji, $hashtags); + $hashtags = $status->hashtags->map(function ($hashtag) { + return [ + 'type' => 'Hashtag', + 'href' => $hashtag->url(), + 'name' => "#{$hashtag->name}", + ]; + })->toArray(); - return [ - '@context' => [ - 'https://w3id.org/security/v1', - 'https://www.w3.org/ns/activitystreams', - [ - 'Hashtag' => 'as:Hashtag', - 'sensitive' => 'as:sensitive', - 'schema' => 'http://schema.org/', - 'pixelfed' => 'http://pixelfed.org/ns#', - 'commentsEnabled' => [ - '@id' => 'pixelfed:commentsEnabled', - '@type' => 'schema:Boolean' - ], - 'capabilities' => [ - '@id' => 'pixelfed:capabilities', - '@container' => '@set' - ], - 'announce' => [ - '@id' => 'pixelfed:canAnnounce', - '@type' => '@id' - ], - 'like' => [ - '@id' => 'pixelfed:canLike', - '@type' => '@id' - ], - 'reply' => [ - '@id' => 'pixelfed:canReply', - '@type' => '@id' - ], - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji', - 'blurhash' => 'toot:blurhash', - ] - ], - 'id' => $status->permalink(), - 'type' => 'Create', - 'actor' => $status->profile->permalink(), - 'published' => $status->created_at->toAtomString(), - 'to' => $status->scopeToAudience('to'), - 'cc' => $status->scopeToAudience('cc'), - 'object' => [ - 'id' => $status->url(), - 'type' => 'Note', - 'summary' => $status->is_nsfw ? $status->cw_summary : null, - 'content' => $status->rendered ?? $status->caption, - 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, - 'published' => $status->created_at->toAtomString(), - 'url' => $status->url(), - 'attributedTo' => $status->profile->permalink(), - 'to' => $status->scopeToAudience('to'), - 'cc' => $status->scopeToAudience('cc'), - 'sensitive' => (bool) $status->is_nsfw, - 'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) { - $res = [ - 'type' => $media->activityVerb(), - 'mediaType' => $media->mime, - 'url' => $media->url(), - 'name' => $media->caption, - ]; - if($media->blurhash) { - $res['blurhash'] = $media->blurhash; - } - if($media->width) { - $res['width'] = $media->width; - } - if($media->height) { - $res['height'] = $media->height; - } - return $res; - })->toArray(), - 'tag' => $tags, - 'commentsEnabled' => (bool) !$status->comments_disabled, - 'capabilities' => [ - 'announce' => 'https://www.w3.org/ns/activitystreams#Public', - 'like' => 'https://www.w3.org/ns/activitystreams#Public', - 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public' - ], - 'location' => $status->place_id ? [ - 'type' => 'Place', - 'name' => $status->place->name, - 'longitude' => $status->place->long, - 'latitude' => $status->place->lat, - 'country' => $status->place->country - ] : null, - ] - ]; - } + $emojis = CustomEmoji::scan($status->caption, true) ?? []; + $emoji = array_merge($emojis, $mentions); + $tags = array_merge($emoji, $hashtags); + $content = $status->caption ? Autolink::create()->autolink($status->caption) : null; + + return [ + '@context' => [ + 'https://w3id.org/security/v1', + 'https://www.w3.org/ns/activitystreams', + [ + 'Hashtag' => 'as:Hashtag', + 'sensitive' => 'as:sensitive', + 'schema' => 'http://schema.org/', + 'pixelfed' => 'http://pixelfed.org/ns#', + 'commentsEnabled' => [ + '@id' => 'pixelfed:commentsEnabled', + '@type' => 'schema:Boolean', + ], + 'capabilities' => [ + '@id' => 'pixelfed:capabilities', + '@container' => '@set', + ], + 'announce' => [ + '@id' => 'pixelfed:canAnnounce', + '@type' => '@id', + ], + 'like' => [ + '@id' => 'pixelfed:canLike', + '@type' => '@id', + ], + 'reply' => [ + '@id' => 'pixelfed:canReply', + '@type' => '@id', + ], + 'toot' => 'http://joinmastodon.org/ns#', + 'Emoji' => 'toot:Emoji', + 'blurhash' => 'toot:blurhash', + ], + ], + 'id' => $status->permalink(), + 'type' => 'Create', + 'actor' => $status->profile->permalink(), + 'published' => $status->created_at->toAtomString(), + 'to' => $status->scopeToAudience('to'), + 'cc' => $status->scopeToAudience('cc'), + 'object' => [ + 'id' => $status->url(), + 'type' => 'Note', + 'summary' => $status->is_nsfw ? $status->cw_summary : null, + 'content' => $content, + 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, + 'published' => $status->created_at->toAtomString(), + 'url' => $status->url(), + 'attributedTo' => $status->profile->permalink(), + 'to' => $status->scopeToAudience('to'), + 'cc' => $status->scopeToAudience('cc'), + 'sensitive' => (bool) $status->is_nsfw, + 'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) { + $res = [ + 'type' => $media->activityVerb(), + 'mediaType' => $media->mime, + 'url' => $media->url(), + 'name' => $media->caption, + ]; + if ($media->blurhash) { + $res['blurhash'] = $media->blurhash; + } + if ($media->width) { + $res['width'] = $media->width; + } + if ($media->height) { + $res['height'] = $media->height; + } + + return $res; + })->toArray(), + 'tag' => $tags, + 'commentsEnabled' => (bool) ! $status->comments_disabled, + 'capabilities' => [ + 'announce' => 'https://www.w3.org/ns/activitystreams#Public', + 'like' => 'https://www.w3.org/ns/activitystreams#Public', + 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public', + ], + 'location' => $status->place_id ? [ + 'type' => 'Place', + 'name' => $status->place->name, + 'longitude' => $status->place->long, + 'latitude' => $status->place->lat, + 'country' => $status->place->country, + ] : null, + ], + ]; + } } diff --git a/app/Transformer/ActivityPub/Verb/Note.php b/app/Transformer/ActivityPub/Verb/Note.php index 1350641d4..52656efec 100644 --- a/app/Transformer/ActivityPub/Verb/Note.php +++ b/app/Transformer/ActivityPub/Verb/Note.php @@ -2,133 +2,137 @@ namespace App\Transformer\ActivityPub\Verb; -use App\Status; -use League\Fractal; use App\Models\CustomEmoji; +use App\Status; +use App\Util\Lexer\Autolink; use Illuminate\Support\Str; +use League\Fractal; class Note extends Fractal\TransformerAbstract { - public function transform(Status $status) - { + public function transform(Status $status) + { - $mentions = $status->mentions->map(function ($mention) { - $webfinger = $mention->emailUrl(); - $name = Str::startsWith($webfinger, '@') ? - $webfinger : - '@' . $webfinger; - return [ - 'type' => 'Mention', - 'href' => $mention->permalink(), - 'name' => $name - ]; - })->toArray(); + $mentions = $status->mentions->map(function ($mention) { + $webfinger = $mention->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@'.$webfinger; - if($status->in_reply_to_id != null) { - $parent = $status->parent()->profile; - if($parent) { - $webfinger = $parent->emailUrl(); - $name = Str::startsWith($webfinger, '@') ? - $webfinger : - '@' . $webfinger; - $reply = [ - 'type' => 'Mention', - 'href' => $parent->permalink(), - 'name' => $name - ]; - array_push($mentions, $reply); - } - } - - $hashtags = $status->hashtags->map(function ($hashtag) { - return [ - 'type' => 'Hashtag', - 'href' => $hashtag->url(), - 'name' => "#{$hashtag->name}", - ]; - })->toArray(); + return [ + 'type' => 'Mention', + 'href' => $mention->permalink(), + 'name' => $name, + ]; + })->toArray(); - $emojis = CustomEmoji::scan($status->caption, true) ?? []; - $emoji = array_merge($emojis, $mentions); - $tags = array_merge($emoji, $hashtags); + if ($status->in_reply_to_id != null) { + $parent = $status->parent()->profile; + if ($parent) { + $webfinger = $parent->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@'.$webfinger; + $reply = [ + 'type' => 'Mention', + 'href' => $parent->permalink(), + 'name' => $name, + ]; + array_push($mentions, $reply); + } + } - return [ - '@context' => [ - 'https://w3id.org/security/v1', - 'https://www.w3.org/ns/activitystreams', - [ - 'Hashtag' => 'as:Hashtag', - 'sensitive' => 'as:sensitive', - 'schema' => 'http://schema.org/', - 'pixelfed' => 'http://pixelfed.org/ns#', - 'commentsEnabled' => [ - '@id' => 'pixelfed:commentsEnabled', - '@type' => 'schema:Boolean' - ], - 'capabilities' => [ - '@id' => 'pixelfed:capabilities', - '@container' => '@set' - ], - 'announce' => [ - '@id' => 'pixelfed:canAnnounce', - '@type' => '@id' - ], - 'like' => [ - '@id' => 'pixelfed:canLike', - '@type' => '@id' - ], - 'reply' => [ - '@id' => 'pixelfed:canReply', - '@type' => '@id' - ], - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji', - 'blurhash' => 'toot:blurhash', - ] - ], - 'id' => $status->url(), - 'type' => 'Note', - 'summary' => $status->is_nsfw ? $status->cw_summary : null, - 'content' => $status->rendered ?? $status->caption, - 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, - 'published' => $status->created_at->toAtomString(), - 'url' => $status->url(), - 'attributedTo' => $status->profile->permalink(), - 'to' => $status->scopeToAudience('to'), - 'cc' => $status->scopeToAudience('cc'), - 'sensitive' => (bool) $status->is_nsfw, - 'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) { - $res = [ - 'type' => $media->activityVerb(), - 'mediaType' => $media->mime, - 'url' => $media->url(), - 'name' => $media->caption, - ]; - if($media->blurhash) { - $res['blurhash'] = $media->blurhash; - } - if($media->width) { - $res['width'] = $media->width; - } - if($media->height) { - $res['height'] = $media->height; - } - return $res; - })->toArray(), - 'tag' => $tags, - 'commentsEnabled' => (bool) !$status->comments_disabled, - 'capabilities' => [ - 'announce' => 'https://www.w3.org/ns/activitystreams#Public', - 'like' => 'https://www.w3.org/ns/activitystreams#Public', - 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public' - ], - 'location' => $status->place_id ? [ - 'type' => 'Place', - 'name' => $status->place->name, - 'longitude' => $status->place->long, - 'latitude' => $status->place->lat, - 'country' => $status->place->country - ] : null, - ]; - } + $hashtags = $status->hashtags->map(function ($hashtag) { + return [ + 'type' => 'Hashtag', + 'href' => $hashtag->url(), + 'name' => "#{$hashtag->name}", + ]; + })->toArray(); + + $emojis = CustomEmoji::scan($status->caption, true) ?? []; + $emoji = array_merge($emojis, $mentions); + $tags = array_merge($emoji, $hashtags); + $content = $status->caption ? Autolink::create()->autolink($status->caption) : null; + + return [ + '@context' => [ + 'https://w3id.org/security/v1', + 'https://www.w3.org/ns/activitystreams', + [ + 'Hashtag' => 'as:Hashtag', + 'sensitive' => 'as:sensitive', + 'schema' => 'http://schema.org/', + 'pixelfed' => 'http://pixelfed.org/ns#', + 'commentsEnabled' => [ + '@id' => 'pixelfed:commentsEnabled', + '@type' => 'schema:Boolean', + ], + 'capabilities' => [ + '@id' => 'pixelfed:capabilities', + '@container' => '@set', + ], + 'announce' => [ + '@id' => 'pixelfed:canAnnounce', + '@type' => '@id', + ], + 'like' => [ + '@id' => 'pixelfed:canLike', + '@type' => '@id', + ], + 'reply' => [ + '@id' => 'pixelfed:canReply', + '@type' => '@id', + ], + 'toot' => 'http://joinmastodon.org/ns#', + 'Emoji' => 'toot:Emoji', + 'blurhash' => 'toot:blurhash', + ], + ], + 'id' => $status->url(), + 'type' => 'Note', + 'summary' => $status->is_nsfw ? $status->cw_summary : null, + 'content' => $content, + 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, + 'published' => $status->created_at->toAtomString(), + 'url' => $status->url(), + 'attributedTo' => $status->profile->permalink(), + 'to' => $status->scopeToAudience('to'), + 'cc' => $status->scopeToAudience('cc'), + 'sensitive' => (bool) $status->is_nsfw, + 'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) { + $res = [ + 'type' => $media->activityVerb(), + 'mediaType' => $media->mime, + 'url' => $media->url(), + 'name' => $media->caption, + ]; + if ($media->blurhash) { + $res['blurhash'] = $media->blurhash; + } + if ($media->width) { + $res['width'] = $media->width; + } + if ($media->height) { + $res['height'] = $media->height; + } + + return $res; + })->toArray(), + 'tag' => $tags, + 'commentsEnabled' => (bool) ! $status->comments_disabled, + 'capabilities' => [ + 'announce' => 'https://www.w3.org/ns/activitystreams#Public', + 'like' => 'https://www.w3.org/ns/activitystreams#Public', + 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public', + ], + 'location' => $status->place_id ? [ + 'type' => 'Place', + 'name' => $status->place->name, + 'longitude' => $status->place->long, + 'latitude' => $status->place->lat, + 'country' => $status->place->country, + ] : null, + ]; + } } diff --git a/app/Transformer/ActivityPub/Verb/Question.php b/app/Transformer/ActivityPub/Verb/Question.php index fb9313fb1..3d53ebcb5 100644 --- a/app/Transformer/ActivityPub/Verb/Question.php +++ b/app/Transformer/ActivityPub/Verb/Question.php @@ -3,104 +3,107 @@ namespace App\Transformer\ActivityPub\Verb; use App\Status; -use League\Fractal; +use App\Util\Lexer\Autolink; use Illuminate\Support\Str; +use League\Fractal; class Question extends Fractal\TransformerAbstract { - public function transform(Status $status) - { - $mentions = $status->mentions->map(function ($mention) { - $webfinger = $mention->emailUrl(); - $name = Str::startsWith($webfinger, '@') ? - $webfinger : - '@' . $webfinger; - return [ - 'type' => 'Mention', - 'href' => $mention->permalink(), - 'name' => $name - ]; - })->toArray(); + public function transform(Status $status) + { + $mentions = $status->mentions->map(function ($mention) { + $webfinger = $mention->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@'.$webfinger; - $hashtags = $status->hashtags->map(function ($hashtag) { - return [ - 'type' => 'Hashtag', - 'href' => $hashtag->url(), - 'name' => "#{$hashtag->name}", - ]; - })->toArray(); - $tags = array_merge($mentions, $hashtags); + return [ + 'type' => 'Mention', + 'href' => $mention->permalink(), + 'name' => $name, + ]; + })->toArray(); - return [ - '@context' => [ - 'https://w3id.org/security/v1', - 'https://www.w3.org/ns/activitystreams', - [ - 'Hashtag' => 'as:Hashtag', - 'sensitive' => 'as:sensitive', - 'schema' => 'http://schema.org/', - 'pixelfed' => 'http://pixelfed.org/ns#', - 'commentsEnabled' => [ - '@id' => 'pixelfed:commentsEnabled', - '@type' => 'schema:Boolean' - ], - 'capabilities' => [ - '@id' => 'pixelfed:capabilities', - '@container' => '@set' - ], - 'announce' => [ - '@id' => 'pixelfed:canAnnounce', - '@type' => '@id' - ], - 'like' => [ - '@id' => 'pixelfed:canLike', - '@type' => '@id' - ], - 'reply' => [ - '@id' => 'pixelfed:canReply', - '@type' => '@id' - ], - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji' - ] - ], - 'id' => $status->url(), - 'type' => 'Question', - 'summary' => null, - 'content' => $status->rendered ?? $status->caption, - 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, - 'published' => $status->created_at->toAtomString(), - 'url' => $status->url(), - 'attributedTo' => $status->profile->permalink(), - 'to' => $status->scopeToAudience('to'), - 'cc' => $status->scopeToAudience('cc'), - 'sensitive' => (bool) $status->is_nsfw, - 'attachment' => [], - 'tag' => $tags, - 'commentsEnabled' => (bool) !$status->comments_disabled, - 'capabilities' => [ - 'announce' => 'https://www.w3.org/ns/activitystreams#Public', - 'like' => 'https://www.w3.org/ns/activitystreams#Public', - 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public' - ], - 'location' => $status->place_id ? [ - 'type' => 'Place', - 'name' => $status->place->name, - 'longitude' => $status->place->long, - 'latitude' => $status->place->lat, - 'country' => $status->place->country - ] : null, - 'endTime' => $status->poll->expires_at->toAtomString(), - 'oneOf' => collect($status->poll->poll_options)->map(function($option, $index) use($status) { - return [ - 'type' => 'Note', - 'name' => $option, - 'replies' => [ - 'type' => 'Collection', - 'totalItems' => $status->poll->cached_tallies[$index] - ] - ]; - }) - ]; - } + $hashtags = $status->hashtags->map(function ($hashtag) { + return [ + 'type' => 'Hashtag', + 'href' => $hashtag->url(), + 'name' => "#{$hashtag->name}", + ]; + })->toArray(); + $tags = array_merge($mentions, $hashtags); + $content = $status->caption ? Autolink::create()->autolink($status->caption) : null; + + return [ + '@context' => [ + 'https://w3id.org/security/v1', + 'https://www.w3.org/ns/activitystreams', + [ + 'Hashtag' => 'as:Hashtag', + 'sensitive' => 'as:sensitive', + 'schema' => 'http://schema.org/', + 'pixelfed' => 'http://pixelfed.org/ns#', + 'commentsEnabled' => [ + '@id' => 'pixelfed:commentsEnabled', + '@type' => 'schema:Boolean', + ], + 'capabilities' => [ + '@id' => 'pixelfed:capabilities', + '@container' => '@set', + ], + 'announce' => [ + '@id' => 'pixelfed:canAnnounce', + '@type' => '@id', + ], + 'like' => [ + '@id' => 'pixelfed:canLike', + '@type' => '@id', + ], + 'reply' => [ + '@id' => 'pixelfed:canReply', + '@type' => '@id', + ], + 'toot' => 'http://joinmastodon.org/ns#', + 'Emoji' => 'toot:Emoji', + ], + ], + 'id' => $status->url(), + 'type' => 'Question', + 'summary' => null, + 'content' => $content, + 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, + 'published' => $status->created_at->toAtomString(), + 'url' => $status->url(), + 'attributedTo' => $status->profile->permalink(), + 'to' => $status->scopeToAudience('to'), + 'cc' => $status->scopeToAudience('cc'), + 'sensitive' => (bool) $status->is_nsfw, + 'attachment' => [], + 'tag' => $tags, + 'commentsEnabled' => (bool) ! $status->comments_disabled, + 'capabilities' => [ + 'announce' => 'https://www.w3.org/ns/activitystreams#Public', + 'like' => 'https://www.w3.org/ns/activitystreams#Public', + 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public', + ], + 'location' => $status->place_id ? [ + 'type' => 'Place', + 'name' => $status->place->name, + 'longitude' => $status->place->long, + 'latitude' => $status->place->lat, + 'country' => $status->place->country, + ] : null, + 'endTime' => $status->poll->expires_at->toAtomString(), + 'oneOf' => collect($status->poll->poll_options)->map(function ($option, $index) use ($status) { + return [ + 'type' => 'Note', + 'name' => $option, + 'replies' => [ + 'type' => 'Collection', + 'totalItems' => $status->poll->cached_tallies[$index], + ], + ]; + }), + ]; + } } diff --git a/app/Transformer/ActivityPub/Verb/UpdateNote.php b/app/Transformer/ActivityPub/Verb/UpdateNote.php index bdbb20c45..09d0b5a2b 100644 --- a/app/Transformer/ActivityPub/Verb/UpdateNote.php +++ b/app/Transformer/ActivityPub/Verb/UpdateNote.php @@ -2,132 +2,135 @@ namespace App\Transformer\ActivityPub\Verb; -use App\Status; -use League\Fractal; use App\Models\CustomEmoji; +use App\Status; +use App\Util\Lexer\Autolink; use Illuminate\Support\Str; +use League\Fractal; class UpdateNote extends Fractal\TransformerAbstract { - public function transform(Status $status) - { - $mentions = $status->mentions->map(function ($mention) { - $webfinger = $mention->emailUrl(); - $name = Str::startsWith($webfinger, '@') ? - $webfinger : - '@' . $webfinger; - return [ - 'type' => 'Mention', - 'href' => $mention->permalink(), - 'name' => $name - ]; - })->toArray(); + public function transform(Status $status) + { + $mentions = $status->mentions->map(function ($mention) { + $webfinger = $mention->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@'.$webfinger; - if($status->in_reply_to_id != null) { - $parent = $status->parent()->profile; - if($parent) { - $webfinger = $parent->emailUrl(); - $name = Str::startsWith($webfinger, '@') ? - $webfinger : - '@' . $webfinger; - $reply = [ - 'type' => 'Mention', - 'href' => $parent->permalink(), - 'name' => $name - ]; - $mentions = array_merge($reply, $mentions); - } - } + return [ + 'type' => 'Mention', + 'href' => $mention->permalink(), + 'name' => $name, + ]; + })->toArray(); - $hashtags = $status->hashtags->map(function ($hashtag) { - return [ - 'type' => 'Hashtag', - 'href' => $hashtag->url(), - 'name' => "#{$hashtag->name}", - ]; - })->toArray(); + if ($status->in_reply_to_id != null) { + $parent = $status->parent()->profile; + if ($parent) { + $webfinger = $parent->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@'.$webfinger; + $reply = [ + 'type' => 'Mention', + 'href' => $parent->permalink(), + 'name' => $name, + ]; + $mentions = array_merge($reply, $mentions); + } + } - $emojis = CustomEmoji::scan($status->caption, true) ?? []; - $emoji = array_merge($emojis, $mentions); - $tags = array_merge($emoji, $hashtags); + $hashtags = $status->hashtags->map(function ($hashtag) { + return [ + 'type' => 'Hashtag', + 'href' => $hashtag->url(), + 'name' => "#{$hashtag->name}", + ]; + })->toArray(); - $latestEdit = $status->edits()->latest()->first(); + $emojis = CustomEmoji::scan($status->caption, true) ?? []; + $emoji = array_merge($emojis, $mentions); + $tags = array_merge($emoji, $hashtags); - return [ - '@context' => [ - 'https://w3id.org/security/v1', - 'https://www.w3.org/ns/activitystreams', - [ - 'Hashtag' => 'as:Hashtag', - 'sensitive' => 'as:sensitive', - 'schema' => 'http://schema.org/', - 'pixelfed' => 'http://pixelfed.org/ns#', - 'commentsEnabled' => [ - '@id' => 'pixelfed:commentsEnabled', - '@type' => 'schema:Boolean' - ], - 'capabilities' => [ - '@id' => 'pixelfed:capabilities', - '@container' => '@set' - ], - 'announce' => [ - '@id' => 'pixelfed:canAnnounce', - '@type' => '@id' - ], - 'like' => [ - '@id' => 'pixelfed:canLike', - '@type' => '@id' - ], - 'reply' => [ - '@id' => 'pixelfed:canReply', - '@type' => '@id' - ], - 'toot' => 'http://joinmastodon.org/ns#', - 'Emoji' => 'toot:Emoji' - ] - ], - 'id' => $status->permalink('#updates/' . $latestEdit->id), - 'type' => 'Update', - 'actor' => $status->profile->permalink(), - 'published' => $latestEdit->created_at->toAtomString(), - 'to' => $status->scopeToAudience('to'), - 'cc' => $status->scopeToAudience('cc'), - 'object' => [ - 'id' => $status->url(), - 'type' => 'Note', - 'summary' => $status->is_nsfw ? $status->cw_summary : null, - 'content' => $status->rendered ?? $status->caption, - 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, - 'published' => $status->created_at->toAtomString(), - 'url' => $status->url(), - 'attributedTo' => $status->profile->permalink(), - 'to' => $status->scopeToAudience('to'), - 'cc' => $status->scopeToAudience('cc'), - 'sensitive' => (bool) $status->is_nsfw, - 'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) { - return [ - 'type' => $media->activityVerb(), - 'mediaType' => $media->mime, - 'url' => $media->url(), - 'name' => $media->caption, - ]; - })->toArray(), - 'tag' => $tags, - 'commentsEnabled' => (bool) !$status->comments_disabled, - 'updated' => $latestEdit->created_at->toAtomString(), - 'capabilities' => [ - 'announce' => 'https://www.w3.org/ns/activitystreams#Public', - 'like' => 'https://www.w3.org/ns/activitystreams#Public', - 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public' - ], - 'location' => $status->place_id ? [ - 'type' => 'Place', - 'name' => $status->place->name, - 'longitude' => $status->place->long, - 'latitude' => $status->place->lat, - 'country' => $status->place->country - ] : null, - ] - ]; - } + $content = $status->caption ? Autolink::create()->autolink($status->caption) : null; + $latestEdit = $status->edits()->latest()->first(); + + return [ + '@context' => [ + 'https://w3id.org/security/v1', + 'https://www.w3.org/ns/activitystreams', + [ + 'Hashtag' => 'as:Hashtag', + 'sensitive' => 'as:sensitive', + 'schema' => 'http://schema.org/', + 'pixelfed' => 'http://pixelfed.org/ns#', + 'commentsEnabled' => [ + '@id' => 'pixelfed:commentsEnabled', + '@type' => 'schema:Boolean', + ], + 'capabilities' => [ + '@id' => 'pixelfed:capabilities', + '@container' => '@set', + ], + 'announce' => [ + '@id' => 'pixelfed:canAnnounce', + '@type' => '@id', + ], + 'like' => [ + '@id' => 'pixelfed:canLike', + '@type' => '@id', + ], + 'reply' => [ + '@id' => 'pixelfed:canReply', + '@type' => '@id', + ], + 'toot' => 'http://joinmastodon.org/ns#', + 'Emoji' => 'toot:Emoji', + ], + ], + 'id' => $status->permalink('#updates/'.$latestEdit->id), + 'type' => 'Update', + 'actor' => $status->profile->permalink(), + 'published' => $latestEdit->created_at->toAtomString(), + 'to' => $status->scopeToAudience('to'), + 'cc' => $status->scopeToAudience('cc'), + 'object' => [ + 'id' => $status->url(), + 'type' => 'Note', + 'summary' => $status->is_nsfw ? $status->cw_summary : null, + 'content' => $content, + 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, + 'published' => $status->created_at->toAtomString(), + 'url' => $status->url(), + 'attributedTo' => $status->profile->permalink(), + 'to' => $status->scopeToAudience('to'), + 'cc' => $status->scopeToAudience('cc'), + 'sensitive' => (bool) $status->is_nsfw, + 'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) { + return [ + 'type' => $media->activityVerb(), + 'mediaType' => $media->mime, + 'url' => $media->url(), + 'name' => $media->caption, + ]; + })->toArray(), + 'tag' => $tags, + 'commentsEnabled' => (bool) ! $status->comments_disabled, + 'updated' => $latestEdit->created_at->toAtomString(), + 'capabilities' => [ + 'announce' => 'https://www.w3.org/ns/activitystreams#Public', + 'like' => 'https://www.w3.org/ns/activitystreams#Public', + 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public', + ], + 'location' => $status->place_id ? [ + 'type' => 'Place', + 'name' => $status->place->name, + 'longitude' => $status->place->long, + 'latitude' => $status->place->lat, + 'country' => $status->place->country, + ] : null, + ], + ]; + } } diff --git a/app/Transformer/Api/Mastodon/v1/StatusTransformer.php b/app/Transformer/Api/Mastodon/v1/StatusTransformer.php index bfbc3d58b..4516bd874 100644 --- a/app/Transformer/Api/Mastodon/v1/StatusTransformer.php +++ b/app/Transformer/Api/Mastodon/v1/StatusTransformer.php @@ -2,48 +2,50 @@ namespace App\Transformer\Api\Mastodon\v1; -use App\Status; -use League\Fractal; -use Cache; use App\Services\MediaService; use App\Services\ProfileService; use App\Services\StatusHashtagService; +use App\Status; +use App\Util\Lexer\Autolink; +use League\Fractal; class StatusTransformer extends Fractal\TransformerAbstract { - public function transform(Status $status) - { - return [ - 'id' => (string) $status->id, - 'created_at' => $status->created_at->toJSON(), - 'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, - 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null, - 'sensitive' => (bool) $status->is_nsfw, - 'spoiler_text' => $status->cw_summary ?? '', - 'visibility' => $status->visibility ?? $status->scope, - 'language' => 'en', - 'uri' => $status->permalink(''), - 'url' => $status->url(), - 'replies_count' => $status->reply_count ?? 0, - 'reblogs_count' => $status->reblogs_count ?? 0, - 'favourites_count' => $status->likes_count ?? 0, - 'reblogged' => $status->shared(), - 'favourited' => $status->liked(), - 'muted' => false, - 'bookmarked' => false, - 'content' => $status->rendered ?? $status->caption ?? '', - 'reblog' => null, - 'application' => [ - 'name' => 'web', - 'website' => null - ], - 'mentions' => [], - 'emojis' => [], - 'card' => null, - 'poll' => null, - 'media_attachments' => MediaService::get($status->id), - 'account' => ProfileService::get($status->profile_id, true), - 'tags' => StatusHashtagService::statusTags($status->id), - ]; - } + public function transform(Status $status) + { + $content = $status->caption ? Autolink::create()->autolink($status->caption) : null; + + return [ + 'id' => (string) $status->id, + 'created_at' => $status->created_at->toJSON(), + 'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, + 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null, + 'sensitive' => (bool) $status->is_nsfw, + 'spoiler_text' => $status->cw_summary ?? '', + 'visibility' => $status->visibility ?? $status->scope, + 'language' => 'en', + 'uri' => $status->permalink(''), + 'url' => $status->url(), + 'replies_count' => $status->reply_count ?? 0, + 'reblogs_count' => $status->reblogs_count ?? 0, + 'favourites_count' => $status->likes_count ?? 0, + 'reblogged' => $status->shared(), + 'favourited' => $status->liked(), + 'muted' => false, + 'bookmarked' => false, + 'content' => $content, + 'reblog' => null, + 'application' => [ + 'name' => 'web', + 'website' => null, + ], + 'mentions' => [], + 'emojis' => [], + 'card' => null, + 'poll' => null, + 'media_attachments' => MediaService::get($status->id), + 'account' => ProfileService::get($status->profile_id, true), + 'tags' => StatusHashtagService::statusTags($status->id), + ]; + } } diff --git a/app/Transformer/Api/StatusStatelessTransformer.php b/app/Transformer/Api/StatusStatelessTransformer.php index 3c2c02d60..bf6e7597e 100644 --- a/app/Transformer/Api/StatusStatelessTransformer.php +++ b/app/Transformer/Api/StatusStatelessTransformer.php @@ -2,76 +2,73 @@ namespace App\Transformer\Api; -use App\Status; -use League\Fractal; -use Cache; +use App\Models\CustomEmoji; use App\Services\AccountService; use App\Services\HashidService; use App\Services\LikeService; use App\Services\MediaService; use App\Services\MediaTagService; -use App\Services\StatusService; +use App\Services\PollService; use App\Services\StatusHashtagService; use App\Services\StatusLabelService; use App\Services\StatusMentionService; -use App\Services\PollService; -use App\Models\CustomEmoji; +use App\Services\StatusService; +use App\Status; use App\Util\Lexer\Autolink; +use League\Fractal; class StatusStatelessTransformer extends Fractal\TransformerAbstract { - public function transform(Status $status) - { - $taggedPeople = MediaTagService::get($status->id); - $poll = $status->type === 'poll' ? PollService::get($status->id) : null; - $rendered = config('exp.autolink') ? - ( $status->caption ? Autolink::create()->autolink($status->caption) : '' ) : - ( $status->rendered ?? $status->caption ); + public function transform(Status $status) + { + $taggedPeople = MediaTagService::get($status->id); + $poll = $status->type === 'poll' ? PollService::get($status->id) : null; + $rendered = $status->caption ? Autolink::create()->autolink($status->caption) : null; - return [ - '_v' => 1, - 'id' => (string) $status->id, - //'gid' => $status->group_id ? (string) $status->group_id : null, - 'shortcode' => HashidService::encode($status->id), - 'uri' => $status->url(), - 'url' => $status->url(), - 'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, - 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null, - 'reblog' => $status->reblog_of_id ? StatusService::get($status->reblog_of_id, false) : null, - 'content' => $rendered, - 'content_text' => $status->caption, - 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), - 'emojis' => CustomEmoji::scan($status->caption), - 'reblogs_count' => $status->reblogs_count ?? 0, - 'favourites_count' => $status->likes_count ?? 0, - 'reblogged' => null, - 'favourited' => null, - 'muted' => null, - 'sensitive' => (bool) $status->is_nsfw, - 'spoiler_text' => $status->cw_summary ?? '', - 'visibility' => $status->scope ?? $status->visibility, - 'application' => [ - 'name' => 'web', - 'website' => null - ], - 'language' => null, - 'mentions' => StatusMentionService::get($status->id), - 'pf_type' => $status->type ?? $status->setType(), - 'reply_count' => (int) $status->reply_count, - 'comments_disabled' => (bool) $status->comments_disabled, - 'thread' => false, - 'replies' => [], - 'parent' => [], - 'place' => $status->place, - 'local' => (bool) $status->local, - 'taggedPeople' => $taggedPeople, - 'label' => StatusLabelService::get($status), - 'liked_by' => LikeService::likedBy($status), - 'media_attachments' => MediaService::get($status->id), - 'account' => AccountService::get($status->profile_id, true), - 'tags' => StatusHashtagService::statusTags($status->id), - 'poll' => $poll, - 'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null, - ]; - } + return [ + '_v' => 1, + 'id' => (string) $status->id, + //'gid' => $status->group_id ? (string) $status->group_id : null, + 'shortcode' => HashidService::encode($status->id), + 'uri' => $status->url(), + 'url' => $status->url(), + 'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, + 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null, + 'reblog' => $status->reblog_of_id ? StatusService::get($status->reblog_of_id, false) : null, + 'content' => $rendered, + 'content_text' => $status->caption, + 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), + 'emojis' => CustomEmoji::scan($status->caption), + 'reblogs_count' => $status->reblogs_count ?? 0, + 'favourites_count' => $status->likes_count ?? 0, + 'reblogged' => null, + 'favourited' => null, + 'muted' => null, + 'sensitive' => (bool) $status->is_nsfw, + 'spoiler_text' => $status->cw_summary ?? '', + 'visibility' => $status->scope ?? $status->visibility, + 'application' => [ + 'name' => 'web', + 'website' => null, + ], + 'language' => null, + 'mentions' => StatusMentionService::get($status->id), + 'pf_type' => $status->type ?? $status->setType(), + 'reply_count' => (int) $status->reply_count, + 'comments_disabled' => (bool) $status->comments_disabled, + 'thread' => false, + 'replies' => [], + 'parent' => [], + 'place' => $status->place, + 'local' => (bool) $status->local, + 'taggedPeople' => $taggedPeople, + 'label' => StatusLabelService::get($status), + 'liked_by' => LikeService::likedBy($status), + 'media_attachments' => MediaService::get($status->id), + 'account' => AccountService::get($status->profile_id, true), + 'tags' => StatusHashtagService::statusTags($status->id), + 'poll' => $poll, + 'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null, + ]; + } } diff --git a/app/Transformer/Api/StatusTransformer.php b/app/Transformer/Api/StatusTransformer.php index 22a840ce0..6f9364194 100644 --- a/app/Transformer/Api/StatusTransformer.php +++ b/app/Transformer/Api/StatusTransformer.php @@ -2,80 +2,75 @@ namespace App\Transformer\Api; -use App\Like; -use App\Status; -use League\Fractal; -use Cache; +use App\Models\CustomEmoji; +use App\Services\BookmarkService; use App\Services\HashidService; use App\Services\LikeService; use App\Services\MediaService; use App\Services\MediaTagService; -use App\Services\StatusService; +use App\Services\PollService; +use App\Services\ProfileService; use App\Services\StatusHashtagService; use App\Services\StatusLabelService; use App\Services\StatusMentionService; -use App\Services\ProfileService; -use Illuminate\Support\Str; -use App\Services\PollService; -use App\Models\CustomEmoji; -use App\Services\BookmarkService; +use App\Services\StatusService; +use App\Status; use App\Util\Lexer\Autolink; +use League\Fractal; class StatusTransformer extends Fractal\TransformerAbstract { - public function transform(Status $status) - { - $pid = request()->user()->profile_id; - $taggedPeople = MediaTagService::get($status->id); - $poll = $status->type === 'poll' ? PollService::get($status->id, $pid) : null; - $rendered = config('exp.autolink') ? - ( $status->caption ? Autolink::create()->autolink($status->caption) : '' ) : - ( $status->rendered ?? $status->caption ); + public function transform(Status $status) + { + $pid = request()->user()->profile_id; + $taggedPeople = MediaTagService::get($status->id); + $poll = $status->type === 'poll' ? PollService::get($status->id, $pid) : null; + $content = $status->caption ? Autolink::create()->autolink($status->caption) : null; - return [ - '_v' => 1, - 'id' => (string) $status->id, - 'shortcode' => HashidService::encode($status->id), - 'uri' => $status->url(), - 'url' => $status->url(), - 'in_reply_to_id' => (string) $status->in_reply_to_id, - 'in_reply_to_account_id' => (string) $status->in_reply_to_profile_id, - 'reblog' => $status->reblog_of_id ? StatusService::get($status->reblog_of_id) : null, - 'content' => $rendered, - 'content_text' => $status->caption, - 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), - 'emojis' => CustomEmoji::scan($status->caption), - 'reblogs_count' => 0, - 'favourites_count' => $status->likes_count ?? 0, - 'reblogged' => $status->shared(), - 'favourited' => $status->liked(), - 'muted' => null, - 'sensitive' => (bool) $status->is_nsfw, - 'spoiler_text' => $status->cw_summary ?? '', - 'visibility' => $status->scope ?? $status->visibility, - 'application' => [ - 'name' => 'web', - 'website' => null - ], - 'language' => null, - 'mentions' => StatusMentionService::get($status->id), - 'pf_type' => $status->type ?? $status->setType(), - 'reply_count' => (int) $status->reply_count, - 'comments_disabled' => (bool) $status->comments_disabled, - 'thread' => false, - 'replies' => [], - 'parent' => [], - 'place' => $status->place, - 'local' => (bool) $status->local, - 'taggedPeople' => $taggedPeople, - 'label' => StatusLabelService::get($status), - 'liked_by' => LikeService::likedBy($status), - 'media_attachments' => MediaService::get($status->id), - 'account' => ProfileService::get($status->profile_id, true), - 'tags' => StatusHashtagService::statusTags($status->id), - 'poll' => $poll, - 'bookmarked' => BookmarkService::get($pid, $status->id), - 'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null, - ]; - } + return [ + '_v' => 1, + 'id' => (string) $status->id, + 'shortcode' => HashidService::encode($status->id), + 'uri' => $status->url(), + 'url' => $status->url(), + 'in_reply_to_id' => (string) $status->in_reply_to_id, + 'in_reply_to_account_id' => (string) $status->in_reply_to_profile_id, + 'reblog' => $status->reblog_of_id ? StatusService::get($status->reblog_of_id) : null, + 'content' => $content, + 'content_text' => $status->caption, + 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), + 'emojis' => CustomEmoji::scan($status->caption), + 'reblogs_count' => 0, + 'favourites_count' => $status->likes_count ?? 0, + 'reblogged' => $status->shared(), + 'favourited' => $status->liked(), + 'muted' => null, + 'sensitive' => (bool) $status->is_nsfw, + 'spoiler_text' => $status->cw_summary ?? '', + 'visibility' => $status->scope ?? $status->visibility, + 'application' => [ + 'name' => 'web', + 'website' => null, + ], + 'language' => null, + 'mentions' => StatusMentionService::get($status->id), + 'pf_type' => $status->type ?? $status->setType(), + 'reply_count' => (int) $status->reply_count, + 'comments_disabled' => (bool) $status->comments_disabled, + 'thread' => false, + 'replies' => [], + 'parent' => [], + 'place' => $status->place, + 'local' => (bool) $status->local, + 'taggedPeople' => $taggedPeople, + 'label' => StatusLabelService::get($status), + 'liked_by' => LikeService::likedBy($status), + 'media_attachments' => MediaService::get($status->id), + 'account' => ProfileService::get($status->profile_id, true), + 'tags' => StatusHashtagService::statusTags($status->id), + 'poll' => $poll, + 'bookmarked' => BookmarkService::get($pid, $status->id), + 'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null, + ]; + } } From ecfc967429b44ed6654c44cad0c6e96691364bd0 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 19 Nov 2024 02:56:58 -0700 Subject: [PATCH 4/6] Update PublicApiController --- app/Http/Controllers/PublicApiController.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/PublicApiController.php b/app/Http/Controllers/PublicApiController.php index b0e2efc40..1c9781935 100644 --- a/app/Http/Controllers/PublicApiController.php +++ b/app/Http/Controllers/PublicApiController.php @@ -31,8 +31,8 @@ class PublicApiController extends Controller public function __construct() { - $this->fractal = new Fractal\Manager(); - $this->fractal->setSerializer(new ArraySerializer()); + $this->fractal = new Fractal\Manager; + $this->fractal->setSerializer(new ArraySerializer); } protected function getUserData($user) @@ -74,7 +74,7 @@ class PublicApiController extends Controller abort_if(! in_array($cached['visibility'], ['public', 'unlisted']), 403); $res = ['status' => $cached]; } else { - $item = new Fractal\Resource\Item($status, new StatusStatelessTransformer()); + $item = new Fractal\Resource\Item($status, new StatusStatelessTransformer); $res = [ 'status' => $this->fractal->createData($item)->toArray(), ]; @@ -141,7 +141,7 @@ class PublicApiController extends Controller $replies = $status->comments() ->whereNull('reblog_of_id') ->whereIn('scope', $scope) - ->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'rendered', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at') + ->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at') ->where('id', '>=', $request->min_id) ->orderBy('id', 'desc') ->paginate($limit); @@ -150,7 +150,7 @@ class PublicApiController extends Controller $replies = $status->comments() ->whereNull('reblog_of_id') ->whereIn('scope', $scope) - ->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'rendered', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at') + ->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at') ->where('id', '<=', $request->max_id) ->orderBy('id', 'desc') ->paginate($limit); @@ -159,12 +159,12 @@ class PublicApiController extends Controller $replies = Status::whereInReplyToId($status->id) ->whereNull('reblog_of_id') ->whereIn('scope', $scope) - ->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'rendered', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at') + ->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at') ->orderBy('id', 'desc') ->paginate($limit); } - $resource = new Fractal\Resource\Collection($replies, new StatusStatelessTransformer(), 'data'); + $resource = new Fractal\Resource\Collection($replies, new StatusStatelessTransformer, 'data'); $resource->setPaginator(new IlluminatePaginatorAdapter($replies)); $res = $this->fractal->createData($resource)->toArray(); @@ -271,7 +271,6 @@ class PublicApiController extends Controller 'id', 'uri', 'caption', - 'rendered', 'profile_id', 'type', 'in_reply_to_id', @@ -405,7 +404,6 @@ class PublicApiController extends Controller 'id', 'uri', 'caption', - 'rendered', 'profile_id', 'type', 'in_reply_to_id', @@ -456,7 +454,6 @@ class PublicApiController extends Controller 'id', 'uri', 'caption', - 'rendered', 'profile_id', 'type', 'in_reply_to_id', From 9f7cc52c246653009aa04eee6adb59e2e9e6fc5f Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 19 Nov 2024 03:00:47 -0700 Subject: [PATCH 5/6] Update ApiV1Controller, fix bookmark bug. Closes #5216 --- app/Http/Controllers/Api/ApiV1Controller.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 56617d57f..e64759e24 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -1878,7 +1878,7 @@ class ApiV1Controller extends Controller $media->original_sha256 = $hash; $media->size = $photo->getSize(); $media->mime = $mime; - $media->caption = $request->input('description') ?? ""; + $media->caption = $request->input('description') ?? ''; $media->filter_class = $filterClass; $media->filter_name = $filterName; if ($license) { @@ -2106,7 +2106,7 @@ class ApiV1Controller extends Controller $media->original_sha256 = $hash; $media->size = $photo->getSize(); $media->mime = $mime; - $media->caption = $request->input('description') ?? ""; + $media->caption = $request->input('description') ?? ''; $media->filter_class = $filterClass; $media->filter_name = $filterName; if ($license) { @@ -3951,6 +3951,7 @@ class ApiV1Controller extends Controller abort_unless($request->user()->tokenCan('write'), 403); $status = Status::findOrFail($id); + $user = $request->user(); $pid = $request->user()->profile_id; $account = AccountService::get($status->profile_id); abort_if(isset($account['moved'], $account['moved']['id']), 422, 'Cannot bookmark a post from an account that has migrated'); @@ -3994,6 +3995,7 @@ class ApiV1Controller extends Controller $status = Status::findOrFail($id); $pid = $request->user()->profile_id; + $user = $request->user(); abort_if($user->has_roles && ! UserRoleService::can('can-bookmark', $user->id), 403, 'Invalid permissions for this action'); abort_if($status->in_reply_to_id || $status->reblog_of_id, 404); From 27960c3a0af3280388f239b5c0d79926c197c45a Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 19 Nov 2024 03:01:10 -0700 Subject: [PATCH 6/6] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e8c874f..bab1bf93f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.12.3...dev) - Update AP helpers, reject statuses with invalid dates ([960f3849](https://github.com/pixelfed/pixelfed/commit/960f3849)) - Update DirectMessage API, fix broken threading ([044d410c](https://github.com/pixelfed/pixelfed/commit/044d410c)) +- Update Status caption render logic ([fb8dbb95](https://github.com/pixelfed/pixelfed/commit/fb8dbb95)) +- Update ApiV1Controller, fix bookmark bug. Closes #5216 ([9f7cc52c](https://github.com/pixelfed/pixelfed/commit/9f7cc52c)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.12.4 (2024-11-08)](https://github.com/pixelfed/pixelfed/compare/v0.12.4...dev)