基于Aiogram的Telegram Bot:MongoDB余额功能与FSMStorage问题排查
问题:Aiogram使用FSM时出现FSMStorageWarning警告
我正在用Aiogram框架开发Telegram Bot,用MongoDB做数据库,实现用户余额查询与修改功能时遇到问题:用户发送/balance指令后,终端弹出FSMStorageWarning警告。以下是相关代码及报错信息,尝试多种方案未解决,请求协助。
余额功能代码
from aiogram import types from db import collection from loader import dp from states.balance_state import balance from aiogram.dispatcher.filters.state import State, StatesGroup from aiogram.dispatcher import FSMContext import motor.motor_asyncio from aiogram.contrib.fsm_storage.memory import MemoryStorage import asyncio storage=MemoryStorage() @dp.message_handler(text='/balance', state = None) async def change_balance(message: types.Message): await message.answer('Amount') await balance.amount.set() async def check_balance(user_id: int, amount, now_balance): try: amount = int(amount) if now_balance + amount >= 0: await change_balance(user_id, amount) return True elif now_balance + amount < 0: return 'no money' except Exception: return False @dp.message_handler(state=balance.amount) async def change_balance(message: types.Message, state: FSMContext): user_id = message.chat.id answer = message.text await state.update_data(amount=answer) check_balance = await check_balance(user_id=user_id, amount=answer) now_balance = collection.find_one({"_id" : user_id})["money"] new_balance = now_balance + answer collection.update_one({"_id" : user_id}, {"$set" : {"money" : new_balance}}) if check_balance == 'no money': await message.answer('error ') await state.finish elif check_balance: await message.answer('Success') await state.finish else: await message.answer('error') await state.finish
数据库操作代码
collection = cluster.Mafia_users.user async def add_user(user_id, username): date = datetime.now().date() collection.insert_one({ "_id" : user_id, "name" : username, "date" : str(date), "money" : int(1), })
(cluster已连接,出于安全未展示连接代码)
终端报错信息
FSMStorageWarning: You haven’t set any storage yet so no states and no data will be saved. You can connect MemoryStorage for debug purposes or non-essential data. await state.set_state(self.state)
解决方案
核心问题:Storage未绑定到Dispatcher
警告的直接原因是你创建了MemoryStorage实例,但没有将它传入Dispatcher的初始化参数中,导致FSM无法存储用户状态和数据。
步骤1:绑定Storage到Dispatcher
找到你的loader.py文件(你从该文件导入了dp),修改Dispatcher初始化代码,传入storage参数:
# loader.py示例代码 from aiogram import Bot, Dispatcher from aiogram.contrib.fsm_storage.memory import MemoryStorage API_TOKEN = '你的Bot Token' storage = MemoryStorage() bot = Bot(token=API_TOKEN) dp = Dispatcher(bot, storage=storage) # 关键:必须在此处传入storage
修复代码中的其他逻辑错误
除了警告,你的代码还有几个功能性问题需要修正:
- 函数重名:两个函数都命名为
change_balance,会导致函数覆盖,建议重命名第一个函数为prompt_balance_amount - 参数缺失:调用
check_balance时未传入now_balance参数,会触发报错 - 异步操作未加await:MongoDB的motor驱动方法是异步的,调用
find_one和update_one时必须加await - 状态结束未执行:
state.finish缺少括号,应改为await state.finish() - 字符串未转整数:用户输入的金额是字符串,直接和整数余额相加会报错,需先转为整数
修正后的余额功能代码示例:
from aiogram import types from db import collection from loader import dp from states.balance_state import balance from aiogram.dispatcher import FSMContext import asyncio @dp.message_handler(text='/balance', state = None) async def prompt_balance_amount(message: types.Message): await message.answer('请输入金额:') await balance.amount.set() async def check_balance(amount: str, now_balance: int): try: amount_int = int(amount) if now_balance + amount_int >= 0: return True, amount_int else: return 'no money', amount_int except ValueError: return False, 0 @dp.message_handler(state=balance.amount) async def process_balance_change(message: types.Message, state: FSMContext): user_id = message.chat.id answer = message.text # 获取当前用户余额 user_data = await collection.find_one({"_id": user_id}) if not user_data: await message.answer('用户不存在,请先注册') await state.finish() return now_balance = user_data["money"] # 校验金额 check_result, amount_int = await check_balance(amount=answer, now_balance=now_balance) if check_result == 'no money': await message.answer('余额不足,无法完成操作') await state.finish() elif check_result: new_balance = now_balance + amount_int await collection.update_one({"_id": user_id}, {"$set": {"money": new_balance}}) await message.answer(f'操作成功!当前余额:{new_balance}') await state.finish() else: await message.answer('请输入有效的数字金额') await state.finish()
验证
修改完成后重启Bot,发送/balance指令,警告会消失,余额修改功能也能正常运行。
内容的提问来源于stack exchange,提问作者TetSigma
相关产品推荐
相关产品推荐

