RemoteFollowPipeline.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. namespace App\Jobs\RemoteFollowPipeline;
  3. use App\Jobs\AvatarPipeline\CreateAvatar;
  4. use App\{Profile};
  5. use GuzzleHttp\Client;
  6. use HttpSignatures\Context;
  7. use HttpSignatures\GuzzleHttpSignatures;
  8. use Illuminate\Bus\Queueable;
  9. use Illuminate\Contracts\Queue\ShouldQueue;
  10. use Illuminate\Foundation\Bus\Dispatchable;
  11. use Illuminate\Queue\InteractsWithQueue;
  12. use Illuminate\Queue\SerializesModels;
  13. use Zttp\Zttp;
  14. class RemoteFollowPipeline implements ShouldQueue
  15. {
  16. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  17. protected $url;
  18. protected $follower;
  19. protected $response;
  20. /**
  21. * Create a new job instance.
  22. *
  23. * @return void
  24. */
  25. public function __construct($follower, $url)
  26. {
  27. $this->follower = $follower;
  28. $this->url = $url;
  29. }
  30. /**
  31. * Execute the job.
  32. *
  33. * @return void
  34. */
  35. public function handle()
  36. {
  37. $follower = $this->follower;
  38. $url = $this->url;
  39. if (Profile::whereRemoteUrl($url)->count() !== 0) {
  40. return true;
  41. }
  42. $this->discover($url);
  43. return true;
  44. }
  45. public function discover($url)
  46. {
  47. $context = new Context([
  48. 'keys' => ['examplekey' => 'secret-key-here'],
  49. 'algorithm' => 'hmac-sha256',
  50. 'headers' => ['(request-target)', 'date'],
  51. ]);
  52. $handlerStack = GuzzleHttpSignatures::defaultHandlerFromContext($context);
  53. $client = new Client(['handler' => $handlerStack]);
  54. $response = Zttp::withHeaders([
  55. 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
  56. 'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org',
  57. ])->get($url);
  58. $this->response = $response->json();
  59. $this->storeProfile();
  60. }
  61. public function storeProfile()
  62. {
  63. $res = $this->response;
  64. $domain = parse_url($res['url'], PHP_URL_HOST);
  65. $username = $res['preferredUsername'];
  66. $remoteUsername = "@{$username}@{$domain}";
  67. $profile = new Profile();
  68. $profile->user_id = null;
  69. $profile->domain = $domain;
  70. $profile->username = $remoteUsername;
  71. $profile->name = $res['name'];
  72. $profile->bio = Purify::clean($res['summary']);
  73. $profile->sharedInbox = $res['endpoints']['sharedInbox'];
  74. $profile->remote_url = $res['url'];
  75. $profile->save();
  76. RemoteFollowImportRecent::dispatch($this->response, $profile);
  77. CreateAvatar::dispatch($profile);
  78. }
  79. public function sendActivity()
  80. {
  81. $res = $this->response;
  82. $url = $res['inbox'];
  83. $activity = Zttp::withHeaders(['Content-Type' => 'application/activity+json'])->post($url, [
  84. 'type' => 'Follow',
  85. 'object' => $this->follower->url(),
  86. ]);
  87. }
  88. }