| 234 | } |
| 235 | |
| 236 | async stop(): Promise<void> { |
| 237 | // Tear down the webhook server + registration before stopping the bot, so a |
| 238 | // stop/restart cleanly rebinds the socket instead of leaking it. |
| 239 | // Order: deleteWebhook first (so Telegram stops sending), then close the |
| 240 | // local HTTP server (no more refused-socket errors on in-flight POSTs), then |
| 241 | // stop the bot. The old reverse order (close server → deleteWebhook) left a |
| 242 | // window where Telegram kept POSTing to an already-closed socket. |
| 243 | if (this.webhookServer) { |
| 244 | const server = this.webhookServer; |
| 245 | this.webhookServer = undefined; |
| 246 | await this.bot.api |
| 247 | .deleteWebhook() |
| 248 | .catch((e) => console.error("[telegram] deleteWebhook failed:", e)); |
| 249 | await new Promise<void>((resolve) => server.close(() => resolve())); |
| 250 | } |
| 251 | await this.bot.stop(); |
| 252 | } |
| 253 | |
| 254 | render(ir: BotNode[]): TelegramPayload { |
| 255 | return renderTelegram(ir); |