我在本地使用ngrok隧道在webhook上启动了一个aigram bot,但是bot返回的不是正确的响应,而是200 OK
,响应正文中几乎没有任何内容,因此用户在聊天中看不到任何内容。
Bot的main.py
驱动程序如下所示:
from aiogram import executor
from loader import dp, bot, cache
from handlers import register_start_handlers, register_main_handlers
from settings import Settings, get_settings
config: Settings = get_settings()
async def on_startup(dispatcher):
await bot.set_webhook(config.webhook.address)
register_start_handlers(dp)
register_main_handlers(dp)
async def on_shutdown(dispatcher):
await bot.delete_webhook()
await dispatcher.storage.close()
await dispatcher.storage.wait_closed()
await cache.close()
await cache.wait_closed()
if __name__ == "__main__":
setup_logging()
executor.start_webhook(
dispatcher=dp,
webhook_path=config.webhook.WEBHOOK_PATH,
on_startup=on_startup,
on_shutdown=on_shutdown,
skip_updates=True,
host=config.webhook.BOT_WEBAPP_HOST,
port=config.webhook.BOT_WEBAPP_PORT,
)
handlers
模块中的消息处理程序是通过如下函数注册的:
from aiogram import Dispatcher
from aiogram.types import Message
from aiogram.dispatcher.webhook import SendMessage
async def begin_interaction(message: Message):
return SendMessage(message.from_user.id, "Message text")
def register_start_handlers(dp: Dispatcher):
dp.register_message_handler(begin_interaction, commands=["start"])
这些设置来自项目根目录中的.env文件,检索方式如下:
from pydantic import validator, BaseSettings
BASE_DIR = pathlib.Path(__file__).parent
class EnvSettings(BaseSettings):
class Config(BaseSettings.Config):
env_file = "../.env"
...
class WebhookSettings(EnvSettings):
WEBHOOK_HOST: str
WEBHOOK_PATH: str
BOT_WEBAPP_HOST: str
BOT_WEBAPP_PORT: int
@property
def address(self) -> str:
return f"{self.WEBHOOK_HOST}{self.WEBHOOK_PATH}"
class Settings:
...
webhook: WebhookSettings = WebhookSettings()
bot连接到几个微服务,所有这些微服务都是使用docker-compose启动的,因此环境变量看起来像这样:
WEBHOOK_HOST='https://some.subdomain.ngrok.io'
WEBHOOK_PATH='/'
BOT_WEBAPP_HOST=0.0.0.0
BOT_WEBAPP_PORT=3001
我不得不使用0.0.0.0
(或工作方式相同的Docker网络本地IP)作为HOST,因为official docs推荐的localhost
导致应用程序失败,并出现以下错误:OSError: [Errno 99] error while attempting to bind on address ('::1', 3001, 0, 0): cannot assign requested address
我认为这并不重要,因为示例应用程序(同样,像official one)在localhost
和0.0.0.0
(也使用相同的ngrok设置)上都能很好地工作。
现在,问题来了。使用上面的设置,应用程序正常启动,但是对来自Telegram的POST请求没有返回预期的响应(用ngrok的inspect页面检查了这一点).相反,它只返回200 OK
给任何在主体中只有ok
的请求,并且没有Telegram可以转换为消息来响应的数据.简单的实验表明消息处理程序是注册的,但不叫,这很奇怪:同样的机器人结构在更简单的测试机器人上工作得很好。2而且这个项目本身在使用长轮询时也工作得很好,所以整体结构看起来或多或少是功能性的。
我尝试编写一个最小的可重现示例来复制错误,但没有成功(我设计的所有简单程序都能很好地在此设置下工作),所以我只是希望能对问题所在进行一些推测。我一直在尝试更改.env中的IP地址和端口,但这从来没有工作过。在Docker中启动也不是问题,因为当我试图在容器外部启动时,会在Docker-compose文件中暴露必要的端口,一切都差不多。
1条答案
按热度按时间atmip9wb1#
事实证明,问题出在机器人的结构上。我使用了aiogram的内置FSM工具,它为与特定用户的对话分配一个状态值,并允许您根据该值过滤消息:
看起来,在测试过程中,我关闭了一次Docker容器,但是它们保留了bot的状态数据,并且在我下一次启动bot服务时,与该状态关联的消息处理程序捕获了所有消息,但没有返回任何内容,因为它们没有处理程序所期望的数据。
所以,这基本上是我的错,但这是一个坚韧捕捉的错误。如果你遇到了像我这样的情况,尝试取消你的状态(比如使用
/cancel
命令)或清除持久化的bot数据,这可能会有所帮助