StatusController.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Auth, Cache;
  4. use League\Fractal;
  5. use Illuminate\Http\Request;
  6. use Vinkla\Hashids\Facades\Hashids;
  7. use App\{Media, Profile, Status, User};
  8. use App\Jobs\ImageOptimizePipeline\ImageOptimize;
  9. use App\Transformer\ActivityPub\StatusTransformer;
  10. use App\Jobs\StatusPipeline\{NewStatusPipeline, StatusDelete};
  11. class StatusController extends Controller
  12. {
  13. public function show(Request $request, $username, int $id)
  14. {
  15. $user = Profile::whereUsername($username)->firstOrFail();
  16. $status = Status::whereProfileId($user->id)
  17. ->withCount(['likes', 'comments', 'media'])
  18. ->findOrFail($id);
  19. if(!$status->media_path && $status->in_reply_to_id) {
  20. return redirect($status->url());
  21. }
  22. if($request->wantsJson() && config('pixelfed.activitypub_enabled')) {
  23. return $this->showActivityPub($request, $status);
  24. }
  25. $replies = Status::whereInReplyToId($status->id)->simplePaginate(30);
  26. return view('status.show', compact('user', 'status', 'replies'));
  27. }
  28. public function compose()
  29. {
  30. $this->authCheck();
  31. return view('status.compose');
  32. }
  33. public function store(Request $request)
  34. {
  35. if(Auth::check() == false)
  36. {
  37. abort(403);
  38. }
  39. $user = Auth::user();
  40. $size = Media::whereUserId($user->id)->sum('size') / 1000;
  41. $limit = (int) config('pixelfed.max_account_size');
  42. if($size >= $limit) {
  43. return redirect()->back()->with('error', 'You have exceeded your storage limit. Please click <a href="#">here</a> for more info.');
  44. }
  45. $this->validate($request, [
  46. 'photo.*' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'),
  47. 'caption' => 'string|max:' . config('pixelfed.max_caption_length'),
  48. 'cw' => 'nullable|string',
  49. 'filter_class' => 'nullable|string',
  50. 'filter_name' => 'nullable|string',
  51. ]);
  52. if(count($request->file('photo')) > config('pixelfed.max_album_length')) {
  53. return redirect()->back()->with('error', 'Too many files, max limit per post: ' . config('pixelfed.max_album_length'));
  54. }
  55. $cw = $request->filled('cw') && $request->cw == 'on' ? true : false;
  56. $monthHash = hash('sha1', date('Y') . date('m'));
  57. $userHash = hash('sha1', $user->id . (string) $user->created_at);
  58. $profile = $user->profile;
  59. $status = new Status;
  60. $status->profile_id = $profile->id;
  61. $status->caption = strip_tags($request->caption);
  62. $status->is_nsfw = $cw;
  63. $status->save();
  64. $photos = $request->file('photo');
  65. $order = 1;
  66. foreach ($photos as $k => $v) {
  67. $storagePath = "public/m/{$monthHash}/{$userHash}";
  68. $path = $v->store($storagePath);
  69. $media = new Media;
  70. $media->status_id = $status->id;
  71. $media->profile_id = $profile->id;
  72. $media->user_id = $user->id;
  73. $media->media_path = $path;
  74. $media->size = $v->getClientSize();
  75. $media->mime = $v->getClientMimeType();
  76. $media->filter_class = $request->input('filter_class');
  77. $media->filter_name = $request->input('filter_name');
  78. $media->order = $order;
  79. $media->save();
  80. ImageOptimize::dispatch($media);
  81. $order++;
  82. }
  83. NewStatusPipeline::dispatch($status);
  84. // TODO: Send to subscribers
  85. return redirect($status->url());
  86. }
  87. public function delete(Request $request)
  88. {
  89. if(!Auth::check()) {
  90. abort(403);
  91. }
  92. $this->validate($request, [
  93. 'type' => 'required|string',
  94. 'item' => 'required|integer|min:1'
  95. ]);
  96. $status = Status::findOrFail($request->input('item'));
  97. if($status->profile_id === Auth::user()->profile->id || Auth::user()->is_admin == true) {
  98. StatusDelete::dispatch($status);
  99. }
  100. return redirect(Auth::user()->url());
  101. }
  102. public function storeShare(Request $request)
  103. {
  104. $this->validate($request, [
  105. 'item' => 'required|integer',
  106. ]);
  107. $profile = Auth::user()->profile;
  108. $status = Status::withCount('shares')->findOrFail($request->input('item'));
  109. $count = $status->shares_count;
  110. $exists = Status::whereProfileId(Auth::user()->profile->id)
  111. ->whereReblogOfId($status->id)
  112. ->count();
  113. if($exists !== 0) {
  114. $shares = Status::whereProfileId(Auth::user()->profile->id)
  115. ->whereReblogOfId($status->id)
  116. ->get();
  117. foreach($shares as $share) {
  118. $share->delete();
  119. $count--;
  120. }
  121. } else {
  122. $share = new Status;
  123. $share->profile_id = $profile->id;
  124. $share->reblog_of_id = $status->id;
  125. $share->save();
  126. $count++;
  127. }
  128. if($request->ajax()) {
  129. $response = ['code' => 200, 'msg' => 'Share saved', 'count' => $count];
  130. } else {
  131. $response = redirect($status->url());
  132. }
  133. return $response;
  134. }
  135. public function showActivityPub(Request $request, $status)
  136. {
  137. $fractal = new Fractal\Manager();
  138. $resource = new Fractal\Resource\Item($status, new StatusTransformer);
  139. $res = $fractal->createData($resource)->toArray();
  140. return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json');
  141. }
  142. protected function authCheck()
  143. {
  144. if(Auth::check() == false)
  145. {
  146. abort(403);
  147. }
  148. }
  149. }