| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- <?php
- namespace App\Console\Commands;
- /*
- * Artisan-команда: php artisan brands:download-logos
- *
- * Скачивает логотипы марок автомобилей из simple-icons CDN и Wikimedia Commons
- * и сохраняет в storage/app/public/makes/logos/.
- * Обновляет поле logo в dict_values для совпавших марок (раздел code=makes).
- *
- * Повторный запуск безопасен: уже скачанные файлы не перезаписываются.
- * Добавьте --force чтобы принудительно перескачать все логотипы.
- */
- use App\Models\DictSection;
- use App\Models\DictValue;
- use Illuminate\Console\Command;
- use Illuminate\Support\Facades\Http;
- use Illuminate\Support\Facades\Storage;
- use Illuminate\Support\Str;
- class DownloadBrandLogos extends Command
- {
- protected $signature = 'brands:download-logos {--force : Перезаписать существующие файлы}';
- protected $description = 'Скачивает логотипы марок автомобилей из simple-icons CDN и Wikimedia';
- // Карта: название марки → прямой URL для скачивания SVG
- // simple-icons CDN для большинства, Wikimedia для остальных
- private array $logoUrls = [
- 'Toyota' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/toyota.svg',
- 'Nissan' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/nissan.svg',
- 'Mitsubishi' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/mitsubishi.svg',
- 'Honda' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/honda.svg',
- 'Subaru' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/subaru.svg',
- 'Mazda' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/mazda.svg',
- 'Suzuki' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/suzuki.svg',
- 'Lexus' => 'https://upload.wikimedia.org/wikipedia/commons/7/75/Lexus.svg',
- 'Infiniti' => 'https://upload.wikimedia.org/wikipedia/commons/c/c3/Infiniti_logo.svg',
- 'BMW' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/bmw.svg',
- 'Mercedes-Benz' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/mercedes.svg',
- 'Audi' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/audi.svg',
- 'Volkswagen' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/volkswagen.svg',
- 'Porsche' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/porsche.svg',
- 'Land Rover' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/landrover.svg',
- 'Jeep' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/jeep.svg',
- 'Ford' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/ford.svg',
- 'Chevrolet' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/chevrolet.svg',
- 'Kia' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/kia.svg',
- 'Hyundai' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/hyundai.svg',
- 'Volvo' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/volvo.svg',
- 'Skoda' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/skoda.svg',
- 'Renault' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/renault.svg',
- 'Tesla' => 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/tesla.svg',
- 'Chery' => 'https://upload.wikimedia.org/wikipedia/commons/b/b6/Chery_logo.svg',
- 'Geely' => 'https://upload.wikimedia.org/wikipedia/commons/d/d4/Geely_logo.svg',
- ];
- public function handle(): int
- {
- $section = DictSection::where('code', 'makes')->first();
- if (! $section) {
- $this->error('Раздел справочника "makes" не найден.');
- return 1;
- }
- Storage::disk('public')->makeDirectory('makes/logos');
- $makes = DictValue::where('section_id', $section->id)
- ->whereNull('parent_id')
- ->get(['id', 'value', 'logo']);
- $this->info("Найдено {$makes->count()} марок. Начинаю загрузку...");
- $downloaded = 0;
- $skipped = 0;
- foreach ($makes as $make) {
- $url = $this->logoUrls[$make->value] ?? null;
- if (! $url) {
- $this->line(" ⚠ {$make->value}: нет источника в карте логотипов");
- continue;
- }
- $filename = 'makes/logos/'.Str::slug($make->value).'.svg';
- // Пропускаем если файл уже есть и не --force
- if (! $this->option('force') && $make->logo && Storage::disk('public')->exists($make->logo)) {
- $this->line(" ✓ {$make->value}: пропущено (уже есть)");
- $skipped++;
- continue;
- }
- try {
- $response = Http::timeout(15)
- ->withHeaders(['User-Agent' => 'TochaApp/1.0 (logo-downloader; contact@tocha.ru)'])
- ->get($url);
- if (! $response->successful()) {
- $this->warn(" ✗ {$make->value}: HTTP {$response->status()} → {$url}");
- continue;
- }
- Storage::disk('public')->put($filename, $response->body());
- $make->update(['logo' => $filename]);
- $this->info(" ↓ {$make->value}: сохранён → {$filename}");
- $downloaded++;
- } catch (\Throwable $e) {
- $this->warn(" ✗ {$make->value}: {$e->getMessage()}");
- }
- }
- $this->info("Готово: скачано {$downloaded}, пропущено {$skipped}.");
- return 0;
- }
- }
|