Search code examples
pythonsqlalchemyaiogram

TelegramBot authorization


I am creating TelegramBot using aiogram and SQLAlchemy to interact with database. I want to start with authorization. All users' phone numbers are stored in SQLite database. When the user runs Bot, it should ask the user to enter phone number. After the user has done it, Bot checks whether this number exists in the database. If so, the user can proceed. If not, Bot should deny access. Could you explain how to implement it in code?


Solution

  • You can add column logged and create /login phone to set it True and /logout to set it False. And then other commands would have to check if logged is True or False

    You could also make it like on web pages and keep time when user was logged and block access when left 5 minutes. if left less then 5 minutes then command could update it to current time.

    from aiogram import Bot, Dispatcher, executor, types
    import os
    import datetime
    
    database = {
        1079414868: {'phone': '1234', 'logged': datetime.datetime(1970, 1, 1)}
    }
    
    # --- functions ---
    
    five_minutes = datetime.timedelta(minutes=1)
    
    def do_login(message):
        user = message.from_user.id
        print('[do_login] user:', user)
        
        if user not in database:
            return False
            
        user_data = database[user]
    
        current_time = datetime.datetime.now()
    
        #phone = message.get_args()
        args = message.get_args().split(' ')
        phone = args[0]
        
        print('[do_login] phone:', phone)
    
        # check new phone
        if phone and user_data['phone'] == phone:
            user_data['logged'] = current_time
            return True
        
        return False
    
    def do_logout(message):
        user = message.from_user.id
        
        if user not in database:
            return True
            
        user_data = database[user]
        user_data['logged'] = datetime.datetime(1970, 1, 1)
    
        return True
        
    def check_login(message, check_phone=False):
    
        user = message.from_user.id
        
        if user not in database:
            return False
            
        user_data = database[user]
    
        current_time = datetime.datetime.now()
    
        # check current session    
        if current_time - user_data['logged'] < five_minutes:
            user_data['logged'] = current_time
            return True
            
        return False
        
    # --- init ---
    
    TOKEN = os.getenv('TELEGRAM_TOKEN')
    
    bot = Bot(token=TOKEN)
    dp = Dispatcher(bot)
    
    # --- commands ---
        
    @dp.message_handler(commands=['login'])
    async def login(message: types.Message):
        if do_login(message):
            await message.answer("Login: OK")
        else:
            await message.answer("Login: Problem")
    
    @dp.message_handler(commands=['logout'])
    async def logout(message: types.Message):
        if do_logout(message):
            await message.answer("Logout: OK")
        else:
            await message.answer("Logout: Problem")
    
    @dp.message_handler(commands=['test'])
    async def test(message: types.Message):
    
        if not check_login(message):
            await message.answer('You have to use "/login phone"')
            return
        
        await message.answer("I'm a bot, please talk to me!")
    
    # --- start ---
    
    if __name__ == '__main__':
        print('Running ...')
        executor.start_polling(dp, skip_updates=True)
    

    BTW: Maybe you could even create decorator @check_login to make it simpler to assign to commands. Or you should use some event to test login automatically for every command (except /login).