forked from mirror/pixelfed
145 lines
3.8 KiB
PHP
145 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs\StoryPipeline;
|
|
|
|
use Cache, Log;
|
|
use App\Story;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
use Illuminate\Queue\InteractsWithQueue;
|
|
use Illuminate\Queue\SerializesModels;
|
|
use App\Util\ActivityPub\Helpers;
|
|
use App\Services\FollowerService;
|
|
use App\Util\Lexer\Bearcap;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Http\Client\RequestException;
|
|
use Illuminate\Http\Client\ConnectionException;
|
|
use App\Util\ActivityPub\Validator\StoryValidator;
|
|
use App\Services\StoryService;
|
|
use App\Services\MediaPathService;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Http\File;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class StoryFetch implements ShouldQueue
|
|
{
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
protected $activity;
|
|
|
|
/**
|
|
* Create a new job instance.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function __construct($activity)
|
|
{
|
|
$this->activity = $activity;
|
|
}
|
|
|
|
/**
|
|
* Execute the job.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function handle()
|
|
{
|
|
$activity = $this->activity;
|
|
$activityId = $activity['id'];
|
|
$activityActor = $activity['actor'];
|
|
|
|
if(parse_url($activityId, PHP_URL_HOST) !== parse_url($activityActor, PHP_URL_HOST)) {
|
|
return;
|
|
}
|
|
|
|
$bearcap = Bearcap::decode($activity['object']['object']);
|
|
|
|
if(!$bearcap) {
|
|
return;
|
|
}
|
|
|
|
$url = $bearcap['url'];
|
|
$token = $bearcap['token'];
|
|
|
|
if(parse_url($activityId, PHP_URL_HOST) !== parse_url($url, PHP_URL_HOST)) {
|
|
return;
|
|
}
|
|
|
|
$version = config('pixelfed.version');
|
|
$appUrl = config('app.url');
|
|
$headers = [
|
|
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
|
'Authorization' => 'Bearer ' . $token,
|
|
'User-Agent' => "(Pixelfed/{$version}; +{$appUrl})",
|
|
];
|
|
|
|
try {
|
|
$res = Http::withHeaders($headers)
|
|
->timeout(30)
|
|
->get($url);
|
|
} catch (RequestException $e) {
|
|
return false;
|
|
} catch (ConnectionException $e) {
|
|
return false;
|
|
} catch (\Exception $e) {
|
|
return false;
|
|
}
|
|
|
|
$payload = $res->json();
|
|
|
|
if(StoryValidator::validate($payload) == false) {
|
|
return;
|
|
}
|
|
|
|
if(Helpers::validateUrl($payload['attachment']['url']) == false) {
|
|
return;
|
|
}
|
|
|
|
$type = $payload['attachment']['type'] == 'Image' ? 'photo' : 'video';
|
|
|
|
$profile = Helpers::profileFetch($payload['attributedTo']);
|
|
|
|
$ext = pathinfo($payload['attachment']['url'], PATHINFO_EXTENSION);
|
|
$storagePath = MediaPathService::story($profile);
|
|
$fileName = Str::random(random_int(2, 12)) . '_' . Str::random(random_int(32, 35)) . '_' . Str::random(random_int(1, 14)) . '.' . $ext;
|
|
$contextOptions = [
|
|
'ssl' => [
|
|
'verify_peer' => false,
|
|
'verify_peername' => false
|
|
]
|
|
];
|
|
$ctx = stream_context_create($contextOptions);
|
|
$data = file_get_contents($payload['attachment']['url'], false, $ctx);
|
|
$tmpBase = storage_path('app/remcache/');
|
|
$tmpPath = $profile->id . '-' . $fileName;
|
|
$tmpName = $tmpBase . $tmpPath;
|
|
file_put_contents($tmpName, $data);
|
|
$disk = Storage::disk(config('filesystems.default'));
|
|
$path = $disk->putFileAs($storagePath, new File($tmpName), $fileName, 'public');
|
|
$size = filesize($tmpName);
|
|
unlink($tmpName);
|
|
|
|
$story = new Story;
|
|
$story->profile_id = $profile->id;
|
|
$story->object_id = $payload['id'];
|
|
$story->size = $size;
|
|
$story->mime = $payload['attachment']['mediaType'];
|
|
$story->duration = $payload['duration'];
|
|
$story->media_url = $payload['attachment']['url'];
|
|
$story->type = $type;
|
|
$story->public = false;
|
|
$story->local = false;
|
|
$story->active = true;
|
|
$story->path = $path;
|
|
$story->view_count = 0;
|
|
$story->can_reply = $payload['can_reply'];
|
|
$story->can_react = $payload['can_react'];
|
|
$story->created_at = now()->parse($payload['published']);
|
|
$story->expires_at = now()->parse($payload['expiresAt']);
|
|
$story->save();
|
|
|
|
StoryService::delLatest($story->profile_id);
|
|
}
|
|
}
|