diff --git a/app/Services/StatusService.php b/app/Services/StatusService.php
index 8807e37b1..892005f7e 100644
--- a/app/Services/StatusService.php
+++ b/app/Services/StatusService.php
@@ -21,10 +21,14 @@ class StatusService {
return self::CACHE_KEY . $id;
}
- public static function get($id)
+ public static function get($id, $publicOnly = true)
{
- return Cache::remember(self::key($id), now()->addDays(7), function() use($id) {
- $status = Status::whereScope('public')->find($id);
+ return Cache::remember(self::key($id), now()->addDays(7), function() use($id, $publicOnly) {
+ if($publicOnly) {
+ $status = Status::whereScope('public')->find($id);
+ } else {
+ $status = Status::whereIn('scope', ['public', 'private', 'unlisted'])->find($id);
+ }
if(!$status) {
return null;
}
@@ -37,6 +41,8 @@ class StatusService {
public static function del($id)
{
+ Cache::forget('pf:services:sh:id:' . $id);
+ Cache::forget('status:transformer:media:attachments:' . $id);
PublicTimelineService::rem($id);
return Cache::forget(self::key($id));
}
diff --git a/app/Status.php b/app/Status.php
index d9adae0ac..e14802406 100644
--- a/app/Status.php
+++ b/app/Status.php
@@ -10,408 +10,408 @@ use Illuminate\Database\Eloquent\SoftDeletes;
class Status extends Model
{
- use HasSnowflakePrimary, SoftDeletes;
+ use HasSnowflakePrimary, SoftDeletes;
- /**
- * Indicates if the IDs are auto-incrementing.
- *
- * @var bool
- */
- public $incrementing = false;
+ /**
+ * Indicates if the IDs are auto-incrementing.
+ *
+ * @var bool
+ */
+ public $incrementing = false;
- /**
- * The attributes that should be mutated to dates.
- *
- * @var array
- */
- protected $dates = ['deleted_at'];
+ /**
+ * The attributes that should be mutated to dates.
+ *
+ * @var array
+ */
+ protected $dates = ['deleted_at'];
- protected $fillable = ['profile_id', 'visibility', 'in_reply_to_id', 'reblog_of_id', 'type'];
+ protected $fillable = ['profile_id', 'visibility', 'in_reply_to_id', 'reblog_of_id', 'type'];
- const STATUS_TYPES = [
- 'text',
- 'photo',
- 'photo:album',
- 'video',
- 'video:album',
- 'photo:video:album',
- 'share',
- 'reply',
- 'story',
- 'story:reply',
- 'story:reaction',
- 'story:live',
- 'loop'
- ];
+ const STATUS_TYPES = [
+ 'text',
+ 'photo',
+ 'photo:album',
+ 'video',
+ 'video:album',
+ 'photo:video:album',
+ 'share',
+ 'reply',
+ 'story',
+ 'story:reply',
+ 'story:reaction',
+ 'story:live',
+ 'loop'
+ ];
- const MAX_MENTIONS = 5;
+ const MAX_MENTIONS = 5;
- const MAX_HASHTAGS = 30;
+ const MAX_HASHTAGS = 30;
- const MAX_LINKS = 0;
+ const MAX_LINKS = 0;
- public function profile()
- {
- return $this->belongsTo(Profile::class);
- }
+ public function profile()
+ {
+ return $this->belongsTo(Profile::class);
+ }
- public function media()
- {
- return $this->hasMany(Media::class);
- }
+ public function media()
+ {
+ return $this->hasMany(Media::class);
+ }
- public function firstMedia()
- {
- return $this->hasMany(Media::class)->orderBy('order', 'asc')->first();
- }
+ public function firstMedia()
+ {
+ return $this->hasMany(Media::class)->orderBy('order', 'asc')->first();
+ }
- public function viewType()
- {
- if($this->type) {
- return $this->type;
- }
- return $this->setType();
- }
+ public function viewType()
+ {
+ if($this->type) {
+ return $this->type;
+ }
+ return $this->setType();
+ }
- public function setType()
- {
- if(in_array($this->type, self::STATUS_TYPES)) {
- return $this->type;
- }
- $mimes = $this->media->pluck('mime')->toArray();
- $type = StatusController::mimeTypeCheck($mimes);
- if($type) {
- $this->type = $type;
- $this->save();
- return $type;
- }
- }
+ public function setType()
+ {
+ if(in_array($this->type, self::STATUS_TYPES)) {
+ return $this->type;
+ }
+ $mimes = $this->media->pluck('mime')->toArray();
+ $type = StatusController::mimeTypeCheck($mimes);
+ if($type) {
+ $this->type = $type;
+ $this->save();
+ return $type;
+ }
+ }
- public function thumb($showNsfw = false)
- {
- $key = $showNsfw ? 'status:thumb:nsfw1'.$this->id : 'status:thumb:nsfw0'.$this->id;
- return Cache::remember($key, now()->addMinutes(15), function() use ($showNsfw) {
- $type = $this->type ?? $this->setType();
- $is_nsfw = !$showNsfw ? $this->is_nsfw : false;
- if ($this->media->count() == 0 || $is_nsfw || !in_array($type,['photo', 'photo:album', 'video'])) {
- return url(Storage::url('public/no-preview.png'));
- }
+ public function thumb($showNsfw = false)
+ {
+ $key = $showNsfw ? 'status:thumb:nsfw1'.$this->id : 'status:thumb:nsfw0'.$this->id;
+ return Cache::remember($key, now()->addMinutes(15), function() use ($showNsfw) {
+ $type = $this->type ?? $this->setType();
+ $is_nsfw = !$showNsfw ? $this->is_nsfw : false;
+ if ($this->media->count() == 0 || $is_nsfw || !in_array($type,['photo', 'photo:album', 'video'])) {
+ return url(Storage::url('public/no-preview.png'));
+ }
- return url(Storage::url($this->firstMedia()->thumbnail_path));
- });
- }
+ return url(Storage::url($this->firstMedia()->thumbnail_path));
+ });
+ }
- public function url()
- {
- if($this->uri) {
- return $this->uri;
- } else {
- $id = $this->id;
- $username = $this->profile->username;
- $path = url(config('app.url')."/p/{$username}/{$id}");
- return $path;
- }
- }
+ public function url($forceLocal = false)
+ {
+ if($this->uri) {
+ return $forceLocal ? "/i/web/post/_/{$this->profile_id}/{$this->id}" : $this->uri;
+ } else {
+ $id = $this->id;
+ $username = $this->profile->username;
+ $path = url(config('app.url')."/p/{$username}/{$id}");
+ return $path;
+ }
+ }
- public function permalink($suffix = '/activity')
- {
- $id = $this->id;
- $username = $this->profile->username;
- $path = config('app.url')."/p/{$username}/{$id}{$suffix}";
+ public function permalink($suffix = '/activity')
+ {
+ $id = $this->id;
+ $username = $this->profile->username;
+ $path = config('app.url')."/p/{$username}/{$id}{$suffix}";
- return url($path);
- }
+ return url($path);
+ }
- public function editUrl()
- {
- return $this->url().'/edit';
- }
+ public function editUrl()
+ {
+ return $this->url().'/edit';
+ }
- public function mediaUrl()
- {
- $media = $this->firstMedia();
- $path = $media->media_path;
- $hash = is_null($media->processed_at) ? md5('unprocessed') : md5($media->created_at);
- $url = $media->cdn_url ? $media->cdn_url . "?v={$hash}" : url(Storage::url($path)."?v={$hash}");
+ public function mediaUrl()
+ {
+ $media = $this->firstMedia();
+ $path = $media->media_path;
+ $hash = is_null($media->processed_at) ? md5('unprocessed') : md5($media->created_at);
+ $url = $media->cdn_url ? $media->cdn_url . "?v={$hash}" : url(Storage::url($path)."?v={$hash}");
- return $url;
- }
+ return $url;
+ }
- public function likes()
- {
- return $this->hasMany(Like::class);
- }
+ public function likes()
+ {
+ return $this->hasMany(Like::class);
+ }
- public function liked() : bool
- {
- if(!Auth::check()) {
- return false;
- }
+ public function liked() : bool
+ {
+ if(!Auth::check()) {
+ return false;
+ }
- $pid = Auth::user()->profile_id;
+ $pid = Auth::user()->profile_id;
- return Like::select('status_id', 'profile_id')
- ->whereStatusId($this->id)
- ->whereProfileId($pid)
- ->exists();
- }
+ return Like::select('status_id', 'profile_id')
+ ->whereStatusId($this->id)
+ ->whereProfileId($pid)
+ ->exists();
+ }
- public function likedBy()
- {
- return $this->hasManyThrough(
- Profile::class,
- Like::class,
- 'status_id',
- 'id',
- 'id',
- 'profile_id'
- );
- }
+ public function likedBy()
+ {
+ return $this->hasManyThrough(
+ Profile::class,
+ Like::class,
+ 'status_id',
+ 'id',
+ 'id',
+ 'profile_id'
+ );
+ }
- public function comments()
- {
- return $this->hasMany(self::class, 'in_reply_to_id');
- }
+ public function comments()
+ {
+ return $this->hasMany(self::class, 'in_reply_to_id');
+ }
- public function bookmarked()
- {
- if (!Auth::check()) {
- return false;
- }
- $profile = Auth::user()->profile;
+ public function bookmarked()
+ {
+ if (!Auth::check()) {
+ return false;
+ }
+ $profile = Auth::user()->profile;
- return Bookmark::whereProfileId($profile->id)->whereStatusId($this->id)->count();
- }
+ return Bookmark::whereProfileId($profile->id)->whereStatusId($this->id)->count();
+ }
- public function shares()
- {
- return $this->hasMany(self::class, 'reblog_of_id');
- }
+ public function shares()
+ {
+ return $this->hasMany(self::class, 'reblog_of_id');
+ }
- public function shared() : bool
- {
- if(!Auth::check()) {
- return false;
- }
- $pid = Auth::user()->profile_id;
+ public function shared() : bool
+ {
+ if(!Auth::check()) {
+ return false;
+ }
+ $pid = Auth::user()->profile_id;
- return $this->select('profile_id', 'reblog_of_id')
- ->whereProfileId($pid)
- ->whereReblogOfId($this->id)
- ->exists();
- }
+ return $this->select('profile_id', 'reblog_of_id')
+ ->whereProfileId($pid)
+ ->whereReblogOfId($this->id)
+ ->exists();
+ }
- public function sharedBy()
- {
- return $this->hasManyThrough(
- Profile::class,
- Status::class,
- 'reblog_of_id',
- 'id',
- 'id',
- 'profile_id'
- );
- }
+ public function sharedBy()
+ {
+ return $this->hasManyThrough(
+ Profile::class,
+ Status::class,
+ 'reblog_of_id',
+ 'id',
+ 'id',
+ 'profile_id'
+ );
+ }
- public function parent()
- {
- $parent = $this->in_reply_to_id ?? $this->reblog_of_id;
- if (!empty($parent)) {
- return $this->findOrFail($parent);
- } else {
- return false;
- }
- }
+ public function parent()
+ {
+ $parent = $this->in_reply_to_id ?? $this->reblog_of_id;
+ if (!empty($parent)) {
+ return $this->findOrFail($parent);
+ } else {
+ return false;
+ }
+ }
- public function conversation()
- {
- return $this->hasOne(Conversation::class);
- }
+ public function conversation()
+ {
+ return $this->hasOne(Conversation::class);
+ }
- public function hashtags()
- {
- return $this->hasManyThrough(
- Hashtag::class,
- StatusHashtag::class,
- 'status_id',
- 'id',
- 'id',
- 'hashtag_id'
- );
- }
+ public function hashtags()
+ {
+ return $this->hasManyThrough(
+ Hashtag::class,
+ StatusHashtag::class,
+ 'status_id',
+ 'id',
+ 'id',
+ 'hashtag_id'
+ );
+ }
- public function mentions()
- {
- return $this->hasManyThrough(
- Profile::class,
- Mention::class,
- 'status_id',
- 'id',
- 'id',
- 'profile_id'
- );
- }
+ public function mentions()
+ {
+ return $this->hasManyThrough(
+ Profile::class,
+ Mention::class,
+ 'status_id',
+ 'id',
+ 'id',
+ 'profile_id'
+ );
+ }
- public function reportUrl()
- {
- return route('report.form')."?type=post&id={$this->id}";
- }
+ public function reportUrl()
+ {
+ return route('report.form')."?type=post&id={$this->id}";
+ }
- public function toActivityStream()
- {
- $media = $this->media;
- $mediaCollection = [];
- foreach ($media as $image) {
- $mediaCollection[] = [
- 'type' => 'Link',
- 'href' => $image->url(),
- 'mediaType' => $image->mime,
- ];
- }
- $obj = [
- '@context' => 'https://www.w3.org/ns/activitystreams',
- 'type' => 'Image',
- 'name' => null,
- 'url' => $mediaCollection,
- ];
+ public function toActivityStream()
+ {
+ $media = $this->media;
+ $mediaCollection = [];
+ foreach ($media as $image) {
+ $mediaCollection[] = [
+ 'type' => 'Link',
+ 'href' => $image->url(),
+ 'mediaType' => $image->mime,
+ ];
+ }
+ $obj = [
+ '@context' => 'https://www.w3.org/ns/activitystreams',
+ 'type' => 'Image',
+ 'name' => null,
+ 'url' => $mediaCollection,
+ ];
- return $obj;
- }
+ return $obj;
+ }
- public function replyToText()
- {
- $actorName = $this->profile->username;
+ public function replyToText()
+ {
+ $actorName = $this->profile->username;
- return "{$actorName} ".__('notification.commented');
- }
+ return "{$actorName} ".__('notification.commented');
+ }
- public function replyToHtml()
- {
- $actorName = $this->profile->username;
- $actorUrl = $this->profile->url();
+ public function replyToHtml()
+ {
+ $actorName = $this->profile->username;
+ $actorUrl = $this->profile->url();
- return "{$actorName} ".
- __('notification.commented');
- }
+ return "{$actorName} ".
+ __('notification.commented');
+ }
- public function shareToText()
- {
- $actorName = $this->profile->username;
+ public function shareToText()
+ {
+ $actorName = $this->profile->username;
- return "{$actorName} ".__('notification.shared');
- }
+ return "{$actorName} ".__('notification.shared');
+ }
- public function shareToHtml()
- {
- $actorName = $this->profile->username;
- $actorUrl = $this->profile->url();
+ public function shareToHtml()
+ {
+ $actorName = $this->profile->username;
+ $actorUrl = $this->profile->url();
- return "{$actorName} ".
- __('notification.shared');
- }
+ return "{$actorName} ".
+ __('notification.shared');
+ }
- public function recentComments()
- {
- return $this->comments()->orderBy('created_at', 'desc')->take(3);
- }
+ public function recentComments()
+ {
+ 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' => $this->created_at->format('c'),
- 'to' => $to,
- 'cc' => $cc,
- 'object' => [
- 'id' => $this->url(),
- 'type' => 'Note',
- 'summary' => null,
- 'inReplyTo' => null,
- 'published' => $this->created_at->format('c'),
- '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 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' => $this->created_at->format('c'),
+ 'to' => $to,
+ 'cc' => $cc,
+ 'object' => [
+ 'id' => $this->url(),
+ 'type' => 'Note',
+ 'summary' => null,
+ 'inReplyTo' => null,
+ 'published' => $this->created_at->format('c'),
+ '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) {
- return;
- }
- $res = [];
- $res['to'] = [];
- $res['cc'] = [];
- $scope = $this->scope;
- $mentions = $this->mentions->map(function ($mention) {
- return $mention->permalink();
- })->toArray();
+ public function scopeToAudience($audience)
+ {
+ if(!in_array($audience, ['to', 'cc']) || $this->local == false) {
+ return;
+ }
+ $res = [];
+ $res['to'] = [];
+ $res['cc'] = [];
+ $scope = $this->scope;
+ $mentions = $this->mentions->map(function ($mention) {
+ return $mention->permalink();
+ })->toArray();
- if($this->in_reply_to_id != null) {
- $parent = $this->parent();
- if($parent) {
- $mentions = array_merge([$parent->profile->permalink()], $mentions);
- }
- }
+ if($this->in_reply_to_id != null) {
+ $parent = $this->parent();
+ if($parent) {
+ $mentions = array_merge([$parent->profile->permalink()], $mentions);
+ }
+ }
- switch ($scope) {
- case 'public':
- $res['to'] = [
- "https://www.w3.org/ns/activitystreams#Public"
- ];
- $res['cc'] = array_merge([$this->profile->permalink('/followers')], $mentions);
- break;
+ switch ($scope) {
+ case 'public':
+ $res['to'] = [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ];
+ $res['cc'] = array_merge([$this->profile->permalink('/followers')], $mentions);
+ break;
- case 'unlisted':
- $res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
- $res['cc'] = [
- "https://www.w3.org/ns/activitystreams#Public"
- ];
- break;
+ case 'unlisted':
+ $res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
+ $res['cc'] = [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ];
+ break;
- case 'private':
- $res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
- $res['cc'] = [];
- break;
+ case 'private':
+ $res['to'] = array_merge([$this->profile->permalink('/followers')], $mentions);
+ $res['cc'] = [];
+ break;
- // TODO: Update scope when DMs are supported
- case 'direct':
- $res['to'] = [];
- $res['cc'] = [];
- break;
- }
- return $res[$audience];
- }
+ // TODO: Update scope when DMs are supported
+ case 'direct':
+ $res['to'] = [];
+ $res['cc'] = [];
+ break;
+ }
+ return $res[$audience];
+ }
- public function place()
- {
- return $this->belongsTo(Place::class);
- }
+ public function place()
+ {
+ return $this->belongsTo(Place::class);
+ }
- public function directMessage()
- {
- return $this->hasOne(DirectMessage::class);
- }
+ public function directMessage()
+ {
+ return $this->hasOne(DirectMessage::class);
+ }
}