fix(formatter+telegram): drop tel: inline button, mark all 4xx as permanent
Pilot on washanyanya.ru exposed that Telegram Bot API rejects tel: URLs in inline_keyboard with HTTP 400 "Wrong port number specified in the URL". Queue was stuck on 5 items retrying the same failure 4 times each. - MessageFormatter: always returns reply_markup = null. The phone number is already rendered in the '📱 ...' line, and mobile Telegram clients linkify it automatically. - TelegramClient::is_permanent: treat all 4xx except 429 as permanent client-side errors, so future payload-shape bugs surface in the dashboard widget immediately instead of burning five retry cycles. - MessageFormatterTest updated: the old test asserting tel: in reply_markup is replaced with one asserting reply_markup is null and the phone still appears in the text body. - Spec §9 + §19 updated, §19's open question closed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,8 +42,12 @@ final class MessageFormatterTest extends TestCase
|
||||
self::assertStringContainsString('Akismet', $result['text']);
|
||||
}
|
||||
|
||||
public function test_tel_button_present_when_phone_valid(): void
|
||||
public function test_reply_markup_is_null_because_tg_rejects_tel_urls(): void
|
||||
{
|
||||
// Telegram Bot API rejects tel: URLs in inline_keyboard with
|
||||
// HTTP 400 "Wrong port number specified in the URL". We no longer
|
||||
// emit any inline button; the phone number is rendered in the
|
||||
// message body instead and mobile TG clients auto-linkify it.
|
||||
$fields = ['your-tel' => '+79031234567', 'your-name' => 'Анна'];
|
||||
$classification = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||||
$r = MessageFormatter::build([
|
||||
@@ -53,9 +57,9 @@ final class MessageFormatterTest extends TestCase
|
||||
'ip' => '', 'user_agent' => '', 'is_retro' => false,
|
||||
]);
|
||||
|
||||
self::assertNotNull($r['reply_markup']);
|
||||
$json = json_encode($r['reply_markup']);
|
||||
self::assertStringContainsString('tel:+79031234567', $json);
|
||||
self::assertNull($r['reply_markup']);
|
||||
// Phone must still be present in the text, formatted as Russian pretty.
|
||||
self::assertStringContainsString('+7 (903) 123-45-67', $r['text']);
|
||||
}
|
||||
|
||||
public function test_no_tel_button_when_no_phone(): void
|
||||
|
||||
Reference in New Issue
Block a user