68 lines
3.0 KiB
PHP
68 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Filament;
|
|
use App\Models\FilamentPrice;
|
|
use App\Models\User;
|
|
use Illuminate\Console\Attributes\Description;
|
|
use Illuminate\Console\Attributes\Signature;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Throwable;
|
|
|
|
#[Signature('filaments:refresh')]
|
|
#[Description('Collect current Amazon prices for tracked filament')]
|
|
class RefreshFilamentPrices extends Command
|
|
{
|
|
public function handle(): int
|
|
{
|
|
$drops = [];
|
|
foreach (Filament::cursor() as $filament) {
|
|
$host = strtolower((string) parse_url($filament->amazonUrl, PHP_URL_HOST));
|
|
if (! in_array($host, ['amazon.co.uk', 'www.amazon.co.uk', 'amazon.com', 'www.amazon.com'], true)) {
|
|
$this->warn($filament->filamentName.': unsupported product host');
|
|
|
|
continue;
|
|
}
|
|
try {
|
|
$html = Http::timeout(15)->withHeaders(['User-Agent' => 'Mozilla/5.0 HickLab3D/1.0'])
|
|
->get($filament->amazonUrl)->throw()->body();
|
|
if (! preg_match('/class="[^"]*a-price-whole[^"]*"[^>]*>([0-9,.]+)/', $html, $whole)
|
|
|| ! preg_match('/class="[^"]*a-price-fraction[^"]*"[^>]*>([0-9]{2})/', $html, $fraction)) {
|
|
$this->warn($filament->filamentName.': price unavailable');
|
|
|
|
continue;
|
|
}
|
|
$price = (float) (str_replace(',', '', $whole[1]).'.'.$fraction[1]);
|
|
if ($price <= 0) {
|
|
continue;
|
|
}
|
|
preg_match('/class="[^"]*savingsPercentage[^"]*"[^>]*>[^0-9]*([0-9]+)%/', $html, $discount);
|
|
$previous = FilamentPrice::where('filamentId', $filament->id)->orderByDesc('recordedAt')->orderByDesc('id')->first();
|
|
FilamentPrice::create([
|
|
'filamentId' => $filament->id,
|
|
'price' => $price,
|
|
'currentDiscount' => ['discount' => ['value' => (int) ($discount[1] ?? 0), 'type' => 'percentage'], 'voucher' => ['value' => 0, 'type' => 'none']],
|
|
]);
|
|
if ($previous && $price < (float) $previous->price) {
|
|
$drops[] = $filament->filamentName.': £'.number_format((float) $previous->price, 2).' → £'.number_format($price, 2).' ('.$filament->amazonUrl.')';
|
|
}
|
|
$this->line($filament->filamentName.': £'.number_format($price, 2));
|
|
} catch (Throwable $exception) {
|
|
report($exception);
|
|
$this->warn($filament->filamentName.': collection failed');
|
|
}
|
|
}
|
|
if ($drops) {
|
|
$body = "HickLab3D filament price drops\n\n".implode("\n", $drops);
|
|
foreach (User::where('alertEmails', true)->where('disabled', false)->pluck('email') as $email) {
|
|
Mail::raw($body, fn ($message) => $message->to($email)->subject('HickLab3D filament price drops'));
|
|
}
|
|
}
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
}
|