mespace App\Sources; use App\Exceptions\Source\SourceConfigurationException; use App\Libraries\Crawler; use App\Sources\Support\AIPSource; use App\Sources\Support\Data\SourceAirport; use App\Sources\Support\Data\SourceChart; use CobaltGrid\AIRACCalculator\AIRACCycle; use GuzzleHttp\Cookie\CookieJar; use Illuminate\Http\Client\PendingRequest; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Http; class HASPGreece extends AIPSource { public static mixed $automaticScheduleAiracDays = 0; public static $publicBaseUrl = 'https://aisgr.hasp.gov.gr/main.php#publications'; public static $supportedCountriesA2 = ['GR']; protected mixed $airportIndexAirportEntrySelector = 'body ul#browser > li:last-of-type > ul > li:not(:first-child) > ul > li.closed'; protected ?string $airportEntryICAOSelector = 'span.folder'; protected ?string $airportEntryICAORegex = '/LG\w{2}$/'; protected mixed $chartEntrySelector = 'ul > li a'; protected ?array $chartNameRemovals = ['/^AD 2/']; protected ?array $chartNameReplacements = ['-' => ' ']; protected function getCurrentIssueUrls(): string|array { $options = []; $optionResults = []; $currentCycle = AIRACCycle::current(); $currentAiracDate = strtolower($currentCycle->getEffectiveDate()->format('dMY')); $numPreviousCyclesToTry = 12; $flipAirac = function (AIRACCycle $cycle) { $cycleCode = $cycle->getCycleCode(); return $cycleCode[2].$cycleCode[3].$cycleCode[0].$cycleCode[1]; }; for ($i = 0; $i < $numPreviousCyclesToTry; $i++) { $cycle = $currentCycle->fromSerial($currentCycle->getSerial() - $i); $cycleDate = strtolower($cycle->getEffectiveDate()->format('dMY')); $options[] = "https://aisgr.hasp.gov.gr/aipgr_incl_amdt_{$flipAirac($cycle)}_wef_{$currentAiracDate}/cd/ais/index.html"; $options[] = "https://aisgr.hasp.gov.gr/aipgr_incl_amdt_{$flipAirac($cycle)}_wef_{$cycleDate}/cd/ais/index.html"; } $options = array_unique($options); foreach ($options as $option) { $result = $this->getHttpClient()->get($option)->status(); if ($result === 200) { return $option; } $optionResults[] = $result; } $optionsWithResults = []; foreach ($options as $idx => $option) { $result = $optionResults[$idx] ?? null; $optionsWithResults[] = "{$option} => HTTP result: {$result}"; } throw new SourceConfigurationException( "Unable to guess current AIP issue URL from options (with HTTP results): \n".implode(";\n", $optionsWithResults) ); } protected function getAirportIndexUrls(mixed $indexUrl = null): array { return array_map(function ($url) { return str_replace('index.html', 'side.htm', $url); }, Arr::wrap($this->getCurrentIssueUrls())); } protected function getChartEntriesCrawlerForAirport(SourceAirport $sourceAirport): ?Crawler { return $sourceAirport->node; } protected function chartNameRemovalStrings(SourceChart $chartContext): array { return array_merge(parent::chartNameRemovalStrings($chartContext), ["/AD ?2[- ]{$chartContext->airport->icao}-?/"]); } protected function createSourceChart(SourceAirport $airport, string $name, mixed $url = null, ?string $code = null, ?string $uuid = null): SourceChart { $chart = parent::createSourceChart($airport, $name, $url, $code, $uuid); if ($chart->name == '') { $chart->name = 'Textual Data'; } return $chart; } public static function getDisplayName(): string { return 'HASP Greece'; } public function getHttpClient(): PendingRequest { if (! isset($this->clientCookieJar)) { $this->clientCookieJar = new CookieJar; } return Http::retry(3, 100, throw: false) ->connectTimeout(60) ->withOptions([ 'cookies' => $this->clientCookieJar, 'headers' => $this->haspBrowserHeaders(), ]); } /** * @return array */ protected function haspBrowserHeaders(): array { return [ 'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 'accept-encoding' => 'gzip, deflate, br, zstd', 'accept-language' => 'en-GB,en;q=0.9,en-US;q=0.8', 'cache-control' => 'no-cache', 'pragma' => 'no-cache', 'priority' => 'u=0, i', 'sec-ch-ua' => '"Not;A=Brand";v="8", "Chromium";v="150", "Microsoft Edge";v="150"', 'sec-ch-ua-mobile' => '?0', 'sec-ch-ua-platform' => '"Windows"', 'sec-fetch-dest' => 'document', 'sec-fetch-mode' => 'navigate', 'sec-fetch-site' => 'none', 'sec-fetch-user' => '?1', 'upgrade-insecure-requests' => '1', 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36 Edg/150.0.0.0', ]; } }