Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ TELEGRAM_TOKEN_KEY_BASE64=derive-from-local-webhook-secret
# Для ручной проверки настоящего бота раскомментируй и заполни только в локальном .env.
# TELEGRAM_REAL_BOT_TOKEN=
# TELEGRAM_REAL_WEBHOOK_SECRET=
TELEGRAM_WEBHOOK_SET_ATTEMPTS=12
TELEGRAM_WEBHOOK_SET_DELAY_SECONDS=10

AGENT_RUNTIME_PORT=18080
# Опциональный профиль task services:model:up. API key для локальной Ollama не нужен.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ task telegram:real:down
Quick Tunnel предназначен только для ручной локальной проверки. Команда не печатает bot token и
не сохраняет его в Compose-файлах. После живого прогона в тесты переносятся только обезличенные формы
Telegram Update и Bot API response.
Если новый адрес ещё не виден DNS-серверам Telegram, команда ограниченно повторяет `setWebhook`.
Число попыток и задержка задаются через `TELEGRAM_WEBHOOK_SET_ATTEMPTS` и
`TELEGRAM_WEBHOOK_SET_DELAY_SECONDS`.

`TEST_LAB_PATH` по умолчанию указывает на соседний `../portable-agent-test-lab`; путь можно
переопределить в `.env`. Channel Gateway доступен на `http://localhost:18084`, Agent Runtime — на
Expand Down
3 changes: 3 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ bot token для разработки и CI не требуется.
Когда нужно проверить настоящий Telegram, добавь `TELEGRAM_REAL_BOT_TOKEN` и
`TELEGRAM_REAL_WEBHOOK_SECRET` в игнорируемый `.env`, затем выполни `task telegram:real:up`.
Команда поднимет временный HTTPS tunnel, проверит bot token и зарегистрирует защищённый webhook.
Если DNS нового Quick Tunnel распространяется с задержкой, команда ограниченно повторит регистрацию.
Предел и пауза задаются через `TELEGRAM_WEBHOOK_SET_ATTEMPTS` и
`TELEGRAM_WEBHOOK_SET_DELAY_SECONDS`.
После ручного сценария выполни `task telegram:real:down`: внешний webhook будет удалён до возврата
адаптера к fake API.

Expand Down
13 changes: 13 additions & 0 deletions scripts/check-compose.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,24 @@ foreach ($required in @("TELEGRAM_REAL_BOT_TOKEN", "TELEGRAM_REAL_WEBHOOK_SECRET
}
}
$realTelegramScript = Get-Content -Raw -LiteralPath "scripts/start-telegram-real.ps1"
$envExample = Get-Content -Raw -LiteralPath ".env.example"
foreach ($required in @("getMe", "setWebhook", "getWebhookInfo", "trycloudflare", "allowed_updates", "callback_query")) {
if ($realTelegramScript -notmatch [regex]::Escape($required)) {
throw "Запуск настоящего Telegram не содержит $required."
}
}
foreach ($setting in @("TELEGRAM_WEBHOOK_SET_ATTEMPTS", "TELEGRAM_WEBHOOK_SET_DELAY_SECONDS")) {
if ($envExample -notmatch "(?m)^$setting=[1-9][0-9]*\r?$") {
throw "В .env.example нет положительной настройки $setting."
}
if ($realTelegramScript -notmatch [regex]::Escape($setting)) {
throw "Запуск настоящего Telegram не использует $setting."
}
}
if ($realTelegramScript -notmatch 'for \(\$attempt = 1; \$attempt -le \$webhookAttempts' `
-or $realTelegramScript -notmatch 'Start-Sleep -Seconds \$webhookDelaySeconds') {
throw "Настройка Telegram webhook должна повторяться, пока DNS Quick Tunnel распространяется."
}
if ($realTelegramScript -notmatch '\[switch\]\$Model' `
-or $realTelegramScript -notmatch 'compose/model.local.yaml') {
throw "Настоящий Telegram должен поддерживать тот же локальный AI-профиль."
Expand Down
48 changes: 37 additions & 11 deletions scripts/start-telegram-real.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,22 @@ $ErrorActionPreference = "Stop"

$token = Get-LocalSetting "TELEGRAM_REAL_BOT_TOKEN"
$webhookSecret = Get-LocalSetting "TELEGRAM_REAL_WEBHOOK_SECRET"
$webhookAttemptsText = Get-LocalSetting "TELEGRAM_WEBHOOK_SET_ATTEMPTS"
$webhookDelayText = Get-LocalSetting "TELEGRAM_WEBHOOK_SET_DELAY_SECONDS"
if ($token -notmatch '^\d+:[A-Za-z0-9_-]{20,}$') {
throw "Set a valid TELEGRAM_REAL_BOT_TOKEN from BotFather in local .env."
}
if ($webhookSecret -notmatch '^[A-Za-z0-9_-]{32,256}$') {
throw "TELEGRAM_REAL_WEBHOOK_SECRET must contain 32-256 characters: A-Z, a-z, 0-9, _ or -."
}
$webhookAttempts = 0
$webhookDelaySeconds = 0
if (-not [int]::TryParse($webhookAttemptsText, [ref]$webhookAttempts) -or $webhookAttempts -lt 1) {
throw "TELEGRAM_WEBHOOK_SET_ATTEMPTS must be a positive integer."
}
if (-not [int]::TryParse($webhookDelayText, [ref]$webhookDelaySeconds) -or $webhookDelaySeconds -lt 1) {
throw "TELEGRAM_WEBHOOK_SET_DELAY_SECONDS must be a positive integer."
}

$env:TELEGRAM_REAL_BOT_TOKEN = $token
$env:TELEGRAM_REAL_WEBHOOK_SECRET = $webhookSecret
Expand Down Expand Up @@ -56,19 +66,35 @@ $apiUrl = "https://api.telegram.org/bot$token"
try {
$bot = Invoke-RestMethod -Method Post -Uri "$apiUrl/getMe"
if (-not $bot.ok -or -not $bot.result.username) { throw "invalid getMe" }
$hook = Invoke-RestMethod -Method Post -Uri "$apiUrl/setWebhook" -ContentType "application/json" -Body (@{
url = "$tunnelUrl/webhooks/telegram"
secret_token = $webhookSecret
allowed_updates = @("message", "callback_query")
drop_pending_updates = $false
} | ConvertTo-Json)
if (-not $hook.ok) { throw "invalid setWebhook" }
$info = Invoke-RestMethod -Method Post -Uri "$apiUrl/getWebhookInfo"
if (-not $info.ok -or $info.result.url -ne "$tunnelUrl/webhooks/telegram") {
throw "invalid getWebhookInfo"
} catch {
throw "Telegram Bot API rejected the bot token. Secrets were not printed."
}

$webhookBody = @{
url = "$tunnelUrl/webhooks/telegram"
secret_token = $webhookSecret
allowed_updates = @("message", "callback_query")
drop_pending_updates = $false
} | ConvertTo-Json
$hookReady = $false
for ($attempt = 1; $attempt -le $webhookAttempts -and -not $hookReady; $attempt += 1) {
try {
$hook = Invoke-RestMethod -Method Post -Uri "$apiUrl/setWebhook" `
-ContentType "application/json" -Body $webhookBody
$hookReady = [bool]$hook.ok
} catch {
if ($attempt -eq $webhookAttempts) { break }
}
if (-not $hookReady) { Start-Sleep -Seconds $webhookDelaySeconds }
}
if (-not $hookReady) {
throw "Telegram did not accept the temporary webhook after $webhookAttempts attempts. Secrets were not printed."
}
try {
$info = Invoke-RestMethod -Method Post -Uri "$apiUrl/getWebhookInfo"
if (-not $info.ok -or $info.result.url -ne "$tunnelUrl/webhooks/telegram") { throw "invalid webhook" }
} catch {
throw "Telegram Bot API rejected the bot token or temporary webhook. Secrets were not printed."
throw "Telegram did not confirm the temporary webhook. Secrets were not printed."
}

Write-Host "Real Telegram connected: @$($bot.result.username)"
Expand Down
Loading