1
0

ApiV1Controller.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use Illuminate\Http\Request;
  4. use App\Http\Controllers\Controller;
  5. use Illuminate\Support\Str;
  6. use App\Jobs\StatusPipeline\StatusDelete;
  7. use Laravel\Passport\Passport;
  8. use Auth, Cache, DB;
  9. use App\{
  10. Like,
  11. Media,
  12. Profile,
  13. Status
  14. };
  15. use League\Fractal;
  16. use App\Transformer\Api\{
  17. AccountTransformer,
  18. RelationshipTransformer,
  19. StatusTransformer,
  20. };
  21. use League\Fractal\Serializer\ArraySerializer;
  22. use League\Fractal\Pagination\IlluminatePaginatorAdapter;
  23. use App\Services\NotificationService;
  24. class ApiV1Controller extends Controller
  25. {
  26. protected $fractal;
  27. public function __construct()
  28. {
  29. $this->fractal = new Fractal\Manager();
  30. $this->fractal->setSerializer(new ArraySerializer());
  31. }
  32. public function apps(Request $request)
  33. {
  34. abort_if(!config('pixelfed.oauth_enabled'), 404);
  35. $this->validate($request, [
  36. 'client_name' => 'required',
  37. 'redirect_uris' => 'required',
  38. 'scopes' => 'nullable',
  39. 'website' => 'nullable'
  40. ]);
  41. $client = Passport::client()->forceFill([
  42. 'user_id' => null,
  43. 'name' => e($request->client_name),
  44. 'secret' => Str::random(40),
  45. 'redirect' => $request->redirect_uris,
  46. 'personal_access_client' => false,
  47. 'password_client' => false,
  48. 'revoked' => false,
  49. ]);
  50. $client->save();
  51. $res = [
  52. 'id' => $client->id,
  53. 'name' => $client->name,
  54. 'website' => null,
  55. 'redirect_uri' => $client->redirect,
  56. 'client_id' => $client->id,
  57. 'client_secret' => $client->secret,
  58. 'vapid_key' => null
  59. ];
  60. return $res;
  61. }
  62. /**
  63. * GET /api/v1/accounts/{id}
  64. *
  65. * @param integer $id
  66. *
  67. * @return \App\Transformer\Api\AccountTransformer
  68. */
  69. public function accountById(Request $request, $id)
  70. {
  71. $profile = Profile::whereNull('status')->findOrFail($id);
  72. $resource = new Fractal\Resource\Item($profile, new AccountTransformer());
  73. $res = $this->fractal->createData($resource)->toArray();
  74. return response()->json($res);
  75. }
  76. /**
  77. * PATCH /api/v1/accounts/update_credentials
  78. *
  79. * @return \App\Transformer\Api\AccountTransformer
  80. */
  81. public function accountUpdateCredentials(Request, $request)
  82. {
  83. abort_if(!$request->user(), 403);
  84. $this->validate($request, [
  85. 'display_name' => 'nullable|string',
  86. 'note' => 'nullable|string',
  87. 'locked' => 'nullable|boolean',
  88. // 'source.privacy' => 'nullable|in:unlisted,public,private',
  89. // 'source.sensitive' => 'nullable|boolean'
  90. ]);
  91. $user = $request->user();
  92. $profile = $user->profile;
  93. $displayName = $request->input('display_name');
  94. $note = $request->input('note');
  95. $locked = $request->input('locked');
  96. // $privacy = $request->input('source.privacy');
  97. // $sensitive = $request->input('source.sensitive');
  98. $changes = false;
  99. if($displayName !== $user->name) {
  100. $user->name = $displayName;
  101. $profile->name = $displayName;
  102. $changes = true;
  103. }
  104. if($note !== $profile->bio) {
  105. $profile->bio = e($note);
  106. $changes = true;
  107. }
  108. if(!is_null($locked)) {
  109. $profile->is_private = $locked;
  110. $changes = true;
  111. }
  112. if($changes) {
  113. $user->save();
  114. $profile->save()
  115. }
  116. $resource = new Fractal\Resource\Item($profile, new AccountTransformer());
  117. $res = $this->fractal->createData($resource)->toArray();
  118. return response()->json($res);
  119. }
  120. /**
  121. * GET /api/v1/accounts/{id}/followers
  122. *
  123. * @param integer $id
  124. *
  125. * @return \App\Transformer\Api\AccountTransformer
  126. */
  127. public function accountFollowersById(Request $request, $id)
  128. {
  129. abort_if(!$request->user(), 403);
  130. $profile = Profile::whereNull('status')->findOrFail($id);
  131. $settings = $profile->user->settings;
  132. if($settings->show_profile_followers == true) {
  133. $limit = $request->input('limit') ?? 40;
  134. $followers = $profile->followers()->paginate($limit);
  135. $resource = new Fractal\Resource\Collection($followers, new AccountTransformer());
  136. $res = $this->fractal->createData($resource)->toArray();
  137. } else {
  138. $res = [];
  139. }
  140. return response()->json($res);
  141. }
  142. /**
  143. * GET /api/v1/accounts/{id}/following
  144. *
  145. * @param integer $id
  146. *
  147. * @return \App\Transformer\Api\AccountTransformer
  148. */
  149. public function accountFollowingById(Request $request, $id)
  150. {
  151. abort_if(!$request->user(), 403);
  152. $profile = Profile::whereNull('status')->findOrFail($id);
  153. $settings = $profile->user->settings;
  154. if($settings->show_profile_following == true) {
  155. $limit = $request->input('limit') ?? 40;
  156. $following = $profile->following()->paginate($limit);
  157. $resource = new Fractal\Resource\Collection($following, new AccountTransformer());
  158. $res = $this->fractal->createData($resource)->toArray();
  159. } else {
  160. $res = [];
  161. }
  162. return response()->json($res);
  163. }
  164. public function statusById(Request $request, $id)
  165. {
  166. $status = Status::whereVisibility('public')->findOrFail($id);
  167. $resource = new Fractal\Resource\Item($status, new StatusTransformer());
  168. $res = $this->fractal->createData($resource)->toArray();
  169. return response()->json($res);
  170. }
  171. public function instance(Request $request)
  172. {
  173. $res = [
  174. 'description' => 'Pixelfed - Photo sharing for everyone',
  175. 'email' => config('instance.email'),
  176. 'languages' => ['en'],
  177. 'max_toot_chars' => config('pixelfed.max_caption_length'),
  178. 'registrations' => config('pixelfed.open_registration'),
  179. 'stats' => [
  180. 'user_count' => 0,
  181. 'status_count' => 0,
  182. 'domain_count' => 0
  183. ],
  184. 'thumbnail' => config('app.url') . '/img/pixelfed-icon-color.png',
  185. 'title' => 'Pixelfed (' . config('pixelfed.domain.app') . ')',
  186. 'uri' => config('app.url'),
  187. 'urls' => [],
  188. 'version' => '2.7.2 (compatible; Pixelfed ' . config('pixelfed.version') . ')'
  189. ];
  190. return response()->json($res, 200, [], JSON_PRETTY_PRINT);
  191. }
  192. public function filters(Request $request)
  193. {
  194. // Pixelfed does not yet support keyword filters
  195. return response()->json([]);
  196. }
  197. public function context(Request $request)
  198. {
  199. // todo
  200. $res = [
  201. 'ancestors' => [],
  202. 'descendants' => []
  203. ];
  204. return response()->json($res);
  205. }
  206. public function createStatus(Request $request)
  207. {
  208. abort_if(!$request->user(), 403);
  209. $this->validate($request, [
  210. 'status' => 'string',
  211. 'media_ids' => 'array',
  212. 'media_ids.*' => 'integer|min:1',
  213. 'sensitive' => 'nullable|boolean',
  214. 'visibility' => 'string|in:private,unlisted,public',
  215. 'in_reply_to_id' => 'integer'
  216. ]);
  217. if(!$request->filled('media_ids') && !$request->filled('in_reply_to_id')) {
  218. abort(403, 'Empty statuses are not allowed');
  219. }
  220. }
  221. }