WebfingerService.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <?php
  2. namespace App\Services;
  3. use App\Profile;
  4. use App\Util\ActivityPub\Helpers;
  5. use App\Util\Webfinger\WebfingerUrl;
  6. use Illuminate\Support\Facades\Http;
  7. class WebfingerService
  8. {
  9. public static function rawGet($url)
  10. {
  11. if (empty($url)) {
  12. return false;
  13. }
  14. $n = WebfingerUrl::get($url);
  15. if (! $n) {
  16. return false;
  17. }
  18. if (empty($n) || ! str_starts_with($n, 'https://')) {
  19. return false;
  20. }
  21. $host = parse_url($n, PHP_URL_HOST);
  22. if (! $host) {
  23. return false;
  24. }
  25. if (in_array($host, InstanceService::getBannedDomains())) {
  26. return false;
  27. }
  28. $webfinger = FetchCacheService::getJson($n);
  29. if (! $webfinger) {
  30. return false;
  31. }
  32. if (! isset($webfinger['links']) || ! is_array($webfinger['links']) || empty($webfinger['links'])) {
  33. return false;
  34. }
  35. $link = collect($webfinger['links'])
  36. ->filter(function ($link) {
  37. return $link &&
  38. isset($link['rel'], $link['type'], $link['href']) &&
  39. $link['rel'] === 'self' &&
  40. in_array($link['type'], ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"']);
  41. })
  42. ->pluck('href')
  43. ->first();
  44. return $link;
  45. }
  46. public static function lookup($query, $mastodonMode = false)
  47. {
  48. return (new self)->run($query, $mastodonMode);
  49. }
  50. protected function run($query, $mastodonMode)
  51. {
  52. if ($profile = Profile::whereUsername($query)->first()) {
  53. return $mastodonMode ?
  54. AccountService::getMastodon($profile->id, true) :
  55. AccountService::get($profile->id);
  56. }
  57. $url = WebfingerUrl::generateWebfingerUrl($query);
  58. if (! Helpers::validateUrl($url)) {
  59. return [];
  60. }
  61. try {
  62. $res = Http::retry(3, 100)
  63. ->acceptJson()
  64. ->withHeaders([
  65. 'User-Agent' => '(Pixelfed/'.config('pixelfed.version').'; +'.config('app.url').')',
  66. ])
  67. ->timeout(20)
  68. ->get($url);
  69. } catch (\Illuminate\Http\Client\ConnectionException $e) {
  70. return [];
  71. }
  72. if (! $res->successful()) {
  73. return [];
  74. }
  75. $webfinger = $res->json();
  76. if (! isset($webfinger['links']) || ! is_array($webfinger['links']) || empty($webfinger['links'])) {
  77. return [];
  78. }
  79. $link = collect($webfinger['links'])
  80. ->filter(function ($link) {
  81. return $link &&
  82. isset($link['rel'], $link['type'], $link['href']) &&
  83. $link['rel'] === 'self' &&
  84. in_array($link['type'], ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"']);
  85. })
  86. ->pluck('href')
  87. ->first();
  88. $profile = Helpers::profileFetch($link);
  89. if (! $profile) {
  90. return;
  91. }
  92. return $mastodonMode ?
  93. AccountService::getMastodon($profile->id, true) :
  94. AccountService::get($profile->id);
  95. }
  96. }