warn('No output file found — nothing to upsert.'); return; } $mediaCacher = app(StoryMediaCacher::class); $items = json_decode(file_get_contents($path), true); foreach ($items as $item) { $attributes = [ 'user_id' => $item['user_id'], 'username' => $item['username'], 'profile_pic_url' => $item['profile_pic_url'], 'code' => $item['code'], 'is_video' => $item['is_video'], 'taken_at' => $item['taken_at'], 'expiring_at' => $item['expiring_at'], 'image_url' => $item['image_url'], 'video_url' => $item['video_url'], 'accessibility_caption' => $item['accessibility_caption'], 'muted' => $item['muted'], ]; $existing = Story::find($item['id']); // Once a story's media has been cached locally, its url columns // no longer point at Instagram — don't let a re-scrape clobber // them with a freshly (and just as temporarily) signed CDN url. if ($existing) { if (! $mediaCacher->isInstagramUrl($existing->image_url)) { unset($attributes['image_url']); } if (! $mediaCacher->isInstagramUrl($existing->video_url)) { unset($attributes['video_url']); } } Story::updateOrCreate(['id' => $item['id']], $attributes); } $this->info('Upserted ' . count($items) . ' story items.'); } }