Привет! Я хочу создать отдельную таблицу в бд "проекты". Бд давай сделаем отдельно. То есть напишем скрипт отдельно и запустим отдельно Чтобы там указывался предмет, а также описание того, что нужно сделать. У каждого предмета может быть несколько проектов. А также нужно чтобы можно было загружать туда файлы и скачивать их. Добавь в моего тг бота вкладку проекты с возможностью добавлять в проекты предметы к ним проекты в проекты описание добавлять либо файлы.


Вот мой код:
main.py: [from datetime import datetime, timedelta
import locale

from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
    ApplicationBuilder,
    CommandHandler,
    CallbackQueryHandler,
    ContextTypes,
    MessageHandler,
    filters
)

from db import fetch_schedule, update_homework

# Инициализация бота
TOKEN = '7895405887-lSB5XkBlQ'

user_state = {}

locale.setlocale(locale.LC_TIME, 'ru_RU.UTF-8')


def format_schedule(date, schedule):
    day_name = date.strftime('%A')
    formatted = f"*Расписание на {date.strftime('%d.%m.%Y')}, {day_name}*\n\n"
    for entry in schedule:
        formatted += f"**{entry[0]}**\n" \
                     f"**{entry[1]}**\n" \
                     f"Преподаватель: {entry[2]}\n" \
                     f"Место: {entry[3]}\n" \
                     f"Домашнее задание: {entry[4]}\n\n"
    return formatted


async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user_id = update.effective_user.id
    today = datetime.now().date()
    user_state[user_id] = {
        'view': 'week',
        'current_date': today
    }
    await send_schedule(update, context, user_id)


async def send_schedule(update: Update, context: ContextTypes.DEFAULT_TYPE, user_id):
    state = user_state[user_id]
    view = state['view']
    current_date = state['current_date']

    if view == 'day':
        schedule = fetch_schedule(current_date.strftime('%Y-%m-%d'))
        text = format_schedule(current_date, schedule)
    elif view == 'week':
        start_of_week = current_date - timedelta(days=current_date.weekday())
        end_of_week = start_of_week + timedelta(days=6)
        text = f"*Расписание с {start_of_week.strftime('%d.%m.%Y')} по {end_of_week.strftime('%d.%m.%Y')}*\n\n"
        for single_date in (start_of_week + timedelta(n) for n in range(7)):
            schedule = fetch_schedule(single_date.strftime('%Y-%m-%d'))
            day_name = single_date.strftime('%A')  # Убедитесь, что локаль установлена на русский
            text += f"• *{single_date.strftime('%d.%m.%Y')}, {day_name}*\n"
            if schedule:
                for entry in schedule:
                    time, subject, teacher, location, homework = entry
                    homework_text = f"\nДомашнее задание: {homework}" if homework else ""
                    text += f"  - **{time}** {subject} ({teacher}){homework_text}\n"
            else:
                text += "  - Нет занятий.\n"
            text += "\n"
        text = text.strip()
    else:
        text = "Неизвестный вид отображения расписания."

    keyboard = [
        [
            InlineKeyboardButton("Неделя", callback_data='view_week'),
            InlineKeyboardButton("День", callback_data='view_day')
        ],
        [
            InlineKeyboardButton("Предыдущий", callback_data='prev'),
            InlineKeyboardButton("Следующий", callback_data='next')
        ],
        [
            InlineKeyboardButton("Добавить домашнее задание", callback_data='add_homework')
        ]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)

    if update.callback_query:
        await update.callback_query.edit_message_text(
            text=text,
            parse_mode='Markdown',
            reply_markup=reply_markup
        )
    else:
        await update.message.reply_text(
            text=text,
            parse_mode='Markdown',
            reply_markup=reply_markup
        )


async def button(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    user_id = query.from_user.id
    state = user_state.get(user_id, {})

    if not state:
        state = {
            'view': 'week',
            'current_date': datetime.now().date()
        }
        user_state[user_id] = state

    if query.data == 'view_week':
        state['view'] = 'week'
        state['current_date'] = datetime.now().date()
    elif query.data == 'view_day':
        state['view'] = 'day'
        state['current_date'] = datetime.now().date()
    elif query.data == 'prev':
        if state['view'] == 'day':
            state['current_date'] -= timedelta(days=1)
        elif state['view'] == 'week':
            state['current_date'] -= timedelta(weeks=1)
    elif query.data == 'next':
        if state['view'] == 'day':
            state['current_date'] += timedelta(days=1)
        elif state['view'] == 'week':
            state['current_date'] += timedelta(weeks=1)
    elif query.data == 'add_homework':
        await send_homework_selection(update, context, user_id)

    user_state[user_id] = state
    if query.data != 'add_homework':
        await send_schedule(update, context, user_id)


async def send_homework_selection(update: Update, context: ContextTypes.DEFAULT_TYPE, user_id):
    state = user_state[user_id]
    today = datetime.now().date()
    start_of_week = today - timedelta(days=today.weekday())
    dates = [(start_of_week + timedelta(days=i)) for i in range(7)]

    keyboard = []
    for date in dates:
        date_str_display = date.strftime('%d.%m.%Y')
        date_str_callback = date.strftime('%Y-%m-%d')
        keyboard.append([InlineKeyboardButton(date_str_display, callback_data=f'date_{date_str_callback}')])

    keyboard.append([InlineKeyboardButton("Отмена", callback_data='cancel')])
    reply_markup = InlineKeyboardMarkup(keyboard)
    await update.callback_query.edit_message_text(
        text="Выберите дату:",
        reply_markup=reply_markup
    )


async def select_date(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()
    user_id = query.from_user.id
    date_str = query.data.split('_')[1]
    selected_date = datetime.strptime(date_str, '%Y-%m-%d').date()
    user_state[user_id]['selected_date'] = selected_date

    schedule = fetch_schedule(selected_date.strftime('%Y-%m-%d'))
    if not schedule:
        await query.edit_message_text(
            text=f"На выбранную дату {selected_date.strftime('%d.%m.%Y')} нет занятий.",
            reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("Добавить домашнее задание", callback_data='add_homework')
            ]])
        )
        return

    homework_subjects = [{'subject': entry[1], 'time': entry[0]} for entry in schedule]
    user_state[user_id]['homework_subjects'] = homework_subjects

    keyboard = [
        [InlineKeyboardButton(f"{entry['subject']} ({entry['time']})", callback_data=f'subject_{i}')]
        for i, entry in enumerate(homework_subjects)
    ]
    keyboard.append([InlineKeyboardButton("Отмена", callback_data='cancel')])
    reply_markup = InlineKeyboardMarkup(keyboard)

    await query.edit_message_text(
        text=f"Вы выбрали дату: {selected_date.strftime('%d.%m.%Y')}. Теперь выберите предмет:",
        reply_markup=reply_markup
    )


async def select_subject(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()
    user_id = query.from_user.id
    data = query.data.split('_')
    if len(data) < 2:
        await query.edit_message_text(
            text="Некорректный выбор предмета.",
            reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("Добавить домашнее задание", callback_data='add_homework')
            ]])
        )
        return
    index = int(data[1])
    homework_subjects = user_state[user_id].get('homework_subjects', [])
    if index >= len(homework_subjects):
        await query.edit_message_text(
            text="Некорректный выбор предмета.",
            reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("Добавить домашнее задание", callback_data='add_homework')
            ]])
        )
        return
    selected_entry = homework_subjects[index]
    subject = selected_entry['subject']
    time_slot = selected_entry['time']
    user_state[user_id]['selected_subject'] = subject
    user_state[user_id]['selected_time'] = time_slot

    await query.edit_message_text(
        text=f"Вы выбрали предмет: {subject} ({time_slot}). Введите домашнее задание."
    )
    context.chat_data['awaiting_homework'] = True


async def handle_homework_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user_id = update.effective_user.id
    if context.chat_data.get('awaiting_homework'):
        homework = update.message.text
        date = user_state[user_id].get('selected_date')
        time_slot = user_state[user_id].get('selected_time')

        if date and time_slot:
            update_homework(date.strftime('%Y-%m-%d'), time_slot, homework)

            await update.message.reply_text(f"Домашнее задание для {date.strftime('%d.%m.%Y')} {time_slot}:\n{homework}")
            await update.message.reply_text("Домашнее задание добавлено.")

            # Очистить состояние ожидания
            context.chat_data['awaiting_homework'] = False
            del user_state[user_id]['selected_date']
            del user_state[user_id]['selected_subject']
            del user_state[user_id]['selected_time']

            # После добавления домашнего задания показать расписание
            await send_schedule(update, context, user_id)
        else:
            await update.message.reply_text("Ошибка. Выберите дату и предмет.")
    else:
        await update.message.reply_text("Вы не находитесь в процессе добавления домашнего задания.")


async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()
    user_id = query.from_user.id
    state = user_state.get(user_id, {})


    if 'selected_date' in state or 'selected_subject' in state:
        # Удалить состояние выбора даты и предмета
        state.pop('selected_date', None)
        state.pop('selected_subject', None)
        state.pop('selected_time', None)
        await query.edit_message_text(
            text="Процесс добавления домашнего задания отменен.",
            reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("Добавить домашнее задание", callback_data='add_homework')
            ]])
        )
        await send_schedule(update, context, user_id)
    else:
        await query.edit_message_text(
            # text="Нет активного процесса добавления домашнего задания.",
            # reply_markup=InlineKeyboardMarkup([[
            #     InlineKeyboardButton("Добавить домашнее задание", callback_data='add_homework')
            # ]]
                await send_schedule(update, context, user_id)
            )



def main():
    application = ApplicationBuilder().token(TOKEN).build()

    application.add_handler(CommandHandler("start", start))

    # Специфичные обработчики добавляются первыми
    application.add_handler(CallbackQueryHandler(select_date, pattern='^date_'))
    application.add_handler(CallbackQueryHandler(select_subject, pattern='^subject_'))
    application.add_handler(CallbackQueryHandler(cancel, pattern='^cancel$'))

    # Общий обработчик добавляется последним
    application.add_handler(CallbackQueryHandler(button))

    application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_homework_text))

    application.run_polling()


if __name__ == '__main__':
    main()]




db.py: [import sqlite3


def create_db():
    conn = sqlite3.connect('schedule.db')
    c = conn.cursor()

    # Создание таблицы расписания
    c.execute('''
        CREATE TABLE IF NOT EXISTS schedule (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            date TEXT,
            time TEXT,
            subject TEXT,
            teacher TEXT,
            location TEXT,
            homework TEXT
        )
    ''')

    conn.commit()
    conn.close()


def insert_schedule(date, time, subject, teacher, location, homework=''):
    conn = sqlite3.connect('schedule.db')
    c = conn.cursor()

    c.execute('''
        INSERT INTO schedule (date, time, subject, teacher, location, homework)
        VALUES (?, ?, ?, ?, ?, ?)
    ''', (date, time, subject, teacher, location, homework))

    conn.commit()
    conn.close()


def fetch_schedule(date):
    conn = sqlite3.connect('schedule.db')
    c = conn.cursor()

    c.execute('''
        SELECT time, subject, teacher, location, homework
        FROM schedule
        WHERE date = ?
    ''', (date,))

    rows = c.fetchall()
    conn.close()

    return rows


def update_homework(date, time, homework):
    conn = sqlite3.connect('schedule.db')
    c = conn.cursor()

    c.execute('''
        UPDATE schedule
        SET homework = ?
        WHERE date = ? AND time = ?
    ''', (homework, date, time))

    conn.commit()
    conn.close()]