ApiController.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use Cache;
  5. use \Zttp\Zttp;
  6. use App\Instance;
  7. use Illuminate\Support\Str;
  8. use App\Services\PixelfedVersions;
  9. class ApiController extends Controller
  10. {
  11. public function instances(Request $request)
  12. {
  13. $this->validate($request, [
  14. 'page' => 'nullable|integer|min:1',
  15. 'latestVersionOnly' => 'nullable',
  16. 'allowsVideos' => 'nullable',
  17. 'openRegistration' => 'nullable',
  18. 'albumSizeRange' => 'required|integer|min:0|max:20',
  19. 'fileSizeLimit' => 'integer|min:1|max:100'
  20. ]);
  21. $albumLimit = (int) $request->input('albumSizeRange');
  22. $i = Instance::query();
  23. $i->whereNotNull('approved_at')
  24. ->where('nodeinfo->metadata->config->uploader->album_limit', '>=', $albumLimit);
  25. if($request->openRegistration == 'true') {
  26. $i->where('nodeinfo->openRegistrations', true);
  27. }
  28. if($request->latestVersionOnly == 'true') {
  29. $i->where('nodeinfo->software->version', PixelfedVersions::latest());
  30. }
  31. if($request->allowsVideos == 'true') {
  32. $i->where('nodeinfo->metadata->config->uploader->media_types', 'like', '%mp4%');
  33. }
  34. if($request->input('fileSizeLimit') !== 15) {
  35. $sizeLimit = $request->input('fileSizeLimit') * 1000;
  36. $i->where('nodeinfo->metadata->config->uploader->max_photo_size', '>=', $sizeLimit);
  37. }
  38. return $i->paginate(20);
  39. }
  40. public function instance(Request $request, $domain)
  41. {
  42. $instance = Instance::whereNotNull('approved_at')
  43. ->whereDomain($domain)
  44. ->whereIn('nodeinfo->software->version', PixelfedVersions::get())
  45. ->firstOrFail();
  46. return $instance;
  47. }
  48. public function instanceTimeline(Request $request, $domain)
  49. {
  50. $this->validate($request, [
  51. 'limit' => 'nullable|integer|min:1|max:20'
  52. ]);
  53. $instance = Instance::whereNotNull('approved_at')
  54. ->whereDomain($domain)
  55. ->firstOrFail();
  56. $key = 'delta:instance:timeline:' . $instance->id;
  57. $ttl = now()->addDays(12);
  58. $res = Cache::remember($key, $ttl, function () use ($domain) {
  59. $url = "https://{$domain}/api/v1/timelines/public?limit=20";
  60. $timeline = Zttp::get($url);
  61. $body = collect($timeline->json())
  62. ->filter(function($v, $k) {
  63. return $v['sensitive'] == false && !empty($v['media_attachments']);
  64. })->map(function($p, $k) {
  65. $thumb = 'https://px03-camo.pixelfedcdn.com/img-proxy?resource=' . encrypt($p['media_attachments'][0]['preview_url']);
  66. return [
  67. 'id' => $p['id'],
  68. 'url' => $p['url'],
  69. 'thumbnail' => $thumb
  70. ];
  71. });
  72. return $body->toArray();
  73. });
  74. if($request->input('limit')) {
  75. $res = array_slice($res, 0, (int) $request->limit);
  76. }
  77. return $res;
  78. }
  79. public function imageProxy(Request $request)
  80. {
  81. $resource = decrypt($request->input('resource'));
  82. if(!$resource || !Str::startsWith($resource, 'https://') || !Str::endsWith($resource, ['.jpg', '.png', '.jpeg'])) {
  83. abort(404, 'Invalid resource');
  84. }
  85. $mime = Str::endsWith($resource, '.png') ? 'image/png' : 'image/jpeg';
  86. $hash = hash('sha512', $resource);
  87. $key = 'delta:proxy:img:hash:' . $hash;
  88. $ttl = now()->addHours(6);
  89. $res = Cache::remember($key, $ttl, function () use ($resource) {
  90. $options = [
  91. 'http' => [
  92. 'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
  93. ]
  94. ];
  95. $context = stream_context_create($options);
  96. return file_get_contents($resource, false, $context);
  97. });
  98. return response($res)->header('Content-Type', $mime);
  99. }
  100. public function stats(Request $request)
  101. {
  102. return Cache::remember('instances:stats', now()->addHours(12), function() {
  103. return [
  104. 'post_count' => Instance::sum('post_count'),
  105. 'user_count' => Instance::sum('user_count'),
  106. 'instance_count' => Instance::whereNotNull('approved_at')->count(),
  107. ];
  108. });
  109. }
  110. }