Reputation: 121
I'm writing a bot in python and aiogram. The point is that the administrator accepts (or rejects) user requests. Accordingly, when the administrator clicks on the button in his chat, I need to change the user's state (his uid is known). I didn't find how to do it anywhere.
I'm looking for something like
dp.set_state(uid, User.accepted))
Thanks!
Upvotes: 3
Views: 8429
Reputation: 39
For new Aiogram 3.1.0
As Aiogram 3.1.0 has slightly different methods of accessing storage and context, I would like to share what I came up with:
from aiogram.fsm.storage.base import StorageKey
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.context import FSMContext
class UserState(StatesGroup):
# any other states
EXPIRED = State()
bot = Bot("your_token", parse_mode=ParseMode.HTML)
storage = MemoryStorage() # for clarity it is created explicitly
dp = Dispatcher(storage=storage)
# here goes the desired userId and chatId (they are same in private chat)
new_user_storage_key = StorageKey(bot.id, user_id, user_id)
new_user_context = FSMContext(storage=storage, key=new_user_storage_key)
await new_user_context.set_state(UserState.EXPIRED) # your specified state
User's own storage (MemoryRecord) is now accessed by StorageKey instead of just user_id, that's why it is necessary to create it first, after that fill it with values (IDs) and then pass it to the FSMcontext. After the context is created, calling set_state(...) and set_data(...) will set state/data specifically for the desired user_id.
Actually there is no need to create a storage explicitly as shown in the previous code snippet, as it will be created automatically, so you can just access it by dispatcher.storage property like here:
# the same imports
# the same UserState class
bot = Bot("your_token", parse_mode=ParseMode.HTML)
dp = Dispatcher() # we don't create storage manually this time
# here goes the desired userId and chatId (they are same in private chat)
new_user_storage_key = StorageKey(bot.id, user_id, user_id)
new_user_context = FSMContext(storage=dp.storage, key=new_user_storage_key)
await new_user_context.set_state(UserState.EXPIRED) # your specified state
Hope it helps! :)
Upvotes: 3
Reputation: 1
state = dp.current_state(chat=chat_id, user=user_id)
await state.set_state(User.accepted)
dp
- an object of the Dispatcher class
chat_id
- chat id, which must be equal to the user id if this is a correspondence with a user
User.accepted
- the state we want to bring the user to
Upvotes: 0
Reputation: 143
from aiogram.dispatcher import FSMContext
@dp.message_handler(state='*')
async def example_handler(message: types.Message, state: FSMContext):
new_state = FSMContext(storage, chat_id, user_id)
then set_state()
and set_data()
on the new_state
.
storage
is the FSM storage.
Upvotes: 3
Reputation: 21
I had the same problem
Found method set() in base class State:
class State:
...
async def set(self):
state = Dispatcher.get_current().current_state()
await state.set_state(self.state)
So I created new class from State and overrode method this way:
async def set(self, user=None):
"""Option to set state for concrete user"""
state = Dispatcher.get_current().current_state(user=user)
await state.set_state(self.state)
Usage:
@dp.message_handler(state='*')
async def example_handler(message: Message):
await SomeStateGroup.SomeState.set(user=message.from_user.id)
If you want some mailing stuff, collect user ids and use that hint.
Upvotes: 2