error('Set MAXMIND_ACCOUNT_ID and MAXMIND_LICENSE_KEY before updating GeoIP data.'); $this->line(''); $this->line('Production uses the shared env file (current/.env is usually a symlink):'); $this->line(' '.$envPath); $this->line(''); $this->line('Add both variables there, then refresh config:'); $this->line(' php artisan config:clear'); $this->line(' php artisan link:geoip-update'); $this->line(' php artisan config:cache'); if ($configCached) { $this->warn('Config is cached — Laravel will ignore new .env values until you run config:clear.'); } return self::FAILURE; } $targetDir = dirname((string) config('link.geoip_database')); File::ensureDirectoryExists($targetDir); $this->info('Downloading GeoLite2-Country database from MaxMind…'); $response = Http::withBasicAuth($accountId, $licenseKey) ->timeout(180) ->withOptions(['allow_redirects' => true]) ->get('https://download.maxmind.com/geoip/databases/GeoLite2-Country/download', [ 'suffix' => 'tar.gz', ]); if ($response->failed()) { $this->error('MaxMind download failed: HTTP '.$response->status()); return self::FAILURE; } $archivePath = $targetDir.'/GeoLite2-Country.tar.gz'; $extractDir = $targetDir.'/extract-'.uniqid('', true); file_put_contents($archivePath, $response->body()); try { File::ensureDirectoryExists($extractDir); $process = new \Symfony\Component\Process\Process([ 'tar', '-xzf', $archivePath, '-C', $extractDir, ]); $process->mustRun(); $finder = Finder::create() ->files() ->name('GeoLite2-Country.mmdb') ->in($extractDir); $database = null; foreach ($finder as $file) { $database = $file->getPathname(); break; } if ($database === null) { $this->error('GeoLite2-Country.mmdb was not found in the downloaded archive.'); return self::FAILURE; } $target = (string) config('link.geoip_database'); File::copy($database, $target); $this->info('GeoIP database updated at '.$target); return self::SUCCESS; } finally { @unlink($archivePath); File::deleteDirectory($extractDir); } } }