Assistant: 
User: User: @router.callback_query(F.data == 'subscribe_select_period')
async def subscribe_select_period(callback: types.CallbackQuery, state: FSMContext, bot: Bot):
    state_data = await state.get_data()
    selected_featutres = state_data.get('selected_features')
    markup = InlineKeyboardBuilder()
    markup.row(
        types.InlineKeyboardButton(text='Назад', callback_data='subscribe_create_button')
    )

    with open('config.json', encoding='utf-8') as config:
            config = json.load(config)
     
    total_price = sum([config.get(feature) for feature in selected_featutres])
    await state.set_state(SubscriptionStates.subscribe_select_period)
        
    await bot.edit_message_text(text=f'Введи кол-во месяцев действия подписки.\nС учетом выбранных вами функий, цена подписки за 1 месяц - {total_price} рублей',
                                chat_id=callback.from_user.id,
                                message_id=state_data.get('message_id'),
                                reply_markup=markup.as_markup())

@router.message(SubscriptionStates.subscribe_select_period)
async def subscribe_set_period(message: types.Message, state: FSMContext, bot: Bot):
    try:
        with open('config.json', encoding='utf-8') as config:
            config = json.load(config)

        selected_period = int(message.text)
        state_data = await state.get_data()
        selected_features = state_data.get('selected_features')
        
        total_price = sum([config.get(feature) for feature in selected_features]) * selected_period
        selected_features = ', '.join([available_features.get(feature) for feature in selected_features])

        if selected_period > 12:
            await message.reply('Введите число меньше чем 12')
        else:
            await state.update_data(selected_period=selected_period)
        
        markup = InlineKeyboardBuilder()
        markup.row(
            types.InlineKeyboardButton(text='Все правильно', callback_data='subscribe_select_yes'),
            types.InlineKeyboardButton(text='Отмена', callback_data='subscribe_select_no')
        )

        await bot.edit_message_text(text=f'Перед оплатой подписки проверьте правильность данных\n\n*Период*: {selected_period} мес.\n*Выбранные функции*: {selected_features}\n*Цена*: {total_price} руб',
                                    chat_id=message.from_user.id,
                                    message_id=state_data.get('message_id'),
                                    reply_markup=markup.as_markup())
    except Exception:
        await message.reply('Введите число!')

@router.callback_query(F.data.startswith('subscribe_select_'))
async def subscribe_agreement(callback: types.CallbackQuery, state: FSMContext, bot: Bot):
    agreement = callback.data.split('_')[2]
    state_data = await state.get_data()

    if agreement == 'yes':
        with open('config.json', encoding='utf-8') as config:
            config = json.load(config)

        selected_features = state_data.get('selected_features')
        selected_period = state_data.get('selected_period')
        
        total_price = sum([config.get(feature) for feature in selected_features]) * selected_period

        if selected_period >= 3:
            total_price = total_price

        confirmation_url, payment_id = create_payment(value=total_price, 
                                                      user_id=callback.from_user.id,
                                                      payment_description='Оплата подписки',
                                                      selected_features=','.join(selected_features),
                                                      selected_period=selected_period)

        markup = InlineKeyboardBuilder()
        markup.row(
            types.InlineKeyboardButton(text='Проверить платеж', callback_data=f'check_{payment_id}')
        )
System: оцени код from aiogram import Router, types, F, Bot
from aiogram.fsm.context import FSMContext

from aiogram.utils.keyboard import InlineKeyboardBuilder

from models.user import User, Subscription

from utils.admin import notify_admins
from utils.states import SubscriptionStates
from utils.payment import create_payment, check_payment

from jinja2 import Environment, FileSystemLoader
from datetime import datetime
from dateutil.relativedelta import relativedelta
from pytz import timezone

import json

router = Router()
templates = Environment(loader=FileSystemLoader('templates/subscribe'))
available_features = {'chatgpt': 'ChatGPT', 
                      'videomaker': 'Генератор видео + оживление фото', 
                      'dalle': 'Генератор фото'}

@router.callback_query(F.data == 'subscribe_main_menu')
async def subscribe_creator_menu(callback: types.CallbackQuery):
    markup = InlineKeyboardBuilder()
    markup.row(
        types.InlineKeyboardButton(
            text='Создать свою подписку!', callback_data='subscribe_create_button')
        )
    
    await callback.message.reply(text='Хотите получить доступ к полным функциям? В таком случае вы можете собрать свой тарифный план', 
                                 reply_markup=markup.as_markup())

@router.callback_query(F.data == 'subscribe_create_button')
async def subscribe_create_button(callback: types.CallbackQuery, state: FSMContext):
    markup = InlineKeyboardBuilder()
    markup.row(
        *[types.InlineKeyboardButton(text=name, callback_data=f'subscribe_include_{tech_name}') 
         for tech_name, name in available_features.items()],
         width=2
    )
    with open('config.json', encoding='utf-8') as config:
            config = json.load(config)

    price = '\n'.join([f'{name} - {config.get(tech_name)} руб.' for tech_name, name in available_features.items()])

    await state.set_state(SubscriptionStates.selecting_features)
    message = await callback.message.reply(f'Какими функциями вы хотите пользоваться в подписке?\n\nЦены:\n\n{price}', 
                                 reply_markup=markup.as_markup())
    
    await state.update_data(message_id=message.message_id)

@router.callback_query(F.data.startswith('subscribe_include_'))
async def subscribe_include_feature(callback: types.CallbackQuery, state: FSMContext, bot: Bot):
    state_data = await state.get_data()
    selected_features: list = state_data.setdefault('selected_features', [])

    feature = callback.data.split('_')[2]

    if selected_features is None:
        await state.update_data(selected_features=[feature])
    else:
        if feature not in selected_features:
            if isinstance(selected_features, list):
                selected_features.append(feature)

                await state.update_data(selected_features=selected_features)
        else:
            selected_features.remove(feature)
            await state.update_data(selected_features=selected_features)

    markup = InlineKeyboardBuilder()
    buttons = []

    for tech_name, name in available_features.items():
        name = name if tech_name not in selected_features else f'✅ {name}'

        buttons.append(
            types.InlineKeyboardButton(text=name, callback_data=f'subscribe_include_{tech_name}') 
        )
    
    markup.row(*buttons)

    if selected_features != []:
        markup.row(types.InlineKeyboardButton(
            text='Сохранить и продолжить', callback_data='subscribe_select_period'
        ))
    
    await bot.edit_message_text(text='Вы можете выбрать ещё несколько функций',
                                chat_id=callback.message.chat.id,
                                message_id=state_data.get('message_id'),
                                reply_markup=markup.as_markup())
System: @router.callback_query(F.data == 'subscribe_select_period')
async def subscribe_select_period(callback: types.CallbackQuery, state: FSMContext, bot: Bot):
    state_data = await state.get_data()
    selected_featutres = state_data.get('selected_features')
    markup = InlineKeyboardBuilder()
    markup.row(
        types.InlineKeyboardButton(text='Назад', callback_data='subscribe_create_button')
    )

    with open('config.json', encoding='utf-8') as config:
            config = json.load(config)
     
    total_price = sum([config.get(feature) for feature in selected_featutres])
    await state.set_state(SubscriptionStates.subscribe_select_period)
        
    await bot.edit_message_text(text=f'Введи кол-во месяцев действия подписки.\nС учетом выбранных вами функий, цена подписки за 1 месяц - {total_price} рублей',
                                chat_id=callback.from_user.id,
                                message_id=state_data.get('message_id'),
                                reply_markup=markup.as_markup())

@router.message(SubscriptionStates.subscribe_select_period)
async def subscribe_set_period(message: types.Message, state: FSMContext, bot: Bot):
    try:
        with open('config.json', encoding='utf-8') as config:
            config = json.load(config)

        selected_period = int(message.text)
        state_data = await state.get_data()
        selected_features = state_data.get('selected_features')
        
        total_price = sum([config.get(feature) for feature in selected_features]) * selected_period
        selected_features = ', '.join([available_features.get(feature) for feature in selected_features])

        if selected_period > 12:
            await message.reply('Введите число меньше чем 12')
        else:
            await state.update_data(selected_period=selected_period)
        
        markup = InlineKeyboardBuilder()
        markup.row(
            types.InlineKeyboardButton(text='Все правильно', callback_data='subscribe_select_yes'),
            types.InlineKeyboardButton(text='Отмена', callback_data='subscribe_select_no')
        )

        await bot.edit_message_text(text=f'Перед оплатой подписки проверьте правильность данных\n\n*Период*: {selected_period} мес.\n*Выбранные функции*: {selected_features}\n*Цена*: {total_price} руб',
                                    chat_id=message.from_user.id,
                                    message_id=state_data.get('message_id'),
                                    reply_markup=markup.as_markup())
    except Exception:
        await message.reply('Введите число!')

@router.callback_query(F.data.startswith('subscribe_select_'))
async def subscribe_agreement(callback: types.CallbackQuery, state: FSMContext, bot: Bot):
    agreement = callback.data.split('_')[2]
    state_data = await state.get_data()

    if agreement == 'yes':
        with open('config.json', encoding='utf-8') as config:
            config = json.load(config)

        selected_features = state_data.get('selected_features')
        selected_period = state_data.get('selected_period')
        
        total_price = sum([config.get(feature) for feature in selected_features]) * selected_period

        if selected_period >= 3:
            total_price = total_price

        confirmation_url, payment_id = create_payment(value=total_price, 
                                                      user_id=callback.from_user.id,
                                                      payment_description='Оплата подписки',
                                                      selected_features=','.join(selected_features),
                                                      selected_period=selected_period)

        markup = InlineKeyboardBuilder()
        markup.row(
            types.InlineKeyboardButton(text='Проверить платеж', callback_data=f'check_{payment_id}')
        )
Assistant:
Assistant: