StatusRemoteUpdatePipeline.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. namespace App\Jobs\StatusPipeline;
  3. use Illuminate\Bus\Queueable;
  4. use Illuminate\Contracts\Queue\ShouldBeUnique;
  5. use Illuminate\Contracts\Queue\ShouldQueue;
  6. use Illuminate\Foundation\Bus\Dispatchable;
  7. use Illuminate\Queue\InteractsWithQueue;
  8. use Illuminate\Queue\SerializesModels;
  9. use App\Media;
  10. use App\ModLog;
  11. use App\Status;
  12. use App\Models\StatusEdit;
  13. use App\Services\StatusService;
  14. use Purify;
  15. class StatusRemoteUpdatePipeline implements ShouldQueue
  16. {
  17. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  18. public $activity;
  19. /**
  20. * Create a new job instance.
  21. */
  22. public function __construct($activity)
  23. {
  24. $this->activity = $activity;
  25. }
  26. /**
  27. * Execute the job.
  28. */
  29. public function handle(): void
  30. {
  31. $ts = (string) microtime(true);
  32. \Log::info('AP:inbox Update:Job invoked ' . $ts);
  33. $activity = $this->activity;
  34. $status = Status::with('media')->whereObjectUrl($activity['id'])->first();
  35. if(!$status) {
  36. \Log::info('AP:inbox Update:Job notFound ' . $ts . ' activity: ' . $activity);
  37. return;
  38. }
  39. $this->createPreviousEdit($status);
  40. $this->updateMedia($status, $activity);
  41. $this->updateImmediateAttributes($status, $activity);
  42. $this->createEdit($status, $activity);
  43. }
  44. protected function createPreviousEdit($status)
  45. {
  46. if(!$status->edits()->count()) {
  47. StatusEdit::create([
  48. 'status_id' => $status->id,
  49. 'profile_id' => $status->profile_id,
  50. 'caption' => $status->caption,
  51. 'spoiler_text' => $status->cw_summary,
  52. 'is_nsfw' => $status->is_nsfw,
  53. 'ordered_media_attachment_ids' => $status->media()->orderBy('order')->pluck('id')->toArray(),
  54. 'created_at' => $status->created_at
  55. ]);
  56. }
  57. }
  58. protected function updateMedia($status, $activity)
  59. {
  60. if(!isset($activity['attachment'])) {
  61. return;
  62. }
  63. $ogm = $status->media->count() ? $status->media()->orderBy('order')->get() : collect([]);
  64. $nm = collect($activity['attachment'])->filter(function($nm) {
  65. return isset(
  66. $nm['type'],
  67. $nm['mediaType'],
  68. $nm['url']
  69. ) &&
  70. in_array($nm['type'], ['Document', 'Image', 'Video']) &&
  71. in_array($nm['mediaType'], explode(',', config('pixelfed.media_types')));
  72. });
  73. // Skip when no media
  74. if(!$ogm->count() && !$nm->count()) {
  75. return;
  76. }
  77. Media::whereProfileId($status->profile_id)
  78. ->whereStatusId($status->id)
  79. ->update([
  80. 'status_id' => null
  81. ]);
  82. $nm->each(function($n, $key) use($status) {
  83. $m = new Media;
  84. $m->status_id = $status->id;
  85. $m->profile_id = $status->profile_id;
  86. $m->remote_media = true;
  87. $m->media_path = $n['url'];
  88. $m->caption = isset($n['name']) && !empty($n['name']) ? Purify::clean($n['name']) : null;
  89. $m->remote_url = $n['url'];
  90. $m->width = isset($n['width']) && !empty($n['width']) ? $n['width'] : null;
  91. $m->height = isset($n['height']) && !empty($n['height']) ? $n['height'] : null;
  92. $m->skip_optimize = true;
  93. $m->order = $key + 1;
  94. $m->save();
  95. });
  96. }
  97. protected function updateImmediateAttributes($status, $activity)
  98. {
  99. if(isset($activity['content'])) {
  100. $status->caption = strip_tags($activity['content']);
  101. $status->rendered = Purify::clean($activity['content']);
  102. }
  103. if(isset($activity['sensitive'])) {
  104. if((bool) $activity['sensitive'] == false) {
  105. $status->is_nsfw = false;
  106. $exists = ModLog::whereObjectType('App\Status::class')
  107. ->whereObjectId($status->id)
  108. ->whereAction('admin.status.moderate')
  109. ->exists();
  110. if($exists == true) {
  111. $status->is_nsfw = true;
  112. }
  113. $profile = Profile::find($status->profile_id);
  114. if(!$profile || $profile->cw == true) {
  115. $status->is_nsfw = true;
  116. }
  117. } else {
  118. $status->is_nsfw = true;
  119. }
  120. }
  121. if(isset($activity['summary'])) {
  122. $status->cw_summary = Purify::clean($activity['summary']);
  123. } else {
  124. $status->cw_summary = null;
  125. }
  126. $status->edited_at = now();
  127. $status->save();
  128. StatusService::del($status->id);
  129. }
  130. protected function createEdit($status, $activity)
  131. {
  132. $cleaned = isset($activity['content']) ? Purify::clean($activity['content']) : null;
  133. $spoiler_text = isset($activity['summary']) ? Purify::clean($attributes['summary']) : null;
  134. $sensitive = isset($activity['sensitive']) ? $activity['sensitive'] : null;
  135. $mids = $status->media()->count() ? $status->media()->orderBy('order')->pluck('id')->toArray() : null;
  136. StatusEdit::create([
  137. 'status_id' => $status->id,
  138. 'profile_id' => $status->profile_id,
  139. 'caption' => $cleaned,
  140. 'spoiler_text' => $spoiler_text,
  141. 'is_nsfw' => $sensitive,
  142. 'ordered_media_attachment_ids' => $mids
  143. ]);
  144. }
  145. }