Merge pull request #5355 from pixelfed/staging

Staging
pull/5375/head
daniel 3 months ago committed by GitHub
commit c04e19bc4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -3,6 +3,8 @@
## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.12.3...dev) ## [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 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 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/)) - ([](https://github.com/pixelfed/pixelfed/commit/))
## [v0.12.4 (2024-11-08)](https://github.com/pixelfed/pixelfed/compare/v0.12.4...dev) ## [v0.12.4 (2024-11-08)](https://github.com/pixelfed/pixelfed/compare/v0.12.4...dev)

@ -1878,7 +1878,7 @@ class ApiV1Controller extends Controller
$media->original_sha256 = $hash; $media->original_sha256 = $hash;
$media->size = $photo->getSize(); $media->size = $photo->getSize();
$media->mime = $mime; $media->mime = $mime;
$media->caption = $request->input('description') ?? ""; $media->caption = $request->input('description') ?? '';
$media->filter_class = $filterClass; $media->filter_class = $filterClass;
$media->filter_name = $filterName; $media->filter_name = $filterName;
if ($license) { if ($license) {
@ -2106,7 +2106,7 @@ class ApiV1Controller extends Controller
$media->original_sha256 = $hash; $media->original_sha256 = $hash;
$media->size = $photo->getSize(); $media->size = $photo->getSize();
$media->mime = $mime; $media->mime = $mime;
$media->caption = $request->input('description') ?? ""; $media->caption = $request->input('description') ?? '';
$media->filter_class = $filterClass; $media->filter_class = $filterClass;
$media->filter_name = $filterName; $media->filter_name = $filterName;
if ($license) { if ($license) {
@ -3951,6 +3951,7 @@ class ApiV1Controller extends Controller
abort_unless($request->user()->tokenCan('write'), 403); abort_unless($request->user()->tokenCan('write'), 403);
$status = Status::findOrFail($id); $status = Status::findOrFail($id);
$user = $request->user();
$pid = $request->user()->profile_id; $pid = $request->user()->profile_id;
$account = AccountService::get($status->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'); 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); $status = Status::findOrFail($id);
$pid = $request->user()->profile_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($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); abort_if($status->in_reply_to_id || $status->reblog_of_id, 404);

@ -31,8 +31,8 @@ class PublicApiController extends Controller
public function __construct() public function __construct()
{ {
$this->fractal = new Fractal\Manager(); $this->fractal = new Fractal\Manager;
$this->fractal->setSerializer(new ArraySerializer()); $this->fractal->setSerializer(new ArraySerializer);
} }
protected function getUserData($user) protected function getUserData($user)
@ -74,7 +74,7 @@ class PublicApiController extends Controller
abort_if(! in_array($cached['visibility'], ['public', 'unlisted']), 403); abort_if(! in_array($cached['visibility'], ['public', 'unlisted']), 403);
$res = ['status' => $cached]; $res = ['status' => $cached];
} else { } else {
$item = new Fractal\Resource\Item($status, new StatusStatelessTransformer()); $item = new Fractal\Resource\Item($status, new StatusStatelessTransformer);
$res = [ $res = [
'status' => $this->fractal->createData($item)->toArray(), 'status' => $this->fractal->createData($item)->toArray(),
]; ];
@ -141,7 +141,7 @@ class PublicApiController extends Controller
$replies = $status->comments() $replies = $status->comments()
->whereNull('reblog_of_id') ->whereNull('reblog_of_id')
->whereIn('scope', $scope) ->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) ->where('id', '>=', $request->min_id)
->orderBy('id', 'desc') ->orderBy('id', 'desc')
->paginate($limit); ->paginate($limit);
@ -150,7 +150,7 @@ class PublicApiController extends Controller
$replies = $status->comments() $replies = $status->comments()
->whereNull('reblog_of_id') ->whereNull('reblog_of_id')
->whereIn('scope', $scope) ->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) ->where('id', '<=', $request->max_id)
->orderBy('id', 'desc') ->orderBy('id', 'desc')
->paginate($limit); ->paginate($limit);
@ -159,12 +159,12 @@ class PublicApiController extends Controller
$replies = Status::whereInReplyToId($status->id) $replies = Status::whereInReplyToId($status->id)
->whereNull('reblog_of_id') ->whereNull('reblog_of_id')
->whereIn('scope', $scope) ->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') ->orderBy('id', 'desc')
->paginate($limit); ->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)); $resource->setPaginator(new IlluminatePaginatorAdapter($replies));
$res = $this->fractal->createData($resource)->toArray(); $res = $this->fractal->createData($resource)->toArray();
@ -271,7 +271,6 @@ class PublicApiController extends Controller
'id', 'id',
'uri', 'uri',
'caption', 'caption',
'rendered',
'profile_id', 'profile_id',
'type', 'type',
'in_reply_to_id', 'in_reply_to_id',
@ -405,7 +404,6 @@ class PublicApiController extends Controller
'id', 'id',
'uri', 'uri',
'caption', 'caption',
'rendered',
'profile_id', 'profile_id',
'type', 'type',
'in_reply_to_id', 'in_reply_to_id',
@ -456,7 +454,6 @@ class PublicApiController extends Controller
'id', 'id',
'uri', 'uri',
'caption', 'caption',
'rendered',
'profile_id', 'profile_id',
'type', 'type',
'in_reply_to_id', 'in_reply_to_id',

@ -2,18 +2,17 @@
namespace App\Http\Resources; namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource; use App\Models\CustomEmoji;
use Cache;
use App\Services\AccountService; use App\Services\AccountService;
use App\Services\HashidService; use App\Services\HashidService;
use App\Services\LikeService; use App\Services\LikeService;
use App\Services\MediaService; use App\Services\MediaService;
use App\Services\MediaTagService; use App\Services\MediaTagService;
use App\Services\PollService;
use App\Services\StatusHashtagService; use App\Services\StatusHashtagService;
use App\Services\StatusLabelService;
use App\Services\StatusMentionService; use App\Services\StatusMentionService;
use App\Services\PollService; use App\Util\Lexer\Autolink;
use App\Models\CustomEmoji; use Illuminate\Http\Resources\Json\JsonResource;
class StatusStateless extends JsonResource class StatusStateless extends JsonResource
{ {
@ -28,49 +27,50 @@ class StatusStateless extends JsonResource
$status = $this; $status = $this;
$taggedPeople = MediaTagService::get($status->id); $taggedPeople = MediaTagService::get($status->id);
$poll = $status->type === 'poll' ? PollService::get($status->id) : null; $poll = $status->type === 'poll' ? PollService::get($status->id) : null;
$autoLink = $status->caption ? Autolink::create()->autolink($status->caption) : null;
return [ return [
'_v' => 1, '_v' => 1,
'id' => (string) $status->id, 'id' => (string) $status->id,
//'gid' => $status->group_id ? (string) $status->group_id : null, //'gid' => $status->group_id ? (string) $status->group_id : null,
'shortcode' => HashidService::encode($status->id), 'shortcode' => HashidService::encode($status->id),
'uri' => $status->url(), 'uri' => $status->url(),
'url' => $status->url(), 'url' => $status->url(),
'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, '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, 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null,
'reblog' => null, 'reblog' => null,
'content' => $status->rendered ?? $status->caption, 'content' => $autoLink,
'content_text' => $status->caption, 'content_text' => $status->caption,
'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)),
'emojis' => CustomEmoji::scan($status->caption), 'emojis' => CustomEmoji::scan($status->caption),
'reblogs_count' => $status->reblogs_count ?? 0, 'reblogs_count' => $status->reblogs_count ?? 0,
'favourites_count' => $status->likes_count ?? 0, 'favourites_count' => $status->likes_count ?? 0,
'reblogged' => null, 'reblogged' => null,
'favourited' => null, 'favourited' => null,
'muted' => null, 'muted' => null,
'sensitive' => (bool) $status->is_nsfw, 'sensitive' => (bool) $status->is_nsfw,
'spoiler_text' => $status->cw_summary ?? '', 'spoiler_text' => $status->cw_summary ?? '',
'visibility' => $status->scope ?? $status->visibility, 'visibility' => $status->scope ?? $status->visibility,
'application' => [ 'application' => [
'name' => 'web', 'name' => 'web',
'website' => null 'website' => null,
], ],
'language' => null, 'language' => null,
'mentions' => StatusMentionService::get($status->id), 'mentions' => StatusMentionService::get($status->id),
'pf_type' => $status->type ?? $status->setType(), 'pf_type' => $status->type ?? $status->setType(),
'reply_count' => (int) $status->reply_count, 'reply_count' => (int) $status->reply_count,
'comments_disabled' => (bool) $status->comments_disabled, 'comments_disabled' => (bool) $status->comments_disabled,
'thread' => false, 'thread' => false,
'replies' => [], 'replies' => [],
'parent' => [], 'parent' => [],
'place' => $status->place, 'place' => $status->place,
'local' => (bool) $status->local, 'local' => (bool) $status->local,
'taggedPeople' => $taggedPeople, 'taggedPeople' => $taggedPeople,
'liked_by' => LikeService::likedBy($status), 'liked_by' => LikeService::likedBy($status),
'media_attachments' => MediaService::get($status->id), 'media_attachments' => MediaService::get($status->id),
'account' => AccountService::get($status->profile_id, true), 'account' => AccountService::get($status->profile_id, true),
'tags' => StatusHashtagService::statusTags($status->id), 'tags' => StatusHashtagService::statusTags($status->id),
'poll' => $poll 'poll' => $poll,
]; ];
} }
} }

@ -308,46 +308,6 @@ class Status extends Model
return $this->comments()->orderBy('created_at', 'desc')->take(3); 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) public function scopeToAudience($audience)
{ {
if(!in_array($audience, ['to', 'cc']) || $this->local == false) { if(!in_array($audience, ['to', 'cc']) || $this->local == false) {

@ -2,59 +2,62 @@
namespace App\Transformer\ActivityPub; namespace App\Transformer\ActivityPub;
use App\Services\MediaService;
use App\Status; use App\Status;
use App\Util\Lexer\Autolink;
use League\Fractal; use League\Fractal;
use App\Services\MediaService;
class StatusTransformer extends Fractal\TransformerAbstract class StatusTransformer extends Fractal\TransformerAbstract
{ {
public function transform(Status $status) public function transform(Status $status)
{ {
$content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
return [ return [
'@context' => [ '@context' => [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
[ [
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
'featured' => [ 'featured' => [
'https://pixelfed.org/ns#featured' => ['@type' => '@id'], 'https://pixelfed.org/ns#featured' => ['@type' => '@id'],
], ],
],
], ],
], 'id' => $status->url(),
'id' => $status->url(),
// TODO: handle other types // TODO: handle other types
'type' => 'Note', 'type' => 'Note',
// XXX: CW Title // XXX: CW Title
'summary' => null, 'summary' => null,
'content' => $status->rendered ?? $status->caption, 'content' => $content,
'inReplyTo' => null, 'inReplyTo' => null,
// TODO: fix date format // TODO: fix date format
'published' => $status->created_at->toAtomString(), 'published' => $status->created_at->toAtomString(),
'url' => $status->url(), 'url' => $status->url(),
'attributedTo' => $status->profile->permalink(), 'attributedTo' => $status->profile->permalink(),
'to' => [ 'to' => [
// TODO: handle proper scope // TODO: handle proper scope
'https://www.w3.org/ns/activitystreams#Public', 'https://www.w3.org/ns/activitystreams#Public',
], ],
'cc' => [ 'cc' => [
// TODO: add cc's // TODO: add cc's
$status->profile->permalink('/followers'), $status->profile->permalink('/followers'),
], ],
'sensitive' => (bool) $status->is_nsfw, 'sensitive' => (bool) $status->is_nsfw,
'atomUri' => $status->url(), 'atomUri' => $status->url(),
'inReplyToAtomUri' => null, 'inReplyToAtomUri' => null,
'attachment' => MediaService::activitypub($status->id), 'attachment' => MediaService::activitypub($status->id),
'tag' => [], 'tag' => [],
'location' => $status->place_id ? [ 'location' => $status->place_id ? [
'type' => 'Place', 'type' => 'Place',
'name' => $status->place->name, 'name' => $status->place->name,
'longitude' => $status->place->long, 'longitude' => $status->place->long,
'latitude' => $status->place->lat, 'latitude' => $status->place->lat,
'country' => $status->place->country 'country' => $status->place->country,
] : null, ] : null,
]; ];
} }
} }

@ -2,140 +2,144 @@
namespace App\Transformer\ActivityPub\Verb; namespace App\Transformer\ActivityPub\Verb;
use App\Status;
use League\Fractal;
use App\Models\CustomEmoji; use App\Models\CustomEmoji;
use App\Status;
use App\Util\Lexer\Autolink;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use League\Fractal;
class CreateNote extends Fractal\TransformerAbstract class CreateNote extends Fractal\TransformerAbstract
{ {
public function transform(Status $status) public function transform(Status $status)
{ {
$mentions = $status->mentions->map(function ($mention) { $mentions = $status->mentions->map(function ($mention) {
$webfinger = $mention->emailUrl(); $webfinger = $mention->emailUrl();
$name = Str::startsWith($webfinger, '@') ? $name = Str::startsWith($webfinger, '@') ?
$webfinger : $webfinger :
'@' . $webfinger; '@'.$webfinger;
return [
'type' => 'Mention', return [
'href' => $mention->permalink(), 'type' => 'Mention',
'name' => $name 'href' => $mention->permalink(),
]; 'name' => $name,
})->toArray(); ];
})->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);
}
}
if($status->in_reply_to_id != null) { $hashtags = $status->hashtags->map(function ($hashtag) {
$parent = $status->parent()->profile; return [
if($parent) { 'type' => 'Hashtag',
$webfinger = $parent->emailUrl(); 'href' => $hashtag->url(),
$name = Str::startsWith($webfinger, '@') ? 'name' => "#{$hashtag->name}",
$webfinger : ];
'@' . $webfinger; })->toArray();
$reply = [
'type' => 'Mention',
'href' => $parent->permalink(),
'name' => $name
];
$mentions = array_merge($reply, $mentions);
}
}
$hashtags = $status->hashtags->map(function ($hashtag) { $emojis = CustomEmoji::scan($status->caption, true) ?? [];
return [ $emoji = array_merge($emojis, $mentions);
'type' => 'Hashtag', $tags = array_merge($emoji, $hashtags);
'href' => $hashtag->url(), $content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
'name' => "#{$hashtag->name}",
];
})->toArray();
$emojis = CustomEmoji::scan($status->caption, true) ?? []; return [
$emoji = array_merge($emojis, $mentions); '@context' => [
$tags = array_merge($emoji, $hashtags); '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 [ return $res;
'@context' => [ })->toArray(),
'https://w3id.org/security/v1', 'tag' => $tags,
'https://www.w3.org/ns/activitystreams', 'commentsEnabled' => (bool) ! $status->comments_disabled,
[ 'capabilities' => [
'Hashtag' => 'as:Hashtag', 'announce' => 'https://www.w3.org/ns/activitystreams#Public',
'sensitive' => 'as:sensitive', 'like' => 'https://www.w3.org/ns/activitystreams#Public',
'schema' => 'http://schema.org/', 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public',
'pixelfed' => 'http://pixelfed.org/ns#', ],
'commentsEnabled' => [ 'location' => $status->place_id ? [
'@id' => 'pixelfed:commentsEnabled', 'type' => 'Place',
'@type' => 'schema:Boolean' 'name' => $status->place->name,
], 'longitude' => $status->place->long,
'capabilities' => [ 'latitude' => $status->place->lat,
'@id' => 'pixelfed:capabilities', 'country' => $status->place->country,
'@container' => '@set' ] : null,
], ],
'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,
]
];
}
} }

@ -2,133 +2,137 @@
namespace App\Transformer\ActivityPub\Verb; namespace App\Transformer\ActivityPub\Verb;
use App\Status;
use League\Fractal;
use App\Models\CustomEmoji; use App\Models\CustomEmoji;
use App\Status;
use App\Util\Lexer\Autolink;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use League\Fractal;
class Note extends Fractal\TransformerAbstract 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();
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);
}
}
$mentions = $status->mentions->map(function ($mention) { $hashtags = $status->hashtags->map(function ($hashtag) {
$webfinger = $mention->emailUrl(); return [
$name = Str::startsWith($webfinger, '@') ? 'type' => 'Hashtag',
$webfinger : 'href' => $hashtag->url(),
'@' . $webfinger; 'name' => "#{$hashtag->name}",
return [ ];
'type' => 'Mention', })->toArray();
'href' => $mention->permalink(),
'name' => $name
];
})->toArray();
if($status->in_reply_to_id != null) { $emojis = CustomEmoji::scan($status->caption, true) ?? [];
$parent = $status->parent()->profile; $emoji = array_merge($emojis, $mentions);
if($parent) { $tags = array_merge($emoji, $hashtags);
$webfinger = $parent->emailUrl(); $content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
$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();
$emojis = CustomEmoji::scan($status->caption, true) ?? []; return [
$emoji = array_merge($emojis, $mentions); '@context' => [
$tags = array_merge($emoji, $hashtags); '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 [ return $res;
'@context' => [ })->toArray(),
'https://w3id.org/security/v1', 'tag' => $tags,
'https://www.w3.org/ns/activitystreams', 'commentsEnabled' => (bool) ! $status->comments_disabled,
[ 'capabilities' => [
'Hashtag' => 'as:Hashtag', 'announce' => 'https://www.w3.org/ns/activitystreams#Public',
'sensitive' => 'as:sensitive', 'like' => 'https://www.w3.org/ns/activitystreams#Public',
'schema' => 'http://schema.org/', 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public',
'pixelfed' => 'http://pixelfed.org/ns#', ],
'commentsEnabled' => [ 'location' => $status->place_id ? [
'@id' => 'pixelfed:commentsEnabled', 'type' => 'Place',
'@type' => 'schema:Boolean' 'name' => $status->place->name,
], 'longitude' => $status->place->long,
'capabilities' => [ 'latitude' => $status->place->lat,
'@id' => 'pixelfed:capabilities', 'country' => $status->place->country,
'@container' => '@set' ] : null,
], ];
'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,
];
}
} }

@ -3,104 +3,107 @@
namespace App\Transformer\ActivityPub\Verb; namespace App\Transformer\ActivityPub\Verb;
use App\Status; use App\Status;
use League\Fractal; use App\Util\Lexer\Autolink;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use League\Fractal;
class Question extends Fractal\TransformerAbstract class Question extends Fractal\TransformerAbstract
{ {
public function transform(Status $status) public function transform(Status $status)
{ {
$mentions = $status->mentions->map(function ($mention) { $mentions = $status->mentions->map(function ($mention) {
$webfinger = $mention->emailUrl(); $webfinger = $mention->emailUrl();
$name = Str::startsWith($webfinger, '@') ? $name = Str::startsWith($webfinger, '@') ?
$webfinger : $webfinger :
'@' . $webfinger; '@'.$webfinger;
return [
'type' => 'Mention', return [
'href' => $mention->permalink(), 'type' => 'Mention',
'name' => $name 'href' => $mention->permalink(),
]; 'name' => $name,
})->toArray(); ];
})->toArray();
$hashtags = $status->hashtags->map(function ($hashtag) { $hashtags = $status->hashtags->map(function ($hashtag) {
return [ return [
'type' => 'Hashtag', 'type' => 'Hashtag',
'href' => $hashtag->url(), 'href' => $hashtag->url(),
'name' => "#{$hashtag->name}", 'name' => "#{$hashtag->name}",
]; ];
})->toArray(); })->toArray();
$tags = array_merge($mentions, $hashtags); $tags = array_merge($mentions, $hashtags);
$content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
return [ return [
'@context' => [ '@context' => [
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
[ [
'Hashtag' => 'as:Hashtag', 'Hashtag' => 'as:Hashtag',
'sensitive' => 'as:sensitive', 'sensitive' => 'as:sensitive',
'schema' => 'http://schema.org/', 'schema' => 'http://schema.org/',
'pixelfed' => 'http://pixelfed.org/ns#', 'pixelfed' => 'http://pixelfed.org/ns#',
'commentsEnabled' => [ 'commentsEnabled' => [
'@id' => 'pixelfed:commentsEnabled', '@id' => 'pixelfed:commentsEnabled',
'@type' => 'schema:Boolean' '@type' => 'schema:Boolean',
], ],
'capabilities' => [ 'capabilities' => [
'@id' => 'pixelfed:capabilities', '@id' => 'pixelfed:capabilities',
'@container' => '@set' '@container' => '@set',
], ],
'announce' => [ 'announce' => [
'@id' => 'pixelfed:canAnnounce', '@id' => 'pixelfed:canAnnounce',
'@type' => '@id' '@type' => '@id',
], ],
'like' => [ 'like' => [
'@id' => 'pixelfed:canLike', '@id' => 'pixelfed:canLike',
'@type' => '@id' '@type' => '@id',
], ],
'reply' => [ 'reply' => [
'@id' => 'pixelfed:canReply', '@id' => 'pixelfed:canReply',
'@type' => '@id' '@type' => '@id',
], ],
'toot' => 'http://joinmastodon.org/ns#', 'toot' => 'http://joinmastodon.org/ns#',
'Emoji' => 'toot:Emoji' 'Emoji' => 'toot:Emoji',
] ],
], ],
'id' => $status->url(), 'id' => $status->url(),
'type' => 'Question', 'type' => 'Question',
'summary' => null, 'summary' => null,
'content' => $status->rendered ?? $status->caption, 'content' => $content,
'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null,
'published' => $status->created_at->toAtomString(), 'published' => $status->created_at->toAtomString(),
'url' => $status->url(), 'url' => $status->url(),
'attributedTo' => $status->profile->permalink(), 'attributedTo' => $status->profile->permalink(),
'to' => $status->scopeToAudience('to'), 'to' => $status->scopeToAudience('to'),
'cc' => $status->scopeToAudience('cc'), 'cc' => $status->scopeToAudience('cc'),
'sensitive' => (bool) $status->is_nsfw, 'sensitive' => (bool) $status->is_nsfw,
'attachment' => [], 'attachment' => [],
'tag' => $tags, 'tag' => $tags,
'commentsEnabled' => (bool) !$status->comments_disabled, 'commentsEnabled' => (bool) ! $status->comments_disabled,
'capabilities' => [ 'capabilities' => [
'announce' => 'https://www.w3.org/ns/activitystreams#Public', 'announce' => 'https://www.w3.org/ns/activitystreams#Public',
'like' => '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' 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public',
], ],
'location' => $status->place_id ? [ 'location' => $status->place_id ? [
'type' => 'Place', 'type' => 'Place',
'name' => $status->place->name, 'name' => $status->place->name,
'longitude' => $status->place->long, 'longitude' => $status->place->long,
'latitude' => $status->place->lat, 'latitude' => $status->place->lat,
'country' => $status->place->country 'country' => $status->place->country,
] : null, ] : null,
'endTime' => $status->poll->expires_at->toAtomString(), 'endTime' => $status->poll->expires_at->toAtomString(),
'oneOf' => collect($status->poll->poll_options)->map(function($option, $index) use($status) { 'oneOf' => collect($status->poll->poll_options)->map(function ($option, $index) use ($status) {
return [ return [
'type' => 'Note', 'type' => 'Note',
'name' => $option, 'name' => $option,
'replies' => [ 'replies' => [
'type' => 'Collection', 'type' => 'Collection',
'totalItems' => $status->poll->cached_tallies[$index] 'totalItems' => $status->poll->cached_tallies[$index],
] ],
]; ];
}) }),
]; ];
} }
} }

@ -2,132 +2,135 @@
namespace App\Transformer\ActivityPub\Verb; namespace App\Transformer\ActivityPub\Verb;
use App\Status;
use League\Fractal;
use App\Models\CustomEmoji; use App\Models\CustomEmoji;
use App\Status;
use App\Util\Lexer\Autolink;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use League\Fractal;
class UpdateNote extends Fractal\TransformerAbstract class UpdateNote extends Fractal\TransformerAbstract
{ {
public function transform(Status $status) public function transform(Status $status)
{ {
$mentions = $status->mentions->map(function ($mention) { $mentions = $status->mentions->map(function ($mention) {
$webfinger = $mention->emailUrl(); $webfinger = $mention->emailUrl();
$name = Str::startsWith($webfinger, '@') ? $name = Str::startsWith($webfinger, '@') ?
$webfinger : $webfinger :
'@' . $webfinger; '@'.$webfinger;
return [
'type' => 'Mention', return [
'href' => $mention->permalink(), 'type' => 'Mention',
'name' => $name 'href' => $mention->permalink(),
]; 'name' => $name,
})->toArray(); ];
})->toArray();
if($status->in_reply_to_id != null) { if ($status->in_reply_to_id != null) {
$parent = $status->parent()->profile; $parent = $status->parent()->profile;
if($parent) { if ($parent) {
$webfinger = $parent->emailUrl(); $webfinger = $parent->emailUrl();
$name = Str::startsWith($webfinger, '@') ? $name = Str::startsWith($webfinger, '@') ?
$webfinger : $webfinger :
'@' . $webfinger; '@'.$webfinger;
$reply = [ $reply = [
'type' => 'Mention', 'type' => 'Mention',
'href' => $parent->permalink(), 'href' => $parent->permalink(),
'name' => $name 'name' => $name,
]; ];
$mentions = array_merge($reply, $mentions); $mentions = array_merge($reply, $mentions);
} }
} }
$hashtags = $status->hashtags->map(function ($hashtag) { $hashtags = $status->hashtags->map(function ($hashtag) {
return [ return [
'type' => 'Hashtag', 'type' => 'Hashtag',
'href' => $hashtag->url(), 'href' => $hashtag->url(),
'name' => "#{$hashtag->name}", 'name' => "#{$hashtag->name}",
]; ];
})->toArray(); })->toArray();
$emojis = CustomEmoji::scan($status->caption, true) ?? []; $emojis = CustomEmoji::scan($status->caption, true) ?? [];
$emoji = array_merge($emojis, $mentions); $emoji = array_merge($emojis, $mentions);
$tags = array_merge($emoji, $hashtags); $tags = array_merge($emoji, $hashtags);
$latestEdit = $status->edits()->latest()->first(); $content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
$latestEdit = $status->edits()->latest()->first();
return [ return [
'@context' => [ '@context' => [
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
[ [
'Hashtag' => 'as:Hashtag', 'Hashtag' => 'as:Hashtag',
'sensitive' => 'as:sensitive', 'sensitive' => 'as:sensitive',
'schema' => 'http://schema.org/', 'schema' => 'http://schema.org/',
'pixelfed' => 'http://pixelfed.org/ns#', 'pixelfed' => 'http://pixelfed.org/ns#',
'commentsEnabled' => [ 'commentsEnabled' => [
'@id' => 'pixelfed:commentsEnabled', '@id' => 'pixelfed:commentsEnabled',
'@type' => 'schema:Boolean' '@type' => 'schema:Boolean',
], ],
'capabilities' => [ 'capabilities' => [
'@id' => 'pixelfed:capabilities', '@id' => 'pixelfed:capabilities',
'@container' => '@set' '@container' => '@set',
], ],
'announce' => [ 'announce' => [
'@id' => 'pixelfed:canAnnounce', '@id' => 'pixelfed:canAnnounce',
'@type' => '@id' '@type' => '@id',
], ],
'like' => [ 'like' => [
'@id' => 'pixelfed:canLike', '@id' => 'pixelfed:canLike',
'@type' => '@id' '@type' => '@id',
], ],
'reply' => [ 'reply' => [
'@id' => 'pixelfed:canReply', '@id' => 'pixelfed:canReply',
'@type' => '@id' '@type' => '@id',
], ],
'toot' => 'http://joinmastodon.org/ns#', 'toot' => 'http://joinmastodon.org/ns#',
'Emoji' => 'toot:Emoji' 'Emoji' => 'toot:Emoji',
] ],
], ],
'id' => $status->permalink('#updates/' . $latestEdit->id), 'id' => $status->permalink('#updates/'.$latestEdit->id),
'type' => 'Update', 'type' => 'Update',
'actor' => $status->profile->permalink(), 'actor' => $status->profile->permalink(),
'published' => $latestEdit->created_at->toAtomString(), 'published' => $latestEdit->created_at->toAtomString(),
'to' => $status->scopeToAudience('to'), 'to' => $status->scopeToAudience('to'),
'cc' => $status->scopeToAudience('cc'), 'cc' => $status->scopeToAudience('cc'),
'object' => [ 'object' => [
'id' => $status->url(), 'id' => $status->url(),
'type' => 'Note', 'type' => 'Note',
'summary' => $status->is_nsfw ? $status->cw_summary : null, 'summary' => $status->is_nsfw ? $status->cw_summary : null,
'content' => $status->rendered ?? $status->caption, 'content' => $content,
'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null,
'published' => $status->created_at->toAtomString(), 'published' => $status->created_at->toAtomString(),
'url' => $status->url(), 'url' => $status->url(),
'attributedTo' => $status->profile->permalink(), 'attributedTo' => $status->profile->permalink(),
'to' => $status->scopeToAudience('to'), 'to' => $status->scopeToAudience('to'),
'cc' => $status->scopeToAudience('cc'), 'cc' => $status->scopeToAudience('cc'),
'sensitive' => (bool) $status->is_nsfw, 'sensitive' => (bool) $status->is_nsfw,
'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) { 'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) {
return [ return [
'type' => $media->activityVerb(), 'type' => $media->activityVerb(),
'mediaType' => $media->mime, 'mediaType' => $media->mime,
'url' => $media->url(), 'url' => $media->url(),
'name' => $media->caption, 'name' => $media->caption,
]; ];
})->toArray(), })->toArray(),
'tag' => $tags, 'tag' => $tags,
'commentsEnabled' => (bool) !$status->comments_disabled, 'commentsEnabled' => (bool) ! $status->comments_disabled,
'updated' => $latestEdit->created_at->toAtomString(), 'updated' => $latestEdit->created_at->toAtomString(),
'capabilities' => [ 'capabilities' => [
'announce' => 'https://www.w3.org/ns/activitystreams#Public', 'announce' => 'https://www.w3.org/ns/activitystreams#Public',
'like' => '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' 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public',
], ],
'location' => $status->place_id ? [ 'location' => $status->place_id ? [
'type' => 'Place', 'type' => 'Place',
'name' => $status->place->name, 'name' => $status->place->name,
'longitude' => $status->place->long, 'longitude' => $status->place->long,
'latitude' => $status->place->lat, 'latitude' => $status->place->lat,
'country' => $status->place->country 'country' => $status->place->country,
] : null, ] : null,
] ],
]; ];
} }
} }

@ -2,48 +2,50 @@
namespace App\Transformer\Api\Mastodon\v1; namespace App\Transformer\Api\Mastodon\v1;
use App\Status;
use League\Fractal;
use Cache;
use App\Services\MediaService; use App\Services\MediaService;
use App\Services\ProfileService; use App\Services\ProfileService;
use App\Services\StatusHashtagService; use App\Services\StatusHashtagService;
use App\Status;
use App\Util\Lexer\Autolink;
use League\Fractal;
class StatusTransformer extends Fractal\TransformerAbstract class StatusTransformer extends Fractal\TransformerAbstract
{ {
public function transform(Status $status) public function transform(Status $status)
{ {
return [ $content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
'id' => (string) $status->id,
'created_at' => $status->created_at->toJSON(), return [
'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, 'id' => (string) $status->id,
'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null, 'created_at' => $status->created_at->toJSON(),
'sensitive' => (bool) $status->is_nsfw, 'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null,
'spoiler_text' => $status->cw_summary ?? '', 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null,
'visibility' => $status->visibility ?? $status->scope, 'sensitive' => (bool) $status->is_nsfw,
'language' => 'en', 'spoiler_text' => $status->cw_summary ?? '',
'uri' => $status->permalink(''), 'visibility' => $status->visibility ?? $status->scope,
'url' => $status->url(), 'language' => 'en',
'replies_count' => $status->reply_count ?? 0, 'uri' => $status->permalink(''),
'reblogs_count' => $status->reblogs_count ?? 0, 'url' => $status->url(),
'favourites_count' => $status->likes_count ?? 0, 'replies_count' => $status->reply_count ?? 0,
'reblogged' => $status->shared(), 'reblogs_count' => $status->reblogs_count ?? 0,
'favourited' => $status->liked(), 'favourites_count' => $status->likes_count ?? 0,
'muted' => false, 'reblogged' => $status->shared(),
'bookmarked' => false, 'favourited' => $status->liked(),
'content' => $status->rendered ?? $status->caption ?? '', 'muted' => false,
'reblog' => null, 'bookmarked' => false,
'application' => [ 'content' => $content,
'name' => 'web', 'reblog' => null,
'website' => null 'application' => [
], 'name' => 'web',
'mentions' => [], 'website' => null,
'emojis' => [], ],
'card' => null, 'mentions' => [],
'poll' => null, 'emojis' => [],
'media_attachments' => MediaService::get($status->id), 'card' => null,
'account' => ProfileService::get($status->profile_id, true), 'poll' => null,
'tags' => StatusHashtagService::statusTags($status->id), 'media_attachments' => MediaService::get($status->id),
]; 'account' => ProfileService::get($status->profile_id, true),
} 'tags' => StatusHashtagService::statusTags($status->id),
];
}
} }

@ -2,76 +2,73 @@
namespace App\Transformer\Api; namespace App\Transformer\Api;
use App\Status; use App\Models\CustomEmoji;
use League\Fractal;
use Cache;
use App\Services\AccountService; use App\Services\AccountService;
use App\Services\HashidService; use App\Services\HashidService;
use App\Services\LikeService; use App\Services\LikeService;
use App\Services\MediaService; use App\Services\MediaService;
use App\Services\MediaTagService; use App\Services\MediaTagService;
use App\Services\StatusService; use App\Services\PollService;
use App\Services\StatusHashtagService; use App\Services\StatusHashtagService;
use App\Services\StatusLabelService; use App\Services\StatusLabelService;
use App\Services\StatusMentionService; use App\Services\StatusMentionService;
use App\Services\PollService; use App\Services\StatusService;
use App\Models\CustomEmoji; use App\Status;
use App\Util\Lexer\Autolink; use App\Util\Lexer\Autolink;
use League\Fractal;
class StatusStatelessTransformer extends Fractal\TransformerAbstract class StatusStatelessTransformer extends Fractal\TransformerAbstract
{ {
public function transform(Status $status) public function transform(Status $status)
{ {
$taggedPeople = MediaTagService::get($status->id); $taggedPeople = MediaTagService::get($status->id);
$poll = $status->type === 'poll' ? PollService::get($status->id) : null; $poll = $status->type === 'poll' ? PollService::get($status->id) : null;
$rendered = config('exp.autolink') ? $rendered = $status->caption ? Autolink::create()->autolink($status->caption) : null;
( $status->caption ? Autolink::create()->autolink($status->caption) : '' ) :
( $status->rendered ?? $status->caption );
return [ return [
'_v' => 1, '_v' => 1,
'id' => (string) $status->id, 'id' => (string) $status->id,
//'gid' => $status->group_id ? (string) $status->group_id : null, //'gid' => $status->group_id ? (string) $status->group_id : null,
'shortcode' => HashidService::encode($status->id), 'shortcode' => HashidService::encode($status->id),
'uri' => $status->url(), 'uri' => $status->url(),
'url' => $status->url(), 'url' => $status->url(),
'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, '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, '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, 'reblog' => $status->reblog_of_id ? StatusService::get($status->reblog_of_id, false) : null,
'content' => $rendered, 'content' => $rendered,
'content_text' => $status->caption, 'content_text' => $status->caption,
'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)),
'emojis' => CustomEmoji::scan($status->caption), 'emojis' => CustomEmoji::scan($status->caption),
'reblogs_count' => $status->reblogs_count ?? 0, 'reblogs_count' => $status->reblogs_count ?? 0,
'favourites_count' => $status->likes_count ?? 0, 'favourites_count' => $status->likes_count ?? 0,
'reblogged' => null, 'reblogged' => null,
'favourited' => null, 'favourited' => null,
'muted' => null, 'muted' => null,
'sensitive' => (bool) $status->is_nsfw, 'sensitive' => (bool) $status->is_nsfw,
'spoiler_text' => $status->cw_summary ?? '', 'spoiler_text' => $status->cw_summary ?? '',
'visibility' => $status->scope ?? $status->visibility, 'visibility' => $status->scope ?? $status->visibility,
'application' => [ 'application' => [
'name' => 'web', 'name' => 'web',
'website' => null 'website' => null,
], ],
'language' => null, 'language' => null,
'mentions' => StatusMentionService::get($status->id), 'mentions' => StatusMentionService::get($status->id),
'pf_type' => $status->type ?? $status->setType(), 'pf_type' => $status->type ?? $status->setType(),
'reply_count' => (int) $status->reply_count, 'reply_count' => (int) $status->reply_count,
'comments_disabled' => (bool) $status->comments_disabled, 'comments_disabled' => (bool) $status->comments_disabled,
'thread' => false, 'thread' => false,
'replies' => [], 'replies' => [],
'parent' => [], 'parent' => [],
'place' => $status->place, 'place' => $status->place,
'local' => (bool) $status->local, 'local' => (bool) $status->local,
'taggedPeople' => $taggedPeople, 'taggedPeople' => $taggedPeople,
'label' => StatusLabelService::get($status), 'label' => StatusLabelService::get($status),
'liked_by' => LikeService::likedBy($status), 'liked_by' => LikeService::likedBy($status),
'media_attachments' => MediaService::get($status->id), 'media_attachments' => MediaService::get($status->id),
'account' => AccountService::get($status->profile_id, true), 'account' => AccountService::get($status->profile_id, true),
'tags' => StatusHashtagService::statusTags($status->id), 'tags' => StatusHashtagService::statusTags($status->id),
'poll' => $poll, 'poll' => $poll,
'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null, 'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null,
]; ];
} }
} }

@ -2,80 +2,75 @@
namespace App\Transformer\Api; namespace App\Transformer\Api;
use App\Like; use App\Models\CustomEmoji;
use App\Status; use App\Services\BookmarkService;
use League\Fractal;
use Cache;
use App\Services\HashidService; use App\Services\HashidService;
use App\Services\LikeService; use App\Services\LikeService;
use App\Services\MediaService; use App\Services\MediaService;
use App\Services\MediaTagService; use App\Services\MediaTagService;
use App\Services\StatusService; use App\Services\PollService;
use App\Services\ProfileService;
use App\Services\StatusHashtagService; use App\Services\StatusHashtagService;
use App\Services\StatusLabelService; use App\Services\StatusLabelService;
use App\Services\StatusMentionService; use App\Services\StatusMentionService;
use App\Services\ProfileService; use App\Services\StatusService;
use Illuminate\Support\Str; use App\Status;
use App\Services\PollService;
use App\Models\CustomEmoji;
use App\Services\BookmarkService;
use App\Util\Lexer\Autolink; use App\Util\Lexer\Autolink;
use League\Fractal;
class StatusTransformer extends Fractal\TransformerAbstract class StatusTransformer extends Fractal\TransformerAbstract
{ {
public function transform(Status $status) public function transform(Status $status)
{ {
$pid = request()->user()->profile_id; $pid = request()->user()->profile_id;
$taggedPeople = MediaTagService::get($status->id); $taggedPeople = MediaTagService::get($status->id);
$poll = $status->type === 'poll' ? PollService::get($status->id, $pid) : null; $poll = $status->type === 'poll' ? PollService::get($status->id, $pid) : null;
$rendered = config('exp.autolink') ? $content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
( $status->caption ? Autolink::create()->autolink($status->caption) : '' ) :
( $status->rendered ?? $status->caption );
return [ return [
'_v' => 1, '_v' => 1,
'id' => (string) $status->id, 'id' => (string) $status->id,
'shortcode' => HashidService::encode($status->id), 'shortcode' => HashidService::encode($status->id),
'uri' => $status->url(), 'uri' => $status->url(),
'url' => $status->url(), 'url' => $status->url(),
'in_reply_to_id' => (string) $status->in_reply_to_id, 'in_reply_to_id' => (string) $status->in_reply_to_id,
'in_reply_to_account_id' => (string) $status->in_reply_to_profile_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, 'reblog' => $status->reblog_of_id ? StatusService::get($status->reblog_of_id) : null,
'content' => $rendered, 'content' => $content,
'content_text' => $status->caption, 'content_text' => $status->caption,
'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)),
'emojis' => CustomEmoji::scan($status->caption), 'emojis' => CustomEmoji::scan($status->caption),
'reblogs_count' => 0, 'reblogs_count' => 0,
'favourites_count' => $status->likes_count ?? 0, 'favourites_count' => $status->likes_count ?? 0,
'reblogged' => $status->shared(), 'reblogged' => $status->shared(),
'favourited' => $status->liked(), 'favourited' => $status->liked(),
'muted' => null, 'muted' => null,
'sensitive' => (bool) $status->is_nsfw, 'sensitive' => (bool) $status->is_nsfw,
'spoiler_text' => $status->cw_summary ?? '', 'spoiler_text' => $status->cw_summary ?? '',
'visibility' => $status->scope ?? $status->visibility, 'visibility' => $status->scope ?? $status->visibility,
'application' => [ 'application' => [
'name' => 'web', 'name' => 'web',
'website' => null 'website' => null,
], ],
'language' => null, 'language' => null,
'mentions' => StatusMentionService::get($status->id), 'mentions' => StatusMentionService::get($status->id),
'pf_type' => $status->type ?? $status->setType(), 'pf_type' => $status->type ?? $status->setType(),
'reply_count' => (int) $status->reply_count, 'reply_count' => (int) $status->reply_count,
'comments_disabled' => (bool) $status->comments_disabled, 'comments_disabled' => (bool) $status->comments_disabled,
'thread' => false, 'thread' => false,
'replies' => [], 'replies' => [],
'parent' => [], 'parent' => [],
'place' => $status->place, 'place' => $status->place,
'local' => (bool) $status->local, 'local' => (bool) $status->local,
'taggedPeople' => $taggedPeople, 'taggedPeople' => $taggedPeople,
'label' => StatusLabelService::get($status), 'label' => StatusLabelService::get($status),
'liked_by' => LikeService::likedBy($status), 'liked_by' => LikeService::likedBy($status),
'media_attachments' => MediaService::get($status->id), 'media_attachments' => MediaService::get($status->id),
'account' => ProfileService::get($status->profile_id, true), 'account' => ProfileService::get($status->profile_id, true),
'tags' => StatusHashtagService::statusTags($status->id), 'tags' => StatusHashtagService::statusTags($status->id),
'poll' => $poll, 'poll' => $poll,
'bookmarked' => BookmarkService::get($pid, $status->id), 'bookmarked' => BookmarkService::get($pid, $status->id),
'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null, 'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null,
]; ];
} }
} }

@ -417,8 +417,8 @@ class Inbox
return; return;
} }
$msg = $activity['content']; $msg = Purify::clean($activity['content']);
$msgText = strip_tags($activity['content']); $msgText = strip_tags($msg);
if (Str::startsWith($msgText, '@'.$profile->username)) { if (Str::startsWith($msgText, '@'.$profile->username)) {
$len = strlen('@'.$profile->username); $len = strlen('@'.$profile->username);

Loading…
Cancel
Save