Assistant: 
User: User: оцени код 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: оцени код 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())
Assistant:
Assistant: