async def friends_data(message: Message, user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=message.from_user.id).set_state(States.THROTTLER)
    *_, user = user_data
    message = await message.answer(Config.local.wait.get(user.language))
    texts = ['']
    friends = await UserPeer.get_friends(user_id=user.id)
    friends_count = await UserPeer.get_friends_count(user_id=user.id)
    observables = await UserPeer.get_observables(user_id=user.id)
    for i, friend in enumerate(friends[:10], 1):
        await message.bot.send_chat_action(user.id, 'typing')
        texts[0] = Config.local.friends_list.get(user.language, from_=1, to=i, friends_count=friends_count)
        peer, text = await text_compile.peer_data_compile(user=user, login=friend.login, is_single=False)
        texts.append(text)
        try:
            with suppress(MessageNotModified, MessageToEditNotFound):
                await message.edit_text('\n\n'.join(texts), disable_web_page_preview=True)
        except RetryAfter as e:
            await message.answer(str(e))
            await asyncio.sleep(e.timeout)
    text = '\n\n'.join(texts)
    await Cache().set(key=f'Friends:{user.id}:1', value=texts)
    keyboard = peer_keyboard(peers=friends[:10], friends=friends[:10], observables=observables,
                             payload='' if friends_count < 11 else 'pagination')
    if friends_count > 10:
        keyboard = pagination_keyboard(action='friends_pagination', count=friends_count, content=1,
                                       limit=10, stop=3, keyboard=keyboard)
    with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
        await message.delete()
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    await bot.send_message(user.id, text, reply_markup=keyboard,
                           disable_web_page_preview=not (friends_count == 1 and user.show_avatar))
async def host_data(message: Message, user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=message.from_user.id
                           ).set_state(States.THROTTLER)
    *_, user = user_data
    host = message.text[1:].lower().strip()
    message = await message.answer(Config.local.wait.get(user.language))
    await message.bot.send_chat_action(user.id, 'typing')
    text, peer = await text_compile.host_data_compile(user=user, host=host)
    keyboard = None
    if peer:
        friends = await UserPeer.get_friends(user_id=user.id)
        observables = await UserPeer.get_observables(user_id=user.id)
        keyboard = peer_keyboard(peers=[peer],
                                 friends=friends,
                                 observables=observables,
                                 payload='pagination')
        keyboard = pagination_keyboard(action='host_pagination',
                                       count=1,
                                       content=host,
                                       limit=0,
                                       stop=3,
                                       keyboard=keyboard)
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
        await message.delete()
    await bot.send_message(user.id,
                           text,
                           reply_markup=keyboard,
                           disable_web_page_preview=not user.show_avatar)
async def peer_locations_pagination(callback_query: CallbackQuery,
                                    user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=callback_query.from_user.id
                           ).set_state(States.THROTTLER)
    *_, user = user_data
    action, login, page = callback_query.data.split('.')
    page = int(page)
    await callback_query.answer(text=Config.local.wait.get(user.language))
    text, count, _ = await text_compile.peer_locations_compile(
        user=user,
        login=login,
        page=page,
        message_text=callback_query.message.text)
    back_button_data = (Config.local.back.get(user.language),
                        f'back.peer.{login}')
    keyboard = pagination_keyboard(action=action,
                                   count=count,
                                   content=login,
                                   limit=10,
                                   stop=4,
                                   page=page,
                                   back_button_data=back_button_data)
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    with suppress(MessageNotModified, MessageToEditNotFound):
        await callback_query.message.edit_text(text,
                                               disable_web_page_preview=True,
                                               reply_markup=keyboard)
async def events_pagination(callback_query: CallbackQuery,
                            user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=callback_query.from_user.id
                           ).set_state(States.THROTTLER)
    _, peer, user = user_data
    campus_id, page = map(int, callback_query.data.split('.')[1:])
    await callback_query.answer(text=Config.local.wait.get(user.language))
    text, count, page = await text_compile.events_text_compile(
        user=user, campus_id=campus_id, cursus_id=peer.cursus_id, page=page)
    back_button_data = None
    if not user.use_default_campus:
        back_button_data = (Config.local.back.get(user.language),
                            'back.events')
    keyboard = pagination_keyboard(action='events_pagination',
                                   count=count,
                                   content=campus_id,
                                   limit=1,
                                   stop=9,
                                   page=page,
                                   back_button_data=back_button_data)
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    with suppress(MessageNotModified, MessageToEditNotFound):
        await callback_query.message.edit_text(text,
                                               reply_markup=keyboard,
                                               disable_web_page_preview=True)
async def host_pagination(callback_query: CallbackQuery,
                          user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=callback_query.from_user.id
                           ).set_state(States.THROTTLER)
    *_, user = user_data
    host, page = callback_query.data.split('.')[1:]
    page = int(page)
    await callback_query.answer(text=Config.local.wait.get(user.language))
    text, peer = await text_compile.host_data_compile(user=user,
                                                      host=host,
                                                      page=page)
    keyboard = None
    if peer:
        friends = await UserPeer.get_friends(user_id=user.id)
        observables = await UserPeer.get_observables(user_id=user.id)
        keyboard = peer_keyboard(peers=[peer],
                                 friends=friends,
                                 observables=observables,
                                 payload='pagination')
    keyboard = pagination_keyboard(action='host_pagination',
                                   count=1,
                                   content=host,
                                   limit=0,
                                   stop=3,
                                   page=page,
                                   keyboard=keyboard)
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    with suppress(MessageNotModified, MessageToEditNotFound):
        await callback_query.message.edit_text(
            text,
            reply_markup=keyboard,
            disable_web_page_preview=not user.show_avatar)
async def campus_events(callback_query: CallbackQuery,
                        user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=callback_query.from_user.id
                           ).set_state(States.THROTTLER)
    _, peer, user = user_data
    campus_id = int(callback_query.data.split('.')[2])
    with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
        await callback_query.message.delete()
    message = await bot.send_message(user.id,
                                     Config.local.wait.get(user.language))
    await callback_query.message.bot.send_chat_action(user.id, 'typing')
    text, count, _ = await text_compile.events_text_compile(
        user=user, campus_id=campus_id, cursus_id=peer.cursus_id)
    back_button_data = (Config.local.back.get(user.language), 'back.events')
    keyboard = pagination_keyboard(action='events_pagination',
                                   count=count,
                                   content=campus_id,
                                   limit=1,
                                   stop=9,
                                   back_button_data=back_button_data)
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
        await message.delete()
    await bot.send_message(user.id,
                           text,
                           reply_markup=keyboard,
                           disable_web_page_preview=True)
async def friends_list(callback_query: CallbackQuery,
                       user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=callback_query.from_user.id
                           ).set_state(States.THROTTLER)
    *_, user = user_data
    peer_id, login = callback_query.data.split('.')[1:-1]
    alert_text = Config.local.remove_friend.get(user.language, login=login)
    await callback_query.answer(alert_text, show_alert=True)
    await UserPeer.remove_friend(user_id=user.id, peer_id=int(peer_id))
    friends_count = await UserPeer.get_friends_count(user_id=user.id)
    friends = await UserPeer.get_friends(user_id=user.id)
    observables = await UserPeer.get_observables(user_id=user.id)
    current_page = 1
    raws = [
        button.callback_data
        for row in callback_query.message.reply_markup.inline_keyboard
        for button in row
    ][-1].split('.')
    if friends_count + 1 > 10 and raws[0] == 'friends_pagination':
        current_page = int(raws[1])
    await callback_query.message.bot.send_chat_action(user.id, 'typing')
    text, page = await text_compile.friends_list_normalization(
        user=user,
        current_page=current_page,
        removable=login,
        friends=friends,
        friends_count=friends_count)
    count = len(friends[(page - 1) * 10:])
    friends = paginate(friends, page=page - 1, limit=10)
    payload = ''
    if friends_count > 11:
        payload = 'pagination'
    if friends_count == 1:
        payload = 'alone_peer'
    keyboard = peer_keyboard(peers=friends,
                             friends=friends,
                             observables=observables,
                             payload=payload)
    if friends_count + 1 > 10:
        keyboard = pagination_keyboard(action='friends_pagination',
                                       count=count,
                                       content=current_page,
                                       limit=10,
                                       stop=3,
                                       page=page - 1,
                                       keyboard=keyboard)
    if friends_count == 1:
        keyboard = alone_peer_keyboard(user=user,
                                       login=friends[0].login,
                                       keyboard=keyboard)
    with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
        await callback_query.message.delete()
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    await bot.send_message(
        user.id,
        text,
        reply_markup=keyboard,
        disable_web_page_preview=not (friends_count == 1 and user.show_avatar))
async def free_locations(message: Message, user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=message.from_user.id).set_state(States.THROTTLER)
    _, peer, user = user_data
    if user.use_default_campus:
        message = await message.answer(Config.local.wait.get(user.language))
        await message.bot.send_chat_action(user.id, 'typing')
        text, count, _ = await text_compile.free_locations_compile(user=user, campus_id=peer.campus_id)
        keyboard = pagination_keyboard(action='locations_pagination', count=count,
                                       content=peer.campus_id, limit=40, stop=9)
        with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
            await message.delete()
        await bot.send_message(user.id, text, reply_markup=keyboard)
    else:
        campuses = await Campus.get_campuses()
        keyboard = data_keyboard(data=campuses, action='locations_campuses', content='locations', limit=30)
        await message.answer(Config.local.campus_choose.get(user.language), reply_markup=keyboard)
    await dp.current_state(user=user.id).set_state(States.GRANTED)
async def campus_locations(callback_query: CallbackQuery,
                           user_data: Tuple[Campus, Peer, User]):
    await dp.current_state(user=callback_query.from_user.id
                           ).set_state(States.THROTTLER)
    *_, user = user_data
    campus_id = int(callback_query.data.split('.')[2])
    with suppress(MessageNotModified, MessageToEditNotFound):
        message = await callback_query.message.edit_text(
            Config.local.wait.get(user.language))
    text, count, _ = await text_compile.free_locations_compile(
        user=user, campus_id=campus_id)
    keyboard = pagination_keyboard(action='locations_pagination',
                                   count=count,
                                   content=campus_id,
                                   limit=40,
                                   stop=9)
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
        await message.delete()
    await bot.send_message(user.id, text, reply_markup=keyboard)
async def get_text_and_keyboard(user: User, message: Message, method: Callable,
                                login: str, action: str, limit: int,
                                stop: int) -> Tuple[str, InlineKeyboardMarkup]:
    data = await method(user=user, login=login)
    back_button_data = (Config.local.back.get(user.language),
                        f'back.peer.{login}')
    if len(data) == 2:
        text, is_peer = data
        count = 1
    else:
        text, count, is_peer = data
    keyboard = None
    if is_peer:
        keyboard = pagination_keyboard(action=action,
                                       count=count,
                                       content=login,
                                       limit=limit,
                                       stop=stop,
                                       back_button_data=back_button_data)
    await dp.current_state(user=user.id).set_state(States.GRANTED)
    with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
        await message.delete()
    return text, keyboard