addOption('url', 'u', InputOption::VALUE_OPTIONAL, 'Override WEBHOOK_URL from env'); $this->addOption('secret', 's', InputOption::VALUE_OPTIONAL, 'Override MAX_BOT_API_SECRET from env'); $this->addOption('types', 't', InputOption::VALUE_OPTIONAL, 'Comma-separated update types (default: empty = all)'); $this->addOption('prune', null, InputOption::VALUE_NONE, 'Unsubscribe every other webhook before subscribing'); } protected function doExecute(SymfonyStyle $io, InputInterface $input, OutputInterface $output): int { $config = Bootstrap::envConfig(); $url = (string) ($input->getOption('url') ?: $config['webhook.url']); $secret = (string) ($input->getOption('secret') ?: $config['bot.secret']); $typesArg = $input->getOption('types'); $types = $typesArg === null ? [] : array_values(array_filter(explode(',', (string) $typesArg))); if ($url === '' || str_contains($url, 'your-tunnel-host')) { $io->error('WEBHOOK_URL is empty or still default. Run `make logs-tunnel` to read the cloudflared URL and put it in .env.'); return self::FAILURE; } if ($secret === '') { $io->error('MAX_BOT_API_SECRET is empty. Generate one (e.g. `openssl rand -hex 32`) and put in .env.'); return self::FAILURE; } if ($input->getOption('prune')) { $existing = $this->api->subscriptions->getSubscriptions(); foreach ($existing->subscriptions as $s) { if ($s->url !== $url) { $io->text("Pruning stale webhook: $s->url"); $this->api->subscriptions->unsubscribe($s->url); } } } $io->text("Subscribing $url with " . ($types === [] ? 'all update types' : 'types: ' . implode(',', $types))); $result = $this->api->subscriptions->subscribe($url, $types, $secret); if (!$result->success) { $io->error('Subscribe failed: ' . ($result->message ?? 'unknown')); return self::FAILURE; } $io->success('Subscribed. Verifying via getSubscriptions()…'); $subs = $this->api->subscriptions->getSubscriptions(); $rows = []; foreach ($subs->subscriptions as $s) { $rows[] = [$s->url, $s->version ?? '—', implode(',', $s->updateTypes) ?: '(all)']; } $io->table(['url', 'version', 'update_types'], $rows); return self::SUCCESS; } }