Ver Fonte

Add command

Daniel Supernault há 2 anos atrás
pai
commit
896e6023bd
1 ficheiros alterados com 149 adições e 0 exclusões
  1. 149 0
      app/Console/Commands/SendUpdateActor.php

+ 149 - 0
app/Console/Commands/SendUpdateActor.php

@@ -0,0 +1,149 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use App\Profile;
+use App\User;
+use App\Instance;
+use App\Util\ActivityPub\Helpers;
+
+class SendUpdateActor extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'ap:update-actors {--force}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Send Update Actor activities to known remote servers to force updates';
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $totalUserCount = Profile::whereNotNull('user_id')->count();
+        $totalInstanceCount = Instance::count();
+        $this->info('Found ' . $totalUserCount . ' local accounts and ' . $totalInstanceCount . ' remote instances');
+
+        $task = $this->choice(
+            'What do you want to do?',
+            [
+                'View top instances',
+                'Send updates to an instance'
+            ],
+            0
+        );
+
+        if($task === 'View top instances') {
+            $this->table(
+                ['domain', 'user_count', 'last_synced'],
+                Instance::orderByDesc('user_count')->take(20)->get(['domain', 'user_count', 'actors_last_synced_at'])->toArray()
+            );
+            return Command::SUCCESS;
+        } else {
+            $domain = $this->anticipate('Enter the instance domain', function ($input) {
+                return Instance::where('domain', 'like', '%' . $input . '%')->pluck('domain')->toArray();
+            });
+            if(!$this->confirm('Are you sure you want to send actor updates to ' . $domain . '?')) {
+                return;
+            }
+            if($cur = Instance::whereDomain($domain)->whereNotNull('actors_last_synced_at')->first()) {
+                if(!$this->option('force')) {
+                    $this->error('ERROR: Cannot re-sync this instance, it was already synced on ' . $cur->actors_last_synced_at);
+                    return;
+                }
+            }
+            $this->line(' ');
+            $this->error('Keep this window open during this process or it will not complete!');
+            $sharedInbox = Profile::whereDomain($domain)->whereNotNull('sharedInbox')->first();
+            if(!$sharedInbox) {
+                $this->error('ERROR: Cannot find the sharedInbox of ' . $domain);
+                return;
+            }
+            $url = $sharedInbox->sharedInbox;
+            $this->line(' ');
+            $this->info('Found sharedInbox: ' . $url);
+            $bar = $this->output->createProgressBar($totalUserCount);
+            $bar->start();
+            User::chunk(50, function($users) use($bar, $url) {
+                foreach($users as $user) {
+                    $profile = Profile::find($user->profile_id);
+                    if(!$profile) {
+                        continue;
+                    }
+                    $body = $this->updateObject($profile);
+                    Helpers::sendSignedObject($profile, $url, $body);
+                    usleep(500);
+                    $bar->advance();
+                }
+            });
+            $bar->finish();
+            $this->line(' ');
+            $instance = Instance::whereDomain($domain)->firstOrFail();
+            $instance->actors_last_synced_at = now();
+            $instance->save();
+            $this->info('Finished!');
+            return Command::SUCCESS;
+        }
+
+        return Command::SUCCESS;
+    }
+
+    protected function updateObject($profile)
+    {
+        return [
+            '@context' => [
+                'https://w3id.org/security/v1',
+                'https://www.w3.org/ns/activitystreams',
+                [
+                    'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
+                ],
+            ],
+            'id' => $profile->permalink('#updates/' . time()),
+            'actor' => $profile->permalink(),
+            'type' => 'Update',
+            'object' => $this->actorObject($profile)
+        ];
+    }
+
+    protected function actorObject($profile)
+    {
+        $permalink = $profile->permalink();
+        return [
+            'id'                        => $permalink,
+            'type'                      => 'Person',
+            'following'                 => $permalink . '/following',
+            'followers'                 => $permalink . '/followers',
+            'inbox'                     => $permalink . '/inbox',
+            'outbox'                    => $permalink . '/outbox',
+            'preferredUsername'         => $profile->username,
+            'name'                      => $profile->name,
+            'summary'                   => $profile->bio,
+            'url'                       => $profile->url(),
+            'manuallyApprovesFollowers' => (bool) $profile->is_private,
+            'publicKey' => [
+                'id'           => $permalink . '#main-key',
+                'owner'        => $permalink,
+                'publicKeyPem' => $profile->public_key,
+            ],
+            'icon' => [
+                'type'      => 'Image',
+                'mediaType' => 'image/jpeg',
+                'url'       => $profile->avatarUrl(),
+            ],
+            'endpoints' => [
+                'sharedInbox' => config('app.url') . '/f/inbox'
+            ]
+        ];
+    }
+}