url */ protected $apps = [ 'Slots Magnet Revolution' => 'https://apps.apple.com/us/app/slots-magnet-revolution/id6759797102', 'Viking Mysteric Slots' => 'https://apps.apple.com/us/app/viking-mysteric-slots/id6759851510', 'Slots Chemistry Pirate' => 'https://apps.apple.com/us/app/slots-chemistry-pirate/id6759852588', ]; /** 页面内容中表示“已下架”的关键词(不区分大小写) */ protected $delistedKeywords = [ 'no longer available', 'removed this app from the app store', 'not available', 'this app is no longer', 'has been removed', ]; public function handle() { $env = env('APP_ENV', 'local'); $delisted = []; foreach ($this->apps as $name => $url) { $result = $this->checkApp($url); if ($result['delisted']) { $delisted[] = [ 'name' => $name, 'url' => $url, 'reason' => $result['reason'], ]; Util::WriteLog('ios_app_store_check', "Delisted: {$name} | {$url} | {$result['reason']}"); } } if (count($delisted) > 0) { $this->notifyDelisted($env, $delisted); $this->warn('已检测到 ' . count($delisted) . ' 个包被下架,已发送 Telegram 通知。'); return 1; } $this->info('所有 iOS 包状态正常。'); return 0; } /** * 检测单个 App 是否可访问(未下架) * @return array ['delisted' => bool, 'reason' => string] */ protected function checkApp($url) { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_TIMEOUT => 15, CURLOPT_USERAGENT => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', CURLOPT_SSL_VERIFYPEER => true, ]); $body = curl_exec($ch); $code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($error) { return ['delisted' => true, 'reason' => "请求失败: {$error}"]; } if ($code === 404) { return ['delisted' => true, 'reason' => 'HTTP 404']; } if ($code !== 200) { return ['delisted' => true, 'reason' => "HTTP {$code}"]; } $bodyLower = mb_strtolower($body); foreach ($this->delistedKeywords as $keyword) { if (strpos($bodyLower, $keyword) !== false) { return ['delisted' => true, 'reason' => "页面包含下架提示: {$keyword}"]; } } return ['delisted' => false, 'reason' => '']; } protected function notifyDelisted($env, array $delisted) { $lines = ["[{$env}] iOS App Store 下架检测告警"]; foreach ($delisted as $item) { $lines[] = "• {$item['name']}"; $lines[] = " 原因: {$item['reason']}"; $lines[] = " 链接: {$item['url']}"; } $message = implode("\n", $lines); try { TelegramBot::getDefault()->sendMsg($message); } catch (\Exception $e) { Util::WriteLog('ios_app_store_check', 'Telegram send error: ' . $e->getMessage()); $this->error('Telegram 发送失败: ' . $e->getMessage()); } } }