1
0

SearchController.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Auth;
  4. use App\Hashtag;
  5. use App\Profile;
  6. use App\Status;
  7. use Illuminate\Http\Request;
  8. use App\Util\ActivityPub\Helpers;
  9. use Illuminate\Support\Facades\Cache;
  10. use Illuminate\Support\Str;
  11. use App\Transformer\Api\{
  12. AccountTransformer,
  13. HashtagTransformer,
  14. StatusTransformer,
  15. };
  16. class SearchController extends Controller
  17. {
  18. public function __construct()
  19. {
  20. $this->middleware('auth');
  21. }
  22. public function searchAPI(Request $request)
  23. {
  24. $this->validate($request, [
  25. 'q' => 'required|string|min:3|max:120',
  26. 'src' => 'required|string|in:metro',
  27. 'v' => 'required|integer|in:1'
  28. ]);
  29. $tag = $request->input('q');
  30. $tag = e(urldecode($tag));
  31. $hash = hash('sha256', $tag);
  32. $tokens = Cache::remember('api:search:tag:'.$hash, now()->addMinutes(5), function () use ($tag) {
  33. $tokens = [];
  34. if(Helpers::validateUrl($tag) != false && config('federation.activitypub.enabled') == true && config('federation.activitypub.remoteFollow') == true) {
  35. abort_if(Helpers::validateLocalUrl($tag), 404);
  36. $remote = Helpers::fetchFromUrl($tag);
  37. if(isset($remote['type']) && in_array($remote['type'], ['Note', 'Person']) == true) {
  38. $type = $remote['type'];
  39. if($type == 'Person') {
  40. $item = Helpers::profileFirstOrNew($tag);
  41. $tokens['profiles'] = [[
  42. 'count' => 1,
  43. 'url' => $item->url(),
  44. 'type' => 'profile',
  45. 'value' => $item->username,
  46. 'tokens' => [$item->username],
  47. 'name' => $item->name,
  48. 'entity' => [
  49. 'id' => (string) $item->id,
  50. 'following' => $item->followedBy(Auth::user()->profile),
  51. 'follow_request' => $item->hasFollowRequestById(Auth::user()->profile_id),
  52. 'thumb' => $item->avatarUrl(),
  53. 'local' => (bool) !$item->domain
  54. ]
  55. ]];
  56. } else if ($type == 'Note') {
  57. $item = Helpers::statusFetch($tag);
  58. $tokens['posts'] = [[
  59. 'count' => 0,
  60. 'url' => $item->url(),
  61. 'type' => 'status',
  62. 'value' => "by {$item->profile->username} <span class='float-right'>{$item->created_at->diffForHumans(null, true, true)}</span>",
  63. 'tokens' => [$item->caption],
  64. 'name' => $item->caption,
  65. 'thumb' => $item->thumb(),
  66. ]];
  67. }
  68. }
  69. }
  70. $htag = Str::startsWith($tag, '#') == true ? mb_substr($tag, 1) : $tag;
  71. $hashtags = Hashtag::select('id', 'name', 'slug')
  72. ->where('slug', 'like', '%'.$htag.'%')
  73. ->whereHas('posts')
  74. ->limit(20)
  75. ->get();
  76. if($hashtags->count() > 0) {
  77. $tags = $hashtags->map(function ($item, $key) {
  78. return [
  79. 'count' => $item->posts()->count(),
  80. 'url' => $item->url(),
  81. 'type' => 'hashtag',
  82. 'value' => $item->name,
  83. 'tokens' => '',
  84. 'name' => null,
  85. ];
  86. });
  87. $tokens['hashtags'] = $tags;
  88. }
  89. return $tokens;
  90. });
  91. $users = Profile::select('domain', 'username', 'name', 'id')
  92. ->whereNull('status')
  93. ->whereNull('domain')
  94. ->where('id', '!=', Auth::user()->profile->id)
  95. ->where('username', 'like', '%'.$tag.'%')
  96. //->orWhere('remote_url', $tag)
  97. ->limit(20)
  98. ->get();
  99. if($users->count() > 0) {
  100. $profiles = $users->map(function ($item, $key) {
  101. return [
  102. 'count' => 0,
  103. 'url' => $item->url(),
  104. 'type' => 'profile',
  105. 'value' => $item->username,
  106. 'tokens' => [$item->username],
  107. 'name' => $item->name,
  108. 'avatar' => $item->avatarUrl(),
  109. 'id' => $item->id,
  110. 'entity' => [
  111. 'id' => (string) $item->id,
  112. 'following' => $item->followedBy(Auth::user()->profile),
  113. 'follow_request' => $item->hasFollowRequestById(Auth::user()->profile_id),
  114. 'thumb' => $item->avatarUrl(),
  115. 'local' => (bool) !$item->domain
  116. ]
  117. ];
  118. });
  119. if(isset($tokens['profiles'])) {
  120. array_push($tokens['profiles'], $profiles);
  121. } else {
  122. $tokens['profiles'] = $profiles;
  123. }
  124. }
  125. $posts = Status::select('id', 'profile_id', 'caption', 'created_at')
  126. ->whereHas('media')
  127. ->whereNull('in_reply_to_id')
  128. ->whereNull('reblog_of_id')
  129. ->whereProfileId(Auth::user()->profile->id)
  130. ->where('caption', 'like', '%'.$tag.'%')
  131. ->latest()
  132. ->limit(10)
  133. ->get();
  134. if($posts->count() > 0) {
  135. $posts = $posts->map(function($item, $key) {
  136. return [
  137. 'count' => 0,
  138. 'url' => $item->url(),
  139. 'type' => 'status',
  140. 'value' => "by {$item->profile->username} <span class='float-right'>{$item->created_at->diffForHumans(null, true, true)}</span>",
  141. 'tokens' => [$item->caption],
  142. 'name' => $item->caption,
  143. 'thumb' => $item->thumb(),
  144. 'filter' => $item->firstMedia()->filter_class
  145. ];
  146. });
  147. $tokens['posts'] = $posts;
  148. }
  149. return response()->json($tokens);
  150. }
  151. public function results(Request $request)
  152. {
  153. $this->validate($request, [
  154. 'q' => 'required|string|min:1',
  155. ]);
  156. return view('search.results');
  157. }
  158. }