150600
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -123,9 +123,9 @@ celerybeat.pid
|
|||||||
# Environments
|
# Environments
|
||||||
.env
|
.env
|
||||||
.venv
|
.venv
|
||||||
env/
|
.env/
|
||||||
venv/
|
venv/
|
||||||
ENV/
|
.env/
|
||||||
env.bak/
|
env.bak/
|
||||||
venv.bak/
|
venv.bak/
|
||||||
|
|
||||||
|
|||||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/old/bot.log" charset="windows-1251" />
|
||||||
|
<file url="file://$PROJECT_DIR$/old/bot.log" charset="windows-1251" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
155
README.md
155
README.md
@@ -1,2 +1,157 @@
|
|||||||
# BOTKlining
|
# BOTKlining
|
||||||
|
|
||||||
|
## Структура
|
||||||
|
|
||||||
|
1. `main.py`: основной файл для запуска бота.
|
||||||
|
2. `handlers.py`: обработчики команд и состояний.
|
||||||
|
3. `database.py`: взаимодействие с базой данных.
|
||||||
|
4. `logger.py`: логирование действий пользователей.
|
||||||
|
5. `.env`: файл для хранения конфиденциальных данных.
|
||||||
|
|
||||||
|
Для создания бота с указанной функциональностью и логикой, а также использования файла .env для хранения конфиденциальных данных, мы разобьем задачу на несколько шагов:
|
||||||
|
|
||||||
|
Настройка окружения и установка зависимостей
|
||||||
|
Создание базы данных
|
||||||
|
Разработка основных обработчиков команд и колбэков
|
||||||
|
Создание функций для работы с базой данных
|
||||||
|
Настройка логирования
|
||||||
|
Реализация основной логики бота
|
||||||
|
|
||||||
|
Вот подробное описание структуры и логики бота:
|
||||||
|
|
||||||
|
## Inline клавиатура бота:
|
||||||
|
1. Учетные данные
|
||||||
|
|
||||||
|
- Изменить ФИО: Пользователь может изменить свое ФИО.
|
||||||
|
- Изменить номер телефона: Позволяет изменить номер телефона.
|
||||||
|
- Добавить адрес: Пользователь может добавить новый адрес.
|
||||||
|
- Удалить адрес: Пользователь может удалить ранее добавленный адрес.
|
||||||
|
- Поделиться контактом: Позволяет поделиться контактными данными, для автоматического заполнения в базе данных.
|
||||||
|
|
||||||
|
2. Сделать заказ
|
||||||
|
|
||||||
|
- Добавить учетные данные: Если у пользователя нет учетных данных, он должен их добавить. Если данные есть они заполняются автоматически.
|
||||||
|
- Выбрать адрес: Пользователь выбирает адрес или добавляет новый.
|
||||||
|
- Выбрать время уборки: Предлагает утро, день, вечер.
|
||||||
|
- Выбрать тип уборки: Влажная, сухая, генеральная.
|
||||||
|
- Выбрать способ оплаты: Картой, наличными.
|
||||||
|
- Подтвердить заказ: Подтверждает заказ или позволяет изменить ответы. После подтверждения заказа автоматически отправлять уведомление в группу операторов, а также добавлять заказ в историю.
|
||||||
|
- Заказу присваивается ID номер
|
||||||
|
|
||||||
|
3. История заказов
|
||||||
|
|
||||||
|
- Просмотреть историю заказов: Позволяет пользователю просмотреть свою историю заказов.
|
||||||
|
- Добавить функцию повторного заказа на основе предыдущих заказов.
|
||||||
|
|
||||||
|
4. Заказать звонок
|
||||||
|
|
||||||
|
- Добавить учетные данные: Если у пользователя нет учетных данных, он должен их добавить. Если данные есть они заполняются автоматически.
|
||||||
|
- Заказать звонок: Отправляет учетные данные (ФИО, номер телефона) в группу операторов, с подписью об звонке. Пользователь видит сообщение "ожидайте звонок в течении 30 минут"
|
||||||
|
|
||||||
|
5. Начать разговор с оператором
|
||||||
|
|
||||||
|
- Добавить учетные данные: Если у пользователя нет учетных данных, он должен их добавить. Если данные есть они заполняются автоматически.
|
||||||
|
- Начать разговор: Отправляет учетные данные (ФИО, номер телефона, ID номер крайнего заказа) в группу операторов.
|
||||||
|
- Завершить разговор: Пользователь завершает разговор.
|
||||||
|
- После завершения разговора автоматически отправлять анкету о качестве обслуживания пользователю для обратной связи. Автоматически закрыть анкету в случае не ответа 2 часов.
|
||||||
|
|
||||||
|
6. Назад
|
||||||
|
|
||||||
|
- Возврат к предыдущему набору кнопок: Позволяет вернуться к предыдущему меню кнопок.
|
||||||
|
|
||||||
|
## Логика нажатия кнопок и сохранения данных:
|
||||||
|
- При первом использовании бота запросить у пользователя учетные данные (ФИО, номер телефона) и сохранить их для последующих заказов. Можно использовать личные данные из Telegram (если пользователь разрешил) для заполнения некоторых полей автоматически.
|
||||||
|
- При нажатии кнопок пользователем, бот запоминает предыдущий выбор и отображает следующий набор кнопок соответственно.
|
||||||
|
- Когда пользователь нажимает на любую из кнопок, предыдущий выбор автоматически скрывается, а вместо него появляется следующий набор кнопок. Кнопка "Назад" позволяет вернуться к предыдущему набору кнопок в случае необходимости. Это помогает сделать интерфейс более удобным и интуитивно понятным для пользователей.
|
||||||
|
- Данные пользователя (учетные данные, адреса, заказы и т.д.) сохраняются в базе данных SQLite3 для последующего использования.
|
||||||
|
- Логирование действий пользователей осуществляется путем записи информации о каждом действии в лог-файлы, включая дату, время, ID пользователя и другие параметры.
|
||||||
|
## Управление из группы и внутри бота:
|
||||||
|
- Группа для заказов управляется операторами и администраторами, которые имеют доступ к соответствующим функциям.
|
||||||
|
- Операторы могут просматривать историю заказов пользователей, отвечать на сообщения, завершать разговоры и управлять заказами.
|
||||||
|
- Администраторы имеют дополнительные функции, такие как выгрузка переписки в формате JSON.
|
||||||
|
- Бот на aiogram используется для более эффективной работы и реализации функций бота через асинхронные методы.
|
||||||
|
- Эта структура и логика позволят создать функционального бота для управления заказами и общения с операторами, обеспечивая удобство пользователей и контроль над данными.
|
||||||
|
- Данные токена id групп, id администраторов, операторов дложны храниться в файле env
|
||||||
|
## Автоматизация
|
||||||
|
|
||||||
|
- Добавить таймеры для отслеживания неактивности пользователя и предложения начать разговор с оператором или оформить заказ при необходимости.
|
||||||
|
- Использовать базу данных для хранения информации о пользователях, заказах и истории коммуникации с операторами.
|
||||||
|
- Реализовать механизм автоматического анализа данных о заказах для предложения персонализированных услуг или скидок.
|
||||||
|
- Создаем базу данных SQLite3 для хранения информации о пользователях, их учетных данных, заказах и истории сообщений с операторами.
|
||||||
|
- Создаем таблицы для каждой категории данных: пользователи, заказы, история сообщений и т.д.
|
||||||
|
- Связываем таблицы между собой по ключам (например, по ID пользователя).
|
||||||
|
- При каждом действии пользователя (нажатие кнопки, отправка сообщения) записываем соответствующую информацию в лог-файлы.
|
||||||
|
- Логируем дату, время действия, ID пользователя, текстовые данные (если есть) и другие необходимые параметры.
|
||||||
|
- Создаем специальную группу для приема заказов, где только операторы и администраторы имеют доступ.
|
||||||
|
- Назначаем операторов и администраторов, которые могут управлять заказами в этой группе.
|
||||||
|
|
||||||
|
1. Функционал операторов:
|
||||||
|
- Операторы могут просматривать историю заказов конкретного пользователя по его ID.
|
||||||
|
- Операторы могут отвечать пользователю из группы используя функцию ответа (replay).
|
||||||
|
- Операторы могут завершать разговор с пользователем с помощью соответствующей кнопки.
|
||||||
|
|
||||||
|
2. Функционал администраторов:
|
||||||
|
- Администраторы имеют все функции операторов.
|
||||||
|
- Дополнительно администраторы могут выгружать переписку операторов и пользователя в виде JSON файла.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Логика Бота
|
||||||
|
есть inline клавиотура со следующими кнопками:
|
||||||
|
Учетные данные
|
||||||
|
Изменить ФИО
|
||||||
|
Изменить номер телефона
|
||||||
|
Добавит адрес
|
||||||
|
Поделиться контактом
|
||||||
|
сделать заказ
|
||||||
|
Добавит учетные данные, если данные не введены, если введены то пропустить вопрос.
|
||||||
|
выбрать адрес или указать новый адрес. все веденные адреса сохраняються.
|
||||||
|
спросить время для уборки: утро/День/вечер
|
||||||
|
Спросить тип уборки: Влажная/Сухая/Генеральная
|
||||||
|
Спросить способ оплаты: Картой/Наличными
|
||||||
|
Подьвердить заказ, или предложить изменить ответ на вопрос. далее кнопки вопросов что бы изменить один ответ и после изменения повторно подтвердить.
|
||||||
|
После подтверждения, сообщения с ответами отправляеться группу операторов.
|
||||||
|
История заказов
|
||||||
|
Все отправленные ответы в группу сохраняются как заказ и храниться в базе данных.
|
||||||
|
Заказать звонок
|
||||||
|
Добавит учетные данные, если данные не введены, если введены то пропустить вопрос.
|
||||||
|
Кнопка заказать звонок, отправляет учетные данные (ФИО, номер телефона) в группу операторов.
|
||||||
|
Начать разговор с оератором
|
||||||
|
Добавит учетные данные, если данные не введены, если введены то пропустить вопрос.
|
||||||
|
Кнопка начать разговор, отправляет учетные данные (ФИО, номер телефона) в группу операторов.
|
||||||
|
Оператор из группы нажимает ответить(replay) и пишет сообщение, сообшение отправляеться пользователю
|
||||||
|
пользователь пишет сообщение и оно отправляеться в группу до дех под пока пользователь не нажмет завершить разговор.
|
||||||
|
Если кнопка завершить разговор не нажато, то через 1 час разговор с оператором завершаеться автоматически.
|
||||||
|
При заходе пользователя через 2 часа появляеться первоначальное меню кнопок.
|
||||||
|
Допиши логику, слелай её более автоматизированной.
|
||||||
|
|
||||||
|
ChatGPT
|
||||||
|
Ты создал очень хорошую базу для логики бота! Вот несколько дополнений и идей для автоматизации:
|
||||||
|
|
||||||
|
Учетные данные:
|
||||||
|
|
||||||
|
При первом использовании бота запросить у пользователя учетные данные (ФИО, номер телефона) и сохранить их для последующих заказов. Можно использовать личные данные из Telegram (если пользователь разрешил) для заполнения некоторых полей автоматически.
|
||||||
|
Добавить возможность изменения учетных данных через команду или кнопку "Изменить учетные данные".
|
||||||
|
Сделать заказ:
|
||||||
|
|
||||||
|
После выбора адреса показывать пользователю карту с указанным адресом для подтверждения или возможности изменения.
|
||||||
|
Автоматически предлагать время уборки в зависимости от текущего времени (например, если пользователь заходит в 9 утра, предложить утреннее время уборки).
|
||||||
|
После подтверждения заказа автоматически отправлять уведомление в группу операторов, а также добавлять заказ в историю.
|
||||||
|
История заказов:
|
||||||
|
|
||||||
|
Позволить пользователю просматривать историю своих заказов через бота.
|
||||||
|
Добавить функцию повторного заказа на основе предыдущих заказов.
|
||||||
|
Заказать звонок:
|
||||||
|
|
||||||
|
Позволить пользователю выбрать время для звонка (например, "Заказать звонок через 30 минут").
|
||||||
|
Автоматически отправлять уведомление о заказе звонка в группу операторов с указанием времени.
|
||||||
|
Начать разговор с оператором:
|
||||||
|
|
||||||
|
Добавить возможность выбора темы разговора (например, "Техническая поддержка", "Вопрос по заказу" и т. д.).
|
||||||
|
После завершения разговора автоматически отправлять анкету о качестве обслуживания пользователю для обратной связи.
|
||||||
|
Автоматизация:
|
||||||
|
|
||||||
|
Добавить таймеры для отслеживания неактивности пользователя и предложения начать разговор с оператором или оформить заказ при необходимости.
|
||||||
|
Использовать базу данных для хранения информации о пользователях, заказах и истории коммуникации с операторами.
|
||||||
|
Реализовать механизм автоматического анализа данных о заказах для предложения персонализированных услуг или скидок.
|
||||||
|
Эти функции помогут сделать бота более удобным и эффективным для пользователей и операторов.
|
||||||
53
database.py
Normal file
53
database.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
def create_tables():
|
||||||
|
conn = sqlite3.connect('bot_data.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS orders (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT,
|
||||||
|
phone TEXT,
|
||||||
|
address TEXT,
|
||||||
|
cleaning_time TEXT,
|
||||||
|
cleaning_type TEXT,
|
||||||
|
payment_method TEXT
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
user_id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
phone TEXT,
|
||||||
|
address TEXT
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def add_order(name, phone, address, cleaning_time, cleaning_type, payment_method):
|
||||||
|
conn = sqlite3.connect('bot_data.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO orders (name, phone, address, cleaning_time, cleaning_type, payment_method)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
|
''', (name, phone, address, cleaning_time, cleaning_type, payment_method))
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def get_order_history(user_id):
|
||||||
|
conn = sqlite3.connect('bot_data.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT * FROM orders WHERE user_id = ?
|
||||||
|
''', (user_id,))
|
||||||
|
|
||||||
|
orders = cursor.fetchall()
|
||||||
|
conn.close()
|
||||||
|
return orders
|
||||||
158
handlers.py
Normal file
158
handlers.py
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import logging
|
||||||
|
from aiogram import types
|
||||||
|
from aiogram.dispatcher import FSMContext
|
||||||
|
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
from database import add_order, get_order_history
|
||||||
|
from logger import log_action
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
class OrderForm(StatesGroup):
|
||||||
|
waiting_for_name = State()
|
||||||
|
waiting_for_phone = State()
|
||||||
|
waiting_for_address = State()
|
||||||
|
waiting_for_cleaning_time = State()
|
||||||
|
waiting_for_cleaning_type = State()
|
||||||
|
waiting_for_payment_method = State()
|
||||||
|
confirmation = State()
|
||||||
|
|
||||||
|
def main_menu_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Учетные данные', callback_data='account_data'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Сделать заказ', callback_data='make_order'))
|
||||||
|
keyboard.add(InlineKeyboardButton('История заказов', callback_data='order_history'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Заказать звонок', callback_data='request_call'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Начать разговор с оператором', callback_data='talk_operator'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
def account_data_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Изменить ФИО', callback_data='change_name'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Изменить номер телефона', callback_data='change_phone'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Добавить адрес', callback_data='add_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Удалить адрес', callback_data='delete_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Поделиться контактом', callback_data='share_contact'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Назад', callback_data='back_to_main'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
def order_confirmation_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Подтвердить', callback_data='confirm_order'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
def register_handlers(dp, OPERATORS_GROUP_ID):
|
||||||
|
@dp.message_handler(commands=['start'])
|
||||||
|
async def send_welcome(message: types.Message):
|
||||||
|
await message.answer("Добро пожаловать в BOTKlining!", reply_markup=main_menu_keyboard())
|
||||||
|
log_action(message.from_user.id, 'start')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'account_data')
|
||||||
|
async def process_account_data(callback_query: types.CallbackQuery):
|
||||||
|
await callback_query.answer()
|
||||||
|
await callback_query.message.answer("Учетные данные:", reply_markup=account_data_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'account_data')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'make_order')
|
||||||
|
async def process_make_order(callback_query: types.CallbackQuery, state: FSMContext):
|
||||||
|
await callback_query.answer()
|
||||||
|
await callback_query.message.answer("Начнем с ваших учетных данных. Введите ваше ФИО:")
|
||||||
|
await OrderForm.waiting_for_name.set()
|
||||||
|
log_action(callback_query.from_user.id, 'make_order')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'order_history')
|
||||||
|
async def process_order_history(callback_query: types.CallbackQuery):
|
||||||
|
await callback_query.answer()
|
||||||
|
orders = get_order_history(callback_query.from_user.id)
|
||||||
|
if orders:
|
||||||
|
history_message = "\n\n".join([f"Заказ {order['id']}:\nФИО: {order['name']}\nАдрес: {order['address']}\nТип уборки: {order['cleaning_type']}" for order in orders])
|
||||||
|
await callback_query.message.answer(f"История заказов:\n{history_message}")
|
||||||
|
else:
|
||||||
|
await callback_query.message.answer("История заказов пуста.")
|
||||||
|
log_action(callback_query.from_user.id, 'order_history')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'request_call')
|
||||||
|
async def process_request_call(callback_query: types.CallbackQuery):
|
||||||
|
await callback_query.answer()
|
||||||
|
await callback_query.message.answer("Заказ звонка оформлен. Ожидайте звонок в течение 30 минут.")
|
||||||
|
log_action(callback_query.from_user.id, 'request_call')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'talk_operator')
|
||||||
|
async def process_talk_operator(callback_query: types.CallbackQuery):
|
||||||
|
await callback_query.answer()
|
||||||
|
await callback_query.message.answer("Разговор с оператором начат.")
|
||||||
|
log_action(callback_query.from_user.id, 'talk_operator')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'back_to_main')
|
||||||
|
async def process_back_to_main(callback_query: types.CallbackQuery):
|
||||||
|
await callback_query.answer()
|
||||||
|
await callback_query.message.answer("Главное меню:", reply_markup=main_menu_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'back_to_main')
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_name, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_name(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['name'] = message.text
|
||||||
|
await message.answer("Введите ваш номер телефона:")
|
||||||
|
await OrderForm.waiting_for_phone.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_phone, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_phone(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['phone'] = message.text
|
||||||
|
await message.answer("Введите адрес для уборки:")
|
||||||
|
await OrderForm.waiting_for_address.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_address, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_order_address(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['address'] = message.text
|
||||||
|
await message.answer("Выберите время для уборки (утро/день/вечер):")
|
||||||
|
await OrderForm.waiting_for_cleaning_time.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_cleaning_time, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_cleaning_time(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['cleaning_time'] = message.text
|
||||||
|
await message.answer("Выберите тип уборки (влажная/сухая/генеральная):")
|
||||||
|
await OrderForm.waiting_for_cleaning_type.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_cleaning_type, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_cleaning_type(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['cleaning_type'] = message.text
|
||||||
|
await message.answer("Выберите способ оплаты (картой/наличными):")
|
||||||
|
await OrderForm.waiting_for_payment_method.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_payment_method, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_payment_method(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['payment_method'] = message.text
|
||||||
|
|
||||||
|
await message.answer("Подтвердите заказ:\n"
|
||||||
|
f"ФИО: {data['name']}\n"
|
||||||
|
f"Номер телефона: {data['phone']}\n"
|
||||||
|
f"Адрес: {data['address']}\n"
|
||||||
|
f"Время уборки: {data['cleaning_time']}\n"
|
||||||
|
f"Тип уборки: {data['cleaning_type']}\n"
|
||||||
|
f"Способ оплаты: {data['payment_method']}\n"
|
||||||
|
"Если все верно, нажмите 'Подтвердить'. В противном случае, измените нужные данные.",
|
||||||
|
reply_markup=order_confirmation_keyboard())
|
||||||
|
await OrderForm.confirmation.set()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'confirm_order', state=OrderForm.confirmation)
|
||||||
|
async def process_confirm_order(callback_query: types.CallbackQuery, state: FSMContext):
|
||||||
|
await callback_query.answer()
|
||||||
|
async with state.proxy() as data:
|
||||||
|
order_details = (f"Новый заказ:\n"
|
||||||
|
f"ФИО: {data['name']}\n"
|
||||||
|
f"Номер телефона: {data['phone']}\n"
|
||||||
|
f"Адрес: {data['address']}\n"
|
||||||
|
f"Время уборки: {data['cleaning_time']}\n"
|
||||||
|
f"Тип уборки: {data['cleaning_type']}\n"
|
||||||
|
f"Способ оплаты: {data['payment_method']}")
|
||||||
|
await bot.send_message(OPERATORS_GROUP_ID, order_details)
|
||||||
|
add_order(data['name'], data['phone'], data['address'], data['cleaning_time'], data['cleaning_type'], data['payment_method'])
|
||||||
|
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Ваш заказ был подтвержден и отправлен операторам.")
|
||||||
|
await state.finish()
|
||||||
6
logger.py
Normal file
6
logger.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
def log_action(user_id, action):
|
||||||
|
logging.info(f"User {user_id} performed action: {action}")
|
||||||
197
main.py
197
main.py
@@ -1,188 +1,31 @@
|
|||||||
import logging
|
import logging
|
||||||
import sqlite3
|
|
||||||
import asyncio
|
|
||||||
from aiogram import Bot, Dispatcher, types
|
from aiogram import Bot, Dispatcher, types
|
||||||
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
||||||
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
|
from aiogram.utils import executor
|
||||||
|
from aiogram.dispatcher import FSMContext
|
||||||
|
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
|
from handlers import register_handlers
|
||||||
|
from database import create_tables
|
||||||
|
|
||||||
|
# Загрузка переменных окружения из .env файла
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
API_TOKEN = os.getenv('BOT_API_TOKEN')
|
||||||
|
OPERATORS_GROUP_ID = int(os.getenv('OPERATORS_GROUP_ID'))
|
||||||
|
ADMIN_GROUP_ID = int(os.getenv('ADMIN_GROUP_ID'))
|
||||||
|
|
||||||
# Устанавливаем уровень логов
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
# Подключаемся к базе данных SQLite
|
|
||||||
conn = sqlite3.connect("answers.db")
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
# Создание таблицы для хранения ответов
|
|
||||||
cursor.execute("""
|
|
||||||
CREATE TABLE IF NOT EXISTS answers (
|
|
||||||
user_id INTEGER,
|
|
||||||
question_id INTEGER,
|
|
||||||
answer TEXT
|
|
||||||
)
|
|
||||||
""")
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
# Заменить на свой токен
|
|
||||||
API_TOKEN = '7472030348:AAGI53nX-ON-WBmEhd_qBC6EnZsHOqp_2kE'
|
|
||||||
GROUP_ID = '-1001961537659'
|
|
||||||
|
|
||||||
# Инициализация бота и диспетчера
|
|
||||||
bot = Bot(token=API_TOKEN)
|
bot = Bot(token=API_TOKEN)
|
||||||
dp = Dispatcher(bot)
|
dp = Dispatcher(bot)
|
||||||
dp.middleware.setup(LoggingMiddleware())
|
dp.middleware.setup(LoggingMiddleware())
|
||||||
|
|
||||||
# Клавиатура для подтверждения ответов
|
# Основное приложение
|
||||||
confirm_keyboard = ReplyKeyboardMarkup(resize_keyboard=True).add(KeyboardButton('Подтвердить'))
|
|
||||||
|
|
||||||
# Словарь для хранения вопросов и ответов
|
|
||||||
questions = {
|
|
||||||
1: "Как вас зовут?",
|
|
||||||
2: "Укажите номер телефона дл связи",
|
|
||||||
3: "Укажите район, улицу дом",
|
|
||||||
4: "Какая уборка нужна, влажная ли сухая?",
|
|
||||||
5: "На какое время?",
|
|
||||||
6: "Оплата наличными или картой?"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Обработчик команды /start
|
|
||||||
@dp.message_handler(commands=['start'])
|
|
||||||
async def start(message: types.Message):
|
|
||||||
await message.answer("Привет! Я задам тебе 6 вопросов. Давай начнем.")
|
|
||||||
await ask_question(message.chat.id, 1)
|
|
||||||
|
|
||||||
|
|
||||||
# Функция для задания вопроса
|
|
||||||
async def ask_question(user_id, question_id):
|
|
||||||
#question_text = questions[question_id]
|
|
||||||
#await bot.send_message(user_id, text=question_text, reply_markup=confirm_keyboard)
|
|
||||||
if question_id == 4:
|
|
||||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
|
||||||
[
|
|
||||||
InlineKeyboardButton(text="Влажная", callback_data="wet_cleaning"),
|
|
||||||
InlineKeyboardButton(text="Сухая", callback_data="dry_cleaning")
|
|
||||||
]
|
|
||||||
])
|
|
||||||
question_text = questions[question_id]
|
|
||||||
await bot.send_message(user_id, text=question_text, reply_markup=keyboard)
|
|
||||||
elif question_id == 5:
|
|
||||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
|
||||||
[
|
|
||||||
InlineKeyboardButton(text="Утро", callback_data="morning_time"),
|
|
||||||
InlineKeyboardButton(text="День", callback_data="day_time"),
|
|
||||||
InlineKeyboardButton(text="Вечер", callback_data="evening_time")
|
|
||||||
]
|
|
||||||
])
|
|
||||||
question_text = questions[question_id]
|
|
||||||
await bot.send_message(user_id, text=question_text, reply_markup=keyboard)
|
|
||||||
elif question_id == 6:
|
|
||||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
|
||||||
[
|
|
||||||
InlineKeyboardButton(text="Наличные", callback_data="cash_payment"),
|
|
||||||
InlineKeyboardButton(text="Карта", callback_data="card_payment")
|
|
||||||
]
|
|
||||||
])
|
|
||||||
question_text = questions[question_id]
|
|
||||||
await bot.send_message(user_id, text=question_text, reply_markup=keyboard)
|
|
||||||
else:
|
|
||||||
question_text = questions[question_id]
|
|
||||||
await bot.send_message(user_id, text=question_text, reply_markup=confirm_keyboard)
|
|
||||||
|
|
||||||
|
|
||||||
# Обработчик callback-кнопок
|
|
||||||
@dp.callback_query_handler(lambda query: query.data in ['wet_cleaning', 'dry_cleaning', 'morning_time', 'day_time', 'evening_time', 'cash_payment', 'card_payment'])
|
|
||||||
async def handle_callback_answer(query: types.CallbackQuery):
|
|
||||||
answer = {
|
|
||||||
'wet_cleaning': 'Влажная уборка',
|
|
||||||
'dry_cleaning': 'Сухая уборка',
|
|
||||||
'morning_time': 'Утро',
|
|
||||||
'day_time': 'День',
|
|
||||||
'evening_time': 'Вечер',
|
|
||||||
'cash_payment': 'Наличные',
|
|
||||||
'card_payment': 'Карта'
|
|
||||||
}
|
|
||||||
await save_answer(query.from_user.id, answer[query.data])
|
|
||||||
await ask_question(query.from_user.id, query.message.message_id + 1)
|
|
||||||
|
|
||||||
# Функция для сохранения ответа в базе данных
|
|
||||||
async def save_answer(user_id, answer):
|
|
||||||
cursor.execute("INSERT INTO answers (user_id, question_id, answer) VALUES (?, ?, ?)", (user_id, cursor.rowcount + 1, answer))
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
# Обработчик ответов с текстовым полем
|
|
||||||
@dp.message_handler(lambda message: message.text != 'Подтвердить')
|
|
||||||
async def handle_text_answer(message: types.Message):
|
|
||||||
user_id = message.chat.id
|
|
||||||
cursor.execute("SELECT MAX(question_id) FROM answers WHERE user_id=?", (user_id,))
|
|
||||||
prev_question_id = cursor.fetchone()[0]
|
|
||||||
|
|
||||||
if prev_question_id is None:
|
|
||||||
question_id = 1
|
|
||||||
else:
|
|
||||||
question_id = prev_question_id + 1
|
|
||||||
answer = message.text
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO answers (user_id, question_id, answer) VALUES (?, ?, ?)",
|
|
||||||
(user_id, question_id, answer))
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
if question_id < 6:
|
|
||||||
await ask_question(user_id, question_id + 1)
|
|
||||||
else:
|
|
||||||
await bot.send_message(user_id, "Ответы записаны. Подтверди перед отправкой.", reply_markup=confirm_keyboard)
|
|
||||||
|
|
||||||
|
|
||||||
# Обработчик ответов с inline кнопкой
|
|
||||||
@dp.callback_query_handler()
|
|
||||||
async def handle_callback_answer(query: types.CallbackQuery):
|
|
||||||
user_id = query.from_user.id
|
|
||||||
answer = query.data
|
|
||||||
|
|
||||||
cursor.execute("SELECT MAX(question_id) FROM answers WHERE user_id=?", (user_id,))
|
|
||||||
prev_question_id = cursor.fetchone()[0]
|
|
||||||
|
|
||||||
if prev_question_id is None:
|
|
||||||
question_id = 1
|
|
||||||
else:
|
|
||||||
question_id = prev_question_id + 1
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO answers (user_id, question_id, answer) VALUES (?, ?, ?)",
|
|
||||||
(user_id, question_id, answer))
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
if question_id < 6:
|
|
||||||
await ask_question(user_id, question_id + 1)
|
|
||||||
else:
|
|
||||||
await bot.send_message(user_id, "Ответы записаны. Подтверди перед отправкой.", reply_markup=confirm_keyboard)
|
|
||||||
# Функция для подтверждения ответов и отправки в группу
|
|
||||||
@dp.message_handler(lambda message: message.text == 'Подтвердить')
|
|
||||||
async def confirm_answers(message: types.Message):
|
|
||||||
user_id = message.chat.id
|
|
||||||
cursor.execute("SELECT * FROM answers WHERE user_id=?", (user_id,))
|
|
||||||
answers = cursor.fetchall()
|
|
||||||
|
|
||||||
if answers:
|
|
||||||
group_id = GROUP_ID # Заменить на ID вашей группы
|
|
||||||
answer_text = '\n'.join([f"{questions[ans[1]]}: {ans[2]}" for ans in answers])
|
|
||||||
|
|
||||||
# Очищаем таблицу с ответами
|
|
||||||
cursor.execute("DELETE FROM answers WHERE user_id=?", (user_id,))
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
# Отправляем ответы в группу с помощью реплая
|
|
||||||
sent_message = await bot.send_message(group_id, answer_text)
|
|
||||||
await bot.send_message(user_id,
|
|
||||||
f"Ответы отправлены в группу. Можете посмотреть их [здесь](https://t.me/{sent_message.chat.username}/{sent_message.message_id})",
|
|
||||||
parse_mode='Markdown')
|
|
||||||
else:
|
|
||||||
await bot.send_message(user_id, "Ответов нет")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
loop = asyncio.get_event_loop()
|
create_tables()
|
||||||
try:
|
register_handlers(dp, OPERATORS_GROUP_ID)
|
||||||
loop.create_task(dp.start_polling())
|
executor.start_polling(dp, skip_updates=True)
|
||||||
loop.run_forever()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
|
|||||||
Binary file not shown.
103
old/bot(OLD).py
Normal file
103
old/bot(OLD).py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import os
|
||||||
|
import logging
|
||||||
|
from aiogram import Bot, Dispatcher, types
|
||||||
|
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
from aiogram.utils import executor
|
||||||
|
from aiogram.dispatcher.filters import Text
|
||||||
|
from database import create_tables
|
||||||
|
from logger import log_action
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Загрузка переменных окружения из .env файла
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
API_TOKEN = os.getenv('BOT_API_TOKEN')
|
||||||
|
OPERATORS_GROUP_ID = os.getenv('OPERATORS_GROUP_ID')
|
||||||
|
ADMIN_GROUP_ID = os.getenv('ADMIN_GROUP_ID')
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
bot = Bot(token=API_TOKEN)
|
||||||
|
dp = Dispatcher(bot)
|
||||||
|
dp.middleware.setup(LoggingMiddleware())
|
||||||
|
|
||||||
|
# Inline клавиатуры
|
||||||
|
def main_menu_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Учетные данные', callback_data='account_data'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Сделать заказ', callback_data='make_order'))
|
||||||
|
keyboard.add(InlineKeyboardButton('История заказов', callback_data='order_history'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Заказать звонок', callback_data='request_call'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Начать разговор с оператором', callback_data='talk_operator'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
def account_data_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Изменить ФИО', callback_data='change_name'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Изменить номер телефона', callback_data='change_phone'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Добавить адрес', callback_data='add_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Удалить адрес', callback_data='delete_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Поделиться контактом', callback_data='share_contact'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Назад', callback_data='back_to_main'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
def order_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Добавить учетные данные', callback_data='add_account_data'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Выбрать адрес', callback_data='select_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Выбрать время для уборки', callback_data='select_time'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Выбрать тип уборки', callback_data='select_cleaning_type'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Выбрать способ оплаты', callback_data='select_payment_method'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Подтвердить заказ', callback_data='confirm_order'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Назад', callback_data='back_to_main'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
# Обработчики команд
|
||||||
|
@dp.message_handler(commands=['start'])
|
||||||
|
async def send_welcome(message: types.Message):
|
||||||
|
await message.answer("Добро пожаловать в BOTKlining!", reply_markup=main_menu_keyboard())
|
||||||
|
log_action(message.from_user.id, 'start')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'account_data')
|
||||||
|
async def process_account_data(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Учетные данные:", reply_markup=account_data_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'account_data')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'make_order')
|
||||||
|
async def process_make_order(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Сделать заказ:", reply_markup=order_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'make_order')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'order_history')
|
||||||
|
async def process_order_history(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для просмотра истории заказов
|
||||||
|
await bot.send_message(callback_query.from_user.id, "История заказов:")
|
||||||
|
log_action(callback_query.from_user.id, 'order_history')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'request_call')
|
||||||
|
async def process_request_call(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для заказа звонка
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Заказ звонка оформлен. Ожидайте звонок в течение 30 минут.")
|
||||||
|
log_action(callback_query.from_user.id, 'request_call')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'talk_operator')
|
||||||
|
async def process_talk_operator(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для начала разговора с оператором
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Разговор с оператором начат.")
|
||||||
|
log_action(callback_query.from_user.id, 'talk_operator')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'back_to_main')
|
||||||
|
async def process_back_to_main(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Главное меню:", reply_markup=main_menu_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'back_to_main')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
create_tables()
|
||||||
|
executor.start_polling(dp, skip_updates=True)
|
||||||
254
old/bot.py
Normal file
254
old/bot.py
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
|
from aiogram import types
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
from aiogram.dispatcher import FSMContext
|
||||||
|
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||||
|
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
||||||
|
from aiogram.utils import executor
|
||||||
|
from aiogram import Bot, Dispatcher
|
||||||
|
from aiogram.dispatcher.filters import Text
|
||||||
|
from database import create_tables, add_user, update_user_name, update_user_phone, add_address, delete_address
|
||||||
|
from logger import log_action
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Загрузка переменных окружения из .env файла
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
API_TOKEN = os.getenv('BOT_API_TOKEN')
|
||||||
|
OPERATORS_GROUP_ID = int(os.getenv('OPERATORS_GROUP_ID'))
|
||||||
|
ADMIN_GROUP_ID = int(os.getenv('ADMIN_GROUP_ID'))
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
bot = Bot(token=API_TOKEN)
|
||||||
|
dp = Dispatcher(bot)
|
||||||
|
dp.middleware.setup(LoggingMiddleware())
|
||||||
|
|
||||||
|
# Состояния
|
||||||
|
class OrderForm(StatesGroup):
|
||||||
|
waiting_for_name = State()
|
||||||
|
waiting_for_phone = State()
|
||||||
|
waiting_for_address = State()
|
||||||
|
waiting_for_cleaning_time = State()
|
||||||
|
waiting_for_cleaning_type = State()
|
||||||
|
waiting_for_payment_method = State()
|
||||||
|
confirmation = State()
|
||||||
|
|
||||||
|
class CallRequest(StatesGroup):
|
||||||
|
waiting_for_name = State()
|
||||||
|
waiting_for_phone = State()
|
||||||
|
|
||||||
|
class OperatorChat(StatesGroup):
|
||||||
|
in_chat = State()
|
||||||
|
|
||||||
|
# Inline клавиатуры
|
||||||
|
def main_menu_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Учетные данные', callback_data='account_data'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Сделать заказ', callback_data='make_order'))
|
||||||
|
keyboard.add(InlineKeyboardButton('История заказов', callback_data='order_history'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Заказать звонок', callback_data='request_call'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Начать разговор с оператором', callback_data='talk_operator'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
def account_data_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Изменить ФИО', callback_data='change_name'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Изменить номер телефона', callback_data='change_phone'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Добавить адрес', callback_data='add_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Удалить адрес', callback_data='delete_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Поделиться контактом', callback_data='share_contact'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Назад', callback_data='back_to_main'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
def order_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Добавить учетные данные', callback_data='add_account_data'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Выбрать адрес', callback_data='select_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Выбрать время для уборки', callback_data='select_time'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Выбрать тип уборки', callback_data='select_cleaning_type'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Выбрать способ оплаты', callback_data='select_payment_method'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Подтвердить заказ', callback_data='confirm_order'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Назад', callback_data='back_to_main'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
# Основные команды
|
||||||
|
@dp.message_handler(commands=['start'])
|
||||||
|
async def send_welcome(message: types.Message):
|
||||||
|
await message.answer("Добро пожаловать в BOTKlining!", reply_markup=main_menu_keyboard())
|
||||||
|
log_action(message.from_user.id, 'start')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'account_data')
|
||||||
|
async def process_account_data(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Учетные данные:", reply_markup=account_data_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'account_data')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'make_order')
|
||||||
|
async def process_make_order(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Сделать заказ:", reply_markup=order_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'make_order')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'order_history')
|
||||||
|
async def process_order_history(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для просмотра истории заказов
|
||||||
|
await bot.send_message(callback_query.from_user.id, "История заказов:")
|
||||||
|
log_action(callback_query.from_user.id, 'order_history')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'request_call')
|
||||||
|
async def process_request_call(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для заказа звонка
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Заказ звонка оформлен. Ожидайте звонок в течение 30 минут.")
|
||||||
|
log_action(callback_query.from_user.id, 'request_call')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'talk_operator')
|
||||||
|
async def process_talk_operator(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для начала разговора с оператором
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Разговор с оператором начат.")
|
||||||
|
log_action(callback_query.from_user.id, 'talk_operator')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'back_to_main')
|
||||||
|
async def process_back_to_main(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Главное меню:", reply_markup=main_menu_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'back_to_main')
|
||||||
|
|
||||||
|
# Добавление учетных данных
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'add_account_data')
|
||||||
|
async def process_add_account_data(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Введите ваше ФИО:")
|
||||||
|
await OrderForm.waiting_for_name.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_name, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_name(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['name'] = message.text
|
||||||
|
await message.answer("Введите ваш номер телефона:")
|
||||||
|
await OrderForm.waiting_for_phone.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_phone, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_phone(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['phone'] = message.text
|
||||||
|
user_id = message.from_user.id
|
||||||
|
name = data['name']
|
||||||
|
phone = data['phone']
|
||||||
|
add_user(user_id, name, phone)
|
||||||
|
await message.answer("Ваши данные успешно сохранены!")
|
||||||
|
await state.finish()
|
||||||
|
|
||||||
|
# Изменение учетных данных
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'change_name')
|
||||||
|
async def process_change_name(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Введите новое ФИО:")
|
||||||
|
await OrderForm.waiting_for_name.set()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'change_phone')
|
||||||
|
async def process_change_phone(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Введите новый номер телефона:")
|
||||||
|
await OrderForm.waiting_for_phone.set()
|
||||||
|
|
||||||
|
# Добавление адреса
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'add_address')
|
||||||
|
async def process_add_address(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Введите адрес для добавления:")
|
||||||
|
await OrderForm.waiting_for_address.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_address, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_add_address_step(message: types.Message, state: FSMContext):
|
||||||
|
user_id = message.from_user.id
|
||||||
|
address = message.text
|
||||||
|
add_address(user_id, address)
|
||||||
|
await message.answer("Адрес успешно добавлен!")
|
||||||
|
await state.finish()
|
||||||
|
|
||||||
|
# Удаление адреса
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'delete_address')
|
||||||
|
async def process_delete_address(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Введите адрес для удаления:")
|
||||||
|
await OrderForm.waiting_for_address.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_address, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_delete_address_step(message: types.Message, state: FSMContext):
|
||||||
|
user_id = message.from_user.id
|
||||||
|
address = message.text
|
||||||
|
delete_address(user_id, address)
|
||||||
|
await message.answer("Адрес успешно удален!")
|
||||||
|
await state.finish()
|
||||||
|
|
||||||
|
# Обработка заказа
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'select_address')
|
||||||
|
async def process_select_address(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Введите адрес для уборки:")
|
||||||
|
await OrderForm.waiting_for_address.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_address, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_order_address(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['address'] = message.text
|
||||||
|
await message.answer("Выберите время для уборки (утро/день/вечер):")
|
||||||
|
await OrderForm.waiting_for_cleaning_time.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_cleaning_time, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_cleaning_time(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['cleaning_time'] = message.text
|
||||||
|
await message.answer("Выберите тип уборки (влажная/сухая/генеральная):")
|
||||||
|
await OrderForm.waiting_for_cleaning_type.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_cleaning_type, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_cleaning_type(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['cleaning_type'] = message.text
|
||||||
|
await message.answer("Выберите способ оплаты (картой/наличными):")
|
||||||
|
await OrderForm.waiting_for_payment_method.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_payment_method, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_payment_method(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['payment_method'] = message.text
|
||||||
|
|
||||||
|
# Отправка подтверждения заказа
|
||||||
|
await message.answer("Подтвердите заказ:\n"
|
||||||
|
f"Адрес: {data['address']}\n"
|
||||||
|
f"Время уборки: {data['cleaning_time']}\n"
|
||||||
|
f"Тип уборки: {data['cleaning_type']}\n"
|
||||||
|
f"Способ оплаты: {data['payment_method']}\n"
|
||||||
|
"Если все верно, нажмите 'Подтвердить'. В противном случае, измените нужные данные.",
|
||||||
|
reply_markup=InlineKeyboardMarkup().add(InlineKeyboardButton('Подтвердить', callback_data='confirm_order')))
|
||||||
|
await OrderForm.confirmation.set()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'confirm_order', state=OrderForm.confirmation)
|
||||||
|
async def process_confirm_order(callback_query: types.CallbackQuery, state: FSMContext):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
async with state.proxy() as data:
|
||||||
|
order_details = (f"Новый заказ:\n"
|
||||||
|
f"ФИО: {data['name']}\n"
|
||||||
|
f"Номер телефона: {data['phone']}\n"
|
||||||
|
f"Адрес: {data['address']}\n"
|
||||||
|
f"Время уборки: {data['cleaning_time']}\n"
|
||||||
|
f"Тип уборки: {data['cleaning_type']}\n"
|
||||||
|
f"Способ оплаты: {data['payment_method']}")
|
||||||
|
|
||||||
|
await bot.send_message(OPERATORS_GROUP_ID, order_details)
|
||||||
|
log_action(callback_query.from_user.id, 'confirm_order')
|
||||||
|
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Ваш заказ был подтвержден и отправлен операторам.")
|
||||||
|
await state.finish()
|
||||||
|
|
||||||
|
# Основное приложение
|
||||||
|
if __name__ == '__main__':
|
||||||
|
create_tables()
|
||||||
|
executor.start_polling(dp, skip_updates=True)
|
||||||
89
old/database.py
Normal file
89
old/database.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
|
||||||
|
def create_tables():
|
||||||
|
conn = sqlite3.connect('bot_klining.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
telegram_id INTEGER UNIQUE,
|
||||||
|
name TEXT,
|
||||||
|
phone TEXT
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS addresses (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
user_id INTEGER,
|
||||||
|
address TEXT,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS orders (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
user_id INTEGER,
|
||||||
|
address TEXT,
|
||||||
|
cleaning_time TEXT,
|
||||||
|
cleaning_type TEXT,
|
||||||
|
payment_method TEXT,
|
||||||
|
order_id TEXT UNIQUE,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS logs (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
user_id INTEGER,
|
||||||
|
action TEXT,
|
||||||
|
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def add_user(telegram_id, name, phone):
|
||||||
|
conn = sqlite3.connect('bot_klining.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('INSERT OR IGNORE INTO users (telegram_id, name, phone) VALUES (?, ?, ?)', (telegram_id, name, phone))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def update_user_name(telegram_id, name):
|
||||||
|
conn = sqlite3.connect('bot_klining.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('UPDATE users SET name = ? WHERE telegram_id = ?', (name, telegram_id))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def update_user_phone(telegram_id, phone):
|
||||||
|
conn = sqlite3.connect('bot_klining.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('UPDATE users SET phone = ? WHERE telegram_id = ?', (phone, telegram_id))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def add_address(telegram_id, address):
|
||||||
|
conn = sqlite3.connect('bot_klining.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('SELECT id FROM users WHERE telegram_id = ?', (telegram_id,))
|
||||||
|
user_id = cursor.fetchone()[0]
|
||||||
|
cursor.execute('INSERT INTO addresses (user_id, address) VALUES (?, ?)', (user_id, address))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def delete_address(telegram_id, address):
|
||||||
|
conn = sqlite3.connect('bot_klining.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('SELECT id FROM users WHERE telegram_id = ?', (telegram_id,))
|
||||||
|
user_id = cursor.fetchone()[0]
|
||||||
|
cursor.execute('DELETE FROM addresses WHERE user_id = ? AND address = ?', (user_id, address))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
183
old/handlers.py
Normal file
183
old/handlers.py
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
|
from aiogram import types
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
from aiogram.dispatcher import FSMContext
|
||||||
|
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||||
|
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
||||||
|
from aiogram.utils import executor
|
||||||
|
from aiogram import Bot, Dispatcher
|
||||||
|
from aiogram.dispatcher.filters import Text
|
||||||
|
from database import create_tables, add_user, update_user_name, update_user_phone, add_address, delete_address, add_order
|
||||||
|
from logger import log_action
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Загрузка переменных окружения из .env файла
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
API_TOKEN = os.getenv('BOT_API_TOKEN')
|
||||||
|
OPERATORS_GROUP_ID = int(os.getenv('OPERATORS_GROUP_ID'))
|
||||||
|
ADMIN_GROUP_ID = int(os.getenv('ADMIN_GROUP_ID'))
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
bot = Bot(token=API_TOKEN)
|
||||||
|
dp = Dispatcher(bot)
|
||||||
|
dp.middleware.setup(LoggingMiddleware())
|
||||||
|
|
||||||
|
# Состояния для заказа
|
||||||
|
class OrderForm(StatesGroup):
|
||||||
|
waiting_for_name = State()
|
||||||
|
waiting_for_phone = State()
|
||||||
|
waiting_for_address = State()
|
||||||
|
waiting_for_cleaning_time = State()
|
||||||
|
waiting_for_cleaning_type = State()
|
||||||
|
waiting_for_payment_method = State()
|
||||||
|
confirmation = State()
|
||||||
|
|
||||||
|
# Inline клавиатуры
|
||||||
|
def main_menu_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Учетные данные', callback_data='account_data'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Сделать заказ', callback_data='make_order'))
|
||||||
|
keyboard.add(InlineKeyboardButton('История заказов', callback_data='order_history'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Заказать звонок', callback_data='request_call'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Начать разговор с оператором', callback_data='talk_operator'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
def account_data_keyboard():
|
||||||
|
keyboard = InlineKeyboardMarkup()
|
||||||
|
keyboard.add(InlineKeyboardButton('Изменить ФИО', callback_data='change_name'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Изменить номер телефона', callback_data='change_phone'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Добавить адрес', callback_data='add_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Удалить адрес', callback_data='delete_address'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Поделиться контактом', callback_data='share_contact'))
|
||||||
|
keyboard.add(InlineKeyboardButton('Назад', callback_data='back_to_main'))
|
||||||
|
return keyboard
|
||||||
|
|
||||||
|
# Основные команды
|
||||||
|
@dp.message_handler(commands=['start'])
|
||||||
|
async def send_welcome(message: types.Message):
|
||||||
|
await message.answer("Добро пожаловать в BOTKlining!", reply_markup=main_menu_keyboard())
|
||||||
|
log_action(message.from_user.id, 'start')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'account_data')
|
||||||
|
async def process_account_data(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Учетные данные:", reply_markup=account_data_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'account_data')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'make_order')
|
||||||
|
async def process_make_order(callback_query: types.CallbackQuery, state: FSMContext):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Начнем с ваших учетных данных. Введите ваше ФИО:")
|
||||||
|
await OrderForm.waiting_for_name.set()
|
||||||
|
log_action(callback_query.from_user.id, 'make_order')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'order_history')
|
||||||
|
async def process_order_history(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для просмотра истории заказов
|
||||||
|
await bot.send_message(callback_query.from_user.id, "История заказов:")
|
||||||
|
log_action(callback_query.from_user.id, 'order_history')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'request_call')
|
||||||
|
async def process_request_call(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для заказа звонка
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Заказ звонка оформлен. Ожидайте звонок в течение 30 минут.")
|
||||||
|
log_action(callback_query.from_user.id, 'request_call')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'talk_operator')
|
||||||
|
async def process_talk_operator(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
# Добавьте логику для начала разговора с оператором
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Разговор с оператором начат.")
|
||||||
|
log_action(callback_query.from_user.id, 'talk_operator')
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'back_to_main')
|
||||||
|
async def process_back_to_main(callback_query: types.CallbackQuery):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Главное меню:", reply_markup=main_menu_keyboard())
|
||||||
|
log_action(callback_query.from_user.id, 'back_to_main')
|
||||||
|
|
||||||
|
# Обработка шагов заказа
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_name, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_name(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['name'] = message.text
|
||||||
|
await message.answer("Введите ваш номер телефона:")
|
||||||
|
await OrderForm.waiting_for_phone.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_phone, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_phone(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['phone'] = message.text
|
||||||
|
await message.answer("Введите адрес для уборки:")
|
||||||
|
await OrderForm.waiting_for_address.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_address, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_order_address(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['address'] = message.text
|
||||||
|
await message.answer("Выберите время для уборки (утро/день/вечер):")
|
||||||
|
await OrderForm.waiting_for_cleaning_time.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_cleaning_time, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_cleaning_time(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['cleaning_time'] = message.text
|
||||||
|
await message.answer("Выберите тип уборки (влажная/сухая/генеральная):")
|
||||||
|
await OrderForm.waiting_for_cleaning_type.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_cleaning_type, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_cleaning_type(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['cleaning_type'] = message.text
|
||||||
|
await message.answer("Выберите способ оплаты (картой/наличными):")
|
||||||
|
await OrderForm.waiting_for_payment_method.set()
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.waiting_for_payment_method, content_types=types.ContentTypes.TEXT)
|
||||||
|
async def process_payment_method(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['payment_method'] = message.text
|
||||||
|
|
||||||
|
# Отправка подтверждения заказа
|
||||||
|
await message.answer("Подтвердите заказ:\n"
|
||||||
|
f"ФИО: {data['name']}\n"
|
||||||
|
f"Номер телефона: {data['phone']}\n"
|
||||||
|
f"Адрес: {data['address']}\n"
|
||||||
|
f"Время уборки: {data['cleaning_time']}\n"
|
||||||
|
f"Тип уборки: {data['cleaning_type']}\n"
|
||||||
|
f"Способ оплаты: {data['payment_method']}\n"
|
||||||
|
"Если все верно, нажмите 'Подтвердить'. В противном случае, измените нужные данные.",
|
||||||
|
reply_markup=InlineKeyboardMarkup().add(InlineKeyboardButton('Подтвердить', callback_data='confirm_order')))
|
||||||
|
await OrderForm.confirmation.set()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == 'confirm_order', state=OrderForm.confirmation)
|
||||||
|
async def process_confirm_order(callback_query: types.CallbackQuery, state: FSMContext):
|
||||||
|
await bot.answer_callback_query(callback_query.id)
|
||||||
|
async with state.proxy() as data:
|
||||||
|
order_details = (f"Новый заказ:\n"
|
||||||
|
f"ФИО: {data['name']}\n"
|
||||||
|
f"Номер телефона: {data['phone']}\n"
|
||||||
|
f"Адрес: {data['address']}\n"
|
||||||
|
f"Время уборки: {data['cleaning_time']}\n"
|
||||||
|
f"Тип уборки: {data['cleaning_type']}\n"
|
||||||
|
f"Способ оплаты: {data['payment_method']}")
|
||||||
|
|
||||||
|
# Отправка заказа операторам
|
||||||
|
await bot.send_message(OPERATORS_GROUP_ID, order_details)
|
||||||
|
log_action(callback_query.from_user.id, 'confirm_order')
|
||||||
|
|
||||||
|
# Сохранение заказа в базе данных
|
||||||
|
add_order(data['name'], data['phone'], data['address'], data['cleaning_time'], data['cleaning_type'], data['payment_method'])
|
||||||
|
|
||||||
|
await bot.send_message(callback_query.from_user.id, "Ваш заказ был подтвержден и отправлен операторам.")
|
||||||
|
await state.finish()
|
||||||
|
|
||||||
|
# Основное приложение
|
||||||
|
if __name__ == '__main__':
|
||||||
|
create_tables()
|
||||||
|
executor.start_polling(dp, skip_updates=True)
|
||||||
185
old/klining_order.py
Normal file
185
old/klining_order.py
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
|
import asyncio
|
||||||
|
from aiogram import Bot, Dispatcher, types
|
||||||
|
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
|
# Устанавливаем уровень логов
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
# Подключаемся к базе данных SQLite
|
||||||
|
conn = sqlite3.connect("answers.db")
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Создание таблицы для хранения ответов
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS answers (
|
||||||
|
user_id INTEGER,
|
||||||
|
question_id INTEGER,
|
||||||
|
answer TEXT
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Заменить на свой токен
|
||||||
|
API_TOKEN = '7472030348:AAGI53nX-ON-WBmEhd_qBC6EnZsHOqp_2kE'
|
||||||
|
GROUP_ID = '-1001961537659'
|
||||||
|
|
||||||
|
# Инициализация бота и диспетчера
|
||||||
|
bot = Bot(token=API_TOKEN)
|
||||||
|
dp = Dispatcher(bot)
|
||||||
|
dp.middleware.setup(LoggingMiddleware())
|
||||||
|
|
||||||
|
# Словарь для хранения вопросов и ответов
|
||||||
|
questions = {
|
||||||
|
1: "Как вас зовут?",
|
||||||
|
2: "Укажите номер телефона для связи",
|
||||||
|
3: "Укажите район, улицу, дом",
|
||||||
|
4: "Какая уборка нужна, влажная или сухая?",
|
||||||
|
5: "На какое время?",
|
||||||
|
6: "Оплата наличными или картой?"
|
||||||
|
}
|
||||||
|
|
||||||
|
answer_map = {
|
||||||
|
'wet_cleaning': 'Влажная уборка',
|
||||||
|
'dry_cleaning': 'Сухая уборка',
|
||||||
|
'morning_time': 'Утро',
|
||||||
|
'day_time': 'День',
|
||||||
|
'evening_time': 'Вечер',
|
||||||
|
'cash_payment': 'Наличные',
|
||||||
|
'card_payment': 'Карта'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Обработчик команды /start
|
||||||
|
@dp.message_handler(commands=['start'])
|
||||||
|
async def start(message: types.Message):
|
||||||
|
await message.answer("Привет! Я задам тебе 6 вопросов. Давай начнем.")
|
||||||
|
await ask_question(message.chat.id, 1)
|
||||||
|
|
||||||
|
# Функция для задания вопроса
|
||||||
|
async def ask_question(user_id, question_id):
|
||||||
|
if question_id in [4, 5, 6]:
|
||||||
|
if question_id == 4:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Влажная", callback_data="wet_cleaning")],
|
||||||
|
[InlineKeyboardButton(text="Сухая", callback_data="dry_cleaning")]
|
||||||
|
])
|
||||||
|
elif question_id == 5:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Утро", callback_data="morning_time")],
|
||||||
|
[InlineKeyboardButton(text="День", callback_data="day_time")],
|
||||||
|
[InlineKeyboardButton(text="Вечер", callback_data="evening_time")]
|
||||||
|
])
|
||||||
|
elif question_id == 6:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Наличные", callback_data="cash_payment")],
|
||||||
|
[InlineKeyboardButton(text="Карта", callback_data="card_payment")]
|
||||||
|
])
|
||||||
|
await bot.send_message(user_id, text=questions[question_id], reply_markup=keyboard)
|
||||||
|
else:
|
||||||
|
await bot.send_message(user_id, text=questions[question_id])
|
||||||
|
|
||||||
|
# Обработчик текстовых ответов на первые три вопроса
|
||||||
|
@dp.message_handler(lambda message: message.text not in ["Переписать", "Отправить"])
|
||||||
|
async def handle_text_answer(message: types.Message):
|
||||||
|
user_id = message.chat.id
|
||||||
|
cursor.execute("SELECT MAX(question_id) FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
prev_question_id = cursor.fetchone()[0]
|
||||||
|
|
||||||
|
if prev_question_id is None:
|
||||||
|
question_id = 1
|
||||||
|
else:
|
||||||
|
question_id = prev_question_id + 1
|
||||||
|
answer = message.text
|
||||||
|
|
||||||
|
await save_answer(user_id, question_id, answer)
|
||||||
|
|
||||||
|
if question_id < 6:
|
||||||
|
await ask_question(user_id, question_id + 1)
|
||||||
|
else:
|
||||||
|
await show_confirmation_options(user_id)
|
||||||
|
|
||||||
|
# Обработчик inline-кнопок
|
||||||
|
@dp.callback_query_handler(lambda query: query.data in answer_map.keys())
|
||||||
|
async def handle_callback_answer(query: types.CallbackQuery):
|
||||||
|
user_id = query.from_user.id
|
||||||
|
cursor.execute("SELECT MAX(question_id) FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
prev_question_id = cursor.fetchone()[0]
|
||||||
|
|
||||||
|
if prev_question_id is None:
|
||||||
|
question_id = 1
|
||||||
|
else:
|
||||||
|
question_id = prev_question_id + 1
|
||||||
|
|
||||||
|
await save_answer(user_id, question_id, answer_map[query.data])
|
||||||
|
await query.answer()
|
||||||
|
|
||||||
|
if question_id < 6:
|
||||||
|
await ask_question(user_id, question_id + 1)
|
||||||
|
else:
|
||||||
|
await show_confirmation_options(user_id)
|
||||||
|
|
||||||
|
# Функция для сохранения ответа в базе данных
|
||||||
|
async def save_answer(user_id, question_id, answer):
|
||||||
|
cursor.execute("INSERT INTO answers (user_id, question_id, answer) VALUES (?, ?, ?)", (user_id, question_id, answer))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Функция для отображения опций подтверждения
|
||||||
|
async def show_confirmation_options(user_id):
|
||||||
|
cursor.execute("SELECT answer FROM answers WHERE user_id=? ORDER BY question_id", (user_id,))
|
||||||
|
answers = cursor.fetchall()
|
||||||
|
answer_text = "\n".join([f"{questions[i+1]}: {answers[i][0]}" for i in range(6)])
|
||||||
|
await bot.send_message(user_id, text=f"Ваши ответы:\n\n{answer_text}")
|
||||||
|
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Отправить", callback_data="send_answers")],
|
||||||
|
[InlineKeyboardButton(text="Переписать", callback_data="rewrite_answers")]
|
||||||
|
])
|
||||||
|
await bot.send_message(user_id, "Проверьте свои ответы. Выберите действие:", reply_markup=keyboard)
|
||||||
|
|
||||||
|
# Обработчик выбора действия подтверждения
|
||||||
|
@dp.callback_query_handler(lambda query: query.data in ['send_answers', 'rewrite_answers'])
|
||||||
|
async def handle_confirmation(query: types.CallbackQuery):
|
||||||
|
user_id = query.from_user.id
|
||||||
|
if query.data == "send_answers":
|
||||||
|
await send_answers_to_group(user_id)
|
||||||
|
elif query.data == "rewrite_answers":
|
||||||
|
await rewrite_answers(user_id)
|
||||||
|
|
||||||
|
# Функция для отправки ответов в группу
|
||||||
|
async def send_answers_to_group(user_id):
|
||||||
|
cursor.execute("SELECT * FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
answers = cursor.fetchall()
|
||||||
|
|
||||||
|
if answers:
|
||||||
|
answer_text = '\n'.join([f"{questions[ans[1]]}: {ans[2]}" for ans in answers])
|
||||||
|
|
||||||
|
# Очищаем таблицу с ответами
|
||||||
|
cursor.execute("DELETE FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Отправляем ответы в группу
|
||||||
|
await bot.send_message(GROUP_ID, answer_text)
|
||||||
|
await bot.send_message(user_id, "Ваши ответы отправлены.")
|
||||||
|
else:
|
||||||
|
await bot.send_message(user_id, "Ответов нет")
|
||||||
|
|
||||||
|
# Функция для переписывания ответов
|
||||||
|
async def rewrite_answers(user_id):
|
||||||
|
# Очищаем таблицу с ответами
|
||||||
|
cursor.execute("DELETE FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
await bot.send_message(user_id, "Ваши ответы удалены. Начнем сначала.")
|
||||||
|
await ask_question(user_id, 1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
try:
|
||||||
|
loop.create_task(dp.start_polling())
|
||||||
|
loop.run_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
17
old/logger.py
Normal file
17
old/logger.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
|
# Настройка логирования
|
||||||
|
logging.basicConfig(filename='bot.log', level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
|
|
||||||
|
def log_action(user_id, action, details=""):
|
||||||
|
logging.info(f"User ID: {user_id} - Action: {action} - Details: {details}")
|
||||||
|
|
||||||
|
|
||||||
|
def log_action(user_id, action):
|
||||||
|
conn = sqlite3.connect('bot_klining.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('INSERT INTO logs (user_id, action) VALUES ((SELECT id FROM users WHERE telegram_id = ?), ?)', (user_id, action))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
213
old/main(OLD).py
Normal file
213
old/main(OLD).py
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
|
import asyncio
|
||||||
|
from aiogram import Bot, Dispatcher, types
|
||||||
|
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
|
# Устанавливаем уровень логов
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
# Подключаемся к базе данных SQLite
|
||||||
|
conn = sqlite3.connect("answers.db")
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Создание таблицы для хранения ответов
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS answers (
|
||||||
|
user_id INTEGER,
|
||||||
|
question_id INTEGER,
|
||||||
|
answer TEXT
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Заменить на свой токен
|
||||||
|
API_TOKEN = '7472030348:AAGI53nX-ON-WBmEhd_qBC6EnZsHOqp_2kE'
|
||||||
|
GROUP_ID = '-1001961537659'
|
||||||
|
|
||||||
|
# Инициализация бота и диспетчера
|
||||||
|
bot = Bot(token=API_TOKEN)
|
||||||
|
dp = Dispatcher(bot)
|
||||||
|
dp.middleware.setup(LoggingMiddleware())
|
||||||
|
|
||||||
|
# Словарь для хранения вопросов и ответов
|
||||||
|
questions = {
|
||||||
|
1: "Как вас зовут?",
|
||||||
|
2: "Укажите номер телефона для связи",
|
||||||
|
3: "Укажите район, улицу, дом",
|
||||||
|
4: "Какая уборка нужна, влажная или сухая?",
|
||||||
|
5: "На какое время?",
|
||||||
|
6: "Оплата наличными или картой?"
|
||||||
|
}
|
||||||
|
|
||||||
|
answer_map = {
|
||||||
|
'wet_cleaning': 'Влажная уборка',
|
||||||
|
'dry_cleaning': 'Сухая уборка',
|
||||||
|
'morning_time': 'Утро',
|
||||||
|
'day_time': 'День',
|
||||||
|
'evening_time': 'Вечер',
|
||||||
|
'cash_payment': 'Наличные',
|
||||||
|
'card_payment': 'Карта'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Обработчик команды /start
|
||||||
|
@dp.message_handler(commands=['start'])
|
||||||
|
async def start(message: types.Message):
|
||||||
|
if message.chat.id != int(GROUP_ID):
|
||||||
|
await message.answer("Привет! Я задам тебе 6 вопросов. Давай начнем.")
|
||||||
|
await ask_question(message.chat.id, 1)
|
||||||
|
|
||||||
|
# Функция для задания вопроса
|
||||||
|
async def ask_question(user_id, question_id):
|
||||||
|
if question_id in [4, 5, 6]:
|
||||||
|
if question_id == 4:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Влажная", callback_data="wet_cleaning")],
|
||||||
|
[InlineKeyboardButton(text="Сухая", callback_data="dry_cleaning")]
|
||||||
|
])
|
||||||
|
elif question_id == 5:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Утро", callback_data="morning_time")],
|
||||||
|
[InlineKeyboardButton(text="День", callback_data="day_time")],
|
||||||
|
[InlineKeyboardButton(text="Вечер", callback_data="evening_time")]
|
||||||
|
])
|
||||||
|
elif question_id == 6:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Наличные", callback_data="cash_payment")],
|
||||||
|
[InlineKeyboardButton(text="Карта", callback_data="card_payment")]
|
||||||
|
])
|
||||||
|
await bot.send_message(user_id, text=questions[question_id], reply_markup=keyboard)
|
||||||
|
else:
|
||||||
|
await bot.send_message(user_id, text=questions[question_id])
|
||||||
|
|
||||||
|
# Обработчик текстовых ответов на первые три вопроса
|
||||||
|
@dp.message_handler(lambda message: message.text not in ["Переписать", "Отправить"])
|
||||||
|
async def handle_text_answer(message: types.Message):
|
||||||
|
if message.chat.id != int(GROUP_ID):
|
||||||
|
user_id = message.chat.id
|
||||||
|
cursor.execute("SELECT MAX(question_id) FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
prev_question_id = cursor.fetchone()[0]
|
||||||
|
|
||||||
|
if prev_question_id is None:
|
||||||
|
question_id = 1
|
||||||
|
else:
|
||||||
|
question_id = prev_question_id + 1
|
||||||
|
answer = message.text
|
||||||
|
|
||||||
|
await save_answer(user_id, question_id, answer)
|
||||||
|
|
||||||
|
if question_id < 6:
|
||||||
|
await ask_question(user_id, question_id + 1)
|
||||||
|
else:
|
||||||
|
await show_confirmation_options(user_id)
|
||||||
|
|
||||||
|
# Обработчик inline-кнопок
|
||||||
|
@dp.callback_query_handler(lambda query: query.data in answer_map.keys())
|
||||||
|
async def handle_callback_answer(query: types.CallbackQuery):
|
||||||
|
user_id = query.from_user.id
|
||||||
|
cursor.execute("SELECT MAX(question_id) FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
prev_question_id = cursor.fetchone()[0]
|
||||||
|
|
||||||
|
if prev_question_id is None:
|
||||||
|
question_id = 1
|
||||||
|
else:
|
||||||
|
question_id = prev_question_id + 1
|
||||||
|
|
||||||
|
await save_answer(user_id, question_id, answer_map[query.data])
|
||||||
|
await query.answer()
|
||||||
|
|
||||||
|
if question_id < 6:
|
||||||
|
await ask_question(user_id, question_id + 1)
|
||||||
|
else:
|
||||||
|
await show_confirmation_options(user_id)
|
||||||
|
|
||||||
|
# Функция для сохранения ответа в базе данных
|
||||||
|
async def save_answer(user_id, question_id, answer):
|
||||||
|
cursor.execute("INSERT INTO answers (user_id, question_id, answer) VALUES (?, ?, ?)", (user_id, question_id, answer))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Функция для отображения опций подтверждения
|
||||||
|
async def show_confirmation_options(user_id):
|
||||||
|
cursor.execute("SELECT answer FROM answers WHERE user_id=? ORDER BY question_id", (user_id,))
|
||||||
|
answers = cursor.fetchall()
|
||||||
|
answer_text = "\n".join([f"{questions[i+1]}: {answers[i][0]}" for i in range(6)])
|
||||||
|
await bot.send_message(user_id, text=f"Ваши ответы:\n\n{answer_text}")
|
||||||
|
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Отправить", callback_data="send_answers")],
|
||||||
|
[InlineKeyboardButton(text="Переписать", callback_data="rewrite_answers")]
|
||||||
|
])
|
||||||
|
await bot.send_message(user_id, "Проверьте свои ответы. Выберите действие:", reply_markup=keyboard)
|
||||||
|
|
||||||
|
# Обработчик выбора действия подтверждения
|
||||||
|
@dp.callback_query_handler(lambda query: query.data in ['send_answers', 'rewrite_answers'])
|
||||||
|
async def handle_confirmation(query: types.CallbackQuery):
|
||||||
|
user_id = query.from_user.id
|
||||||
|
if query.data == "send_answers":
|
||||||
|
await send_answers_to_group(user_id)
|
||||||
|
elif query.data == "rewrite_answers":
|
||||||
|
await rewrite_answers(user_id)
|
||||||
|
|
||||||
|
# Функция для отправки ответов в группу
|
||||||
|
async def send_answers_to_group(user_id):
|
||||||
|
cursor.execute("SELECT * FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
answers = cursor.fetchall()
|
||||||
|
|
||||||
|
if answers:
|
||||||
|
answer_text = '\n'.join([f"{questions[ans[1]]}: {ans[2]}" for ans in answers])
|
||||||
|
|
||||||
|
# Очищаем таблицу с ответами
|
||||||
|
cursor.execute("DELETE FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Отправляем ответы в группу и добавляем ID пользователя
|
||||||
|
sent_message = await bot.send_message(GROUP_ID, f"Ответы от пользователя {user_id}:\n\n{answer_text}")
|
||||||
|
await bot.send_message(user_id, f"Ваши ответы отправлены. Можете посмотреть их [здесь](https://t.me/{sent_message.chat.username}/{sent_message.message_id})",
|
||||||
|
parse_mode='Markdown')
|
||||||
|
else:
|
||||||
|
await bot.send_message(user_id, "Ответов нет")
|
||||||
|
|
||||||
|
# Функция для переписывания ответов
|
||||||
|
async def rewrite_answers(user_id):
|
||||||
|
# Очищаем таблицу с ответами
|
||||||
|
cursor.execute("DELETE FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
await bot.send_message(user_id, "Ваши ответы удалены. Начнем сначала.")
|
||||||
|
await ask_question(user_id, 1)
|
||||||
|
|
||||||
|
# Функция для обработки сообщений из группы и пересылки их пользователю
|
||||||
|
@dp.message_handler(lambda message: message.chat.id == int(GROUP_ID) and message.reply_to_message)
|
||||||
|
async def handle_group_reply(message: types.Message):
|
||||||
|
# Проверяем, что сообщение является ответом на сообщение бота
|
||||||
|
if message.reply_to_message.from_user.id == bot.id:
|
||||||
|
# Извлекаем ID пользователя из текста сообщения
|
||||||
|
try:
|
||||||
|
user_id = int(message.reply_to_message.text.split()[2].strip(':'))
|
||||||
|
await bot.send_message(user_id, f"Сообщение от администратора:\n\n{message.text}")
|
||||||
|
# Сохраняем ответ пользователя для пересылки обратно в группу
|
||||||
|
cursor.execute("INSERT INTO admin_user_conversation (user_id, admin_message_id) VALUES (?, ?)",
|
||||||
|
(user_id, message.message_id))
|
||||||
|
conn.commit()
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
await message.reply("Не удалось определить ID пользователя для ответа.")
|
||||||
|
|
||||||
|
# Обработчик сообщений от пользователя в ответ на администратора
|
||||||
|
@dp.message_handler(lambda message: message.chat.id != int(GROUP_ID))
|
||||||
|
async def handle_user_reply(message: types.Message):
|
||||||
|
user_id = message.chat.id
|
||||||
|
cursor.execute("SELECT admin_message_id FROM admin_user_conversation WHERE user_id=? ORDER BY admin_message_id DESC LIMIT 1", (user_id,))
|
||||||
|
admin_message_id = cursor.fetchone()
|
||||||
|
if admin_message_id:
|
||||||
|
await bot.send_message(GROUP_ID, f"Сообщение от пользователя {user_id}:\n\n{message.text}", reply_to_message_id=admin_message_id[0])
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
try:
|
||||||
|
loop.create_task(dp.start_polling())
|
||||||
|
loop.run_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
221
old/main.py
Normal file
221
old/main.py
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
|
import asyncio
|
||||||
|
from aiogram import Bot, Dispatcher, types
|
||||||
|
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
||||||
|
from aiogram.dispatcher.filters import Command
|
||||||
|
from aiogram.dispatcher import FSMContext
|
||||||
|
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||||
|
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
|
# Устанавливаем уровень логов
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
# Подключаемся к базе данных SQLite
|
||||||
|
conn = sqlite3.connect("answers.db")
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Создание таблицы для хранения ответов
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS answers (
|
||||||
|
user_id INTEGER,
|
||||||
|
question_id INTEGER,
|
||||||
|
answer TEXT
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Заменить на свой токен
|
||||||
|
API_TOKEN = '7472030348:AAGI53nX-ON-WBmEhd_qBC6EnZsHOqp_2kE'
|
||||||
|
GROUP_ID = '-1001961537659'
|
||||||
|
|
||||||
|
# Инициализация бота и диспетчера
|
||||||
|
bot = Bot(token=API_TOKEN)
|
||||||
|
dp = Dispatcher(bot)
|
||||||
|
dp.middleware.setup(LoggingMiddleware())
|
||||||
|
|
||||||
|
# Словарь для хранения вопросов и ответов
|
||||||
|
questions = {
|
||||||
|
1: "Как вас зовут?",
|
||||||
|
2: "Укажите номер телефона для связи",
|
||||||
|
3: "Укажите район, улицу, дом",
|
||||||
|
4: "Какая уборка нужна, влажная или сухая?",
|
||||||
|
5: "На какое время?",
|
||||||
|
6: "Оплата наличными или картой?"
|
||||||
|
}
|
||||||
|
|
||||||
|
answer_map = {
|
||||||
|
'wet_cleaning': 'Влажная уборка',
|
||||||
|
'dry_cleaning': 'Сухая уборка',
|
||||||
|
'morning_time': 'Утро',
|
||||||
|
'day_time': 'День',
|
||||||
|
'evening_time': 'Вечер',
|
||||||
|
'cash_payment': 'Наличные',
|
||||||
|
'card_payment': 'Карта'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Обработчик команды /start
|
||||||
|
@dp.message_handler(commands=['start'])
|
||||||
|
async def start(message: types.Message):
|
||||||
|
if message.chat.id != int(GROUP_ID):
|
||||||
|
await message.answer("Привет! Я задам тебе 6 вопросов Чтобы создать заказ. Давай начнем.")
|
||||||
|
await ask_question(message.chat.id, 1)
|
||||||
|
|
||||||
|
@dp.message_handler(Command("start"))
|
||||||
|
async def show_menu(message: types.Message):
|
||||||
|
await message.reply("Выбери действие:", reply_markup=ReplyKeyboardMarkup(
|
||||||
|
resize_keyboard=True).add(KeyboardButton("Создать заказ")))
|
||||||
|
|
||||||
|
# Функция для задания вопроса
|
||||||
|
async def ask_question(user_id, question_id):
|
||||||
|
if question_id in [4, 5, 6]:
|
||||||
|
if question_id == 4:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Влажная", callback_data="wet_cleaning")],
|
||||||
|
[InlineKeyboardButton(text="Сухая", callback_data="dry_cleaning")]
|
||||||
|
])
|
||||||
|
elif question_id == 5:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Утро", callback_data="morning_time")],
|
||||||
|
[InlineKeyboardButton(text="День", callback_data="day_time")],
|
||||||
|
[InlineKeyboardButton(text="Вечер", callback_data="evening_time")]
|
||||||
|
])
|
||||||
|
elif question_id == 6:
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Наличные", callback_data="cash_payment")],
|
||||||
|
[InlineKeyboardButton(text="Карта", callback_data="card_payment")]
|
||||||
|
])
|
||||||
|
await bot.send_message(user_id, text=questions[question_id], reply_markup=keyboard)
|
||||||
|
else:
|
||||||
|
await bot.send_message(user_id, text=questions[question_id])
|
||||||
|
|
||||||
|
# Обработчик текстовых ответов на первые три вопроса
|
||||||
|
@dp.message_handler(lambda message: message.text not in ["Переписать", "Отправить"])
|
||||||
|
async def handle_text_answer(message: types.Message):
|
||||||
|
if message.chat.id != int(GROUP_ID):
|
||||||
|
user_id = message.chat.id
|
||||||
|
cursor.execute("SELECT MAX(question_id) FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
prev_question_id = cursor.fetchone()[0]
|
||||||
|
|
||||||
|
if prev_question_id is None:
|
||||||
|
question_id = 1
|
||||||
|
else:
|
||||||
|
question_id = prev_question_id + 1
|
||||||
|
answer = message.text
|
||||||
|
|
||||||
|
await save_answer(user_id, question_id, answer)
|
||||||
|
|
||||||
|
if question_id < 6:
|
||||||
|
await ask_question(user_id, question_id + 1)
|
||||||
|
else:
|
||||||
|
await show_confirmation_options(user_id)
|
||||||
|
|
||||||
|
# Обработчик inline-кнопок
|
||||||
|
@dp.callback_query_handler(lambda query: query.data in answer_map.keys())
|
||||||
|
async def handle_callback_answer(query: types.CallbackQuery):
|
||||||
|
user_id = query.from_user.id
|
||||||
|
cursor.execute("SELECT MAX(question_id) FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
prev_question_id = cursor.fetchone()[0]
|
||||||
|
|
||||||
|
if prev_question_id is None:
|
||||||
|
question_id = 1
|
||||||
|
else:
|
||||||
|
question_id = prev_question_id + 1
|
||||||
|
|
||||||
|
await save_answer(user_id, question_id, answer_map[query.data])
|
||||||
|
await query.answer()
|
||||||
|
|
||||||
|
if question_id < 6:
|
||||||
|
await ask_question(user_id, question_id + 1)
|
||||||
|
else:
|
||||||
|
await show_confirmation_options(user_id)
|
||||||
|
|
||||||
|
# Функция для сохранения ответа в базе данных
|
||||||
|
async def save_answer(user_id, question_id, answer):
|
||||||
|
cursor.execute("INSERT INTO answers (user_id, question_id, answer) VALUES (?, ?, ?)", (user_id, question_id, answer))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Функция для отображения опций подтверждения
|
||||||
|
async def show_confirmation_options(user_id):
|
||||||
|
cursor.execute("SELECT answer FROM answers WHERE user_id=? ORDER BY question_id", (user_id,))
|
||||||
|
answers = cursor.fetchall()
|
||||||
|
answer_text = "\n".join([f"{questions[i+1]}: {answers[i][0]}" for i in range(6)])
|
||||||
|
await bot.send_message(user_id, text=f"Ваши ответы:\n\n{answer_text}")
|
||||||
|
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Отправить", callback_data="send_answers")],
|
||||||
|
[InlineKeyboardButton(text="Переписать", callback_data="rewrite_answers")]
|
||||||
|
])
|
||||||
|
await bot.send_message(user_id, "Проверьте свои ответы. Выберите действие:", reply_markup=keyboard)
|
||||||
|
|
||||||
|
# Обработчик выбора действия подтверждения
|
||||||
|
@dp.callback_query_handler(lambda query: query.data in ['send_answers', 'rewrite_answers'])
|
||||||
|
async def handle_confirmation(query: types.CallbackQuery):
|
||||||
|
user_id = query.from_user.id
|
||||||
|
if query.data == "send_answers":
|
||||||
|
await send_answers_to_group(user_id)
|
||||||
|
elif query.data == "rewrite_answers":
|
||||||
|
await rewrite_answers(user_id)
|
||||||
|
|
||||||
|
# Функция для отправки ответов в группу
|
||||||
|
async def send_answers_to_group(user_id):
|
||||||
|
cursor.execute("SELECT * FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
answers = cursor.fetchall()
|
||||||
|
|
||||||
|
if answers:
|
||||||
|
answer_text = '\n'.join([f"{questions[ans[1]]}: {ans[2]}" for ans in answers])
|
||||||
|
|
||||||
|
# Очищаем таблицу с ответами
|
||||||
|
cursor.execute("DELETE FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# Отправляем ответы в группу и добавляем ID пользователя
|
||||||
|
sent_message = await bot.send_message(GROUP_ID, f"Ответы от пользователя {user_id}:\n\n{answer_text}")
|
||||||
|
await bot.send_message(user_id, f"Ваши ответы отправлены. Оператор с вами свяжится)",
|
||||||
|
parse_mode='Markdown')
|
||||||
|
else:
|
||||||
|
await bot.send_message(user_id, "Ответов нет")
|
||||||
|
|
||||||
|
# Функция для переписывания ответов
|
||||||
|
async def rewrite_answers(user_id):
|
||||||
|
# Очищаем таблицу с ответами
|
||||||
|
cursor.execute("DELETE FROM answers WHERE user_id=?", (user_id,))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
await bot.send_message(user_id, "Ваши ответы удалены. Начнем сначала.")
|
||||||
|
await ask_question(user_id, 1)
|
||||||
|
|
||||||
|
# Функция для обработки сообщений из группы и пересылки их пользователю
|
||||||
|
@dp.message_handler(lambda message: message.chat.id == int(GROUP_ID) and message.reply_to_message)
|
||||||
|
async def handle_group_reply(message: types.Message):
|
||||||
|
# Проверяем, что сообщение является ответом на сообщение бота
|
||||||
|
if message.reply_to_message.from_user.id == bot.id:
|
||||||
|
# Извлекаем ID пользователя из текста сообщения
|
||||||
|
try:
|
||||||
|
user_id = int(message.reply_to_message.text.split()[2].strip(':'))
|
||||||
|
await bot.send_message(user_id, f"Сообщение от администратора:\n\n{message.text}")
|
||||||
|
# Сохраняем ответ пользователя для пересылки обратно в группу
|
||||||
|
cursor.execute("INSERT INTO admin_user_conversation (user_id, admin_message_id) VALUES (?, ?)",
|
||||||
|
(user_id, message.message_id))
|
||||||
|
conn.commit()
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
await message.reply("Не удалось определить ID пользователя для ответа.")
|
||||||
|
|
||||||
|
# Обработчик сообщений от пользователя в ответ на администратора
|
||||||
|
@dp.message_handler(lambda message: message.chat.id != int(GROUP_ID))
|
||||||
|
async def handle_user_reply(message: types.Message):
|
||||||
|
user_id = message.chat.id
|
||||||
|
cursor.execute("SELECT admin_message_id FROM admin_user_conversation WHERE user_id=? ORDER BY admin_message_id DESC LIMIT 1", (user_id,))
|
||||||
|
admin_message_id = cursor.fetchone()
|
||||||
|
if admin_message_id:
|
||||||
|
await bot.send_message(GROUP_ID, f"Сообщение от пользователя {user_id}:\n\n{message.text}", reply_to_message_id=admin_message_id[0])
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
try:
|
||||||
|
loop.create_task(dp.start_polling())
|
||||||
|
loop.run_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
76
old/remain.py
Normal file
76
old/remain.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import logging
|
||||||
|
from aiogram import Bot, Dispatcher, types
|
||||||
|
from aiogram.contrib.middlewares.logging import LoggingMiddleware
|
||||||
|
from aiogram.dispatcher import FSMContext
|
||||||
|
from aiogram.dispatcher.filters import Command
|
||||||
|
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||||
|
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
|
API_TOKEN = '7472030348:AAGI53nX-ON-WBmEhd_qBC6EnZsHOqp_2kE'
|
||||||
|
GROUP_ID = '-1001961537659'
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
bot = Bot(token=API_TOKEN)
|
||||||
|
dp = Dispatcher(bot)
|
||||||
|
dp.middleware.setup(LoggingMiddleware())
|
||||||
|
|
||||||
|
# Define states
|
||||||
|
class OrderForm(StatesGroup):
|
||||||
|
question_1 = State()
|
||||||
|
question_2 = State()
|
||||||
|
question_3 = State()
|
||||||
|
question_4 = State()
|
||||||
|
question_5 = State()
|
||||||
|
question_6 = State()
|
||||||
|
|
||||||
|
@dp.message_handler(Command("start"))
|
||||||
|
async def cmd_start(message: types.Message):
|
||||||
|
await message.reply("Привет! Чтобы создать заказ, нажми на кнопку 'Создать заказ' внизу.", reply_markup=ReplyKeyboardMarkup(
|
||||||
|
resize_keyboard=True).add(KeyboardButton("Создать заказ")))
|
||||||
|
|
||||||
|
@dp.message_handler(Command("menu"))
|
||||||
|
async def show_menu(message: types.Message):
|
||||||
|
await message.reply("Выбери действие:", reply_markup=ReplyKeyboardMarkup(
|
||||||
|
resize_keyboard=True).add(KeyboardButton("Создать заказ")))
|
||||||
|
|
||||||
|
@dp.message_handler(Command("create_order"))
|
||||||
|
async def cmd_create_order(message: types.Message):
|
||||||
|
await OrderForm.question_1.set()
|
||||||
|
await message.reply("Ответьте на первый вопрос:")
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.question_1)
|
||||||
|
async def process_question_1(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['question_1'] = message.text
|
||||||
|
await OrderForm.next()
|
||||||
|
await message.reply("Ответьте на второй вопрос:")
|
||||||
|
|
||||||
|
# Аналогично для остальных вопросов
|
||||||
|
|
||||||
|
@dp.message_handler(state=OrderForm.question_6)
|
||||||
|
async def process_question_6(message: types.Message, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
data['question_6'] = message.text
|
||||||
|
await message.reply("Отлично! Ваши ответы:")
|
||||||
|
async with state.proxy() as data:
|
||||||
|
for key, value in data.items():
|
||||||
|
await message.reply(f"{key}: {value}")
|
||||||
|
|
||||||
|
# Предложить отправить или переписать ответы
|
||||||
|
keyboard = InlineKeyboardMarkup().add(InlineKeyboardButton("Отправить", callback_data="send_order")).add(InlineKeyboardButton("Переписать", callback_data="rewrite_order"))
|
||||||
|
await message.reply("Хотите отправить эти ответы или переписать?", reply_markup=keyboard)
|
||||||
|
|
||||||
|
@dp.callback_query_handler(text="send_order", state="*")
|
||||||
|
async def send_order(callback_query: types.CallbackQuery, state: FSMContext):
|
||||||
|
async with state.proxy() as data:
|
||||||
|
for key, value in data.items():
|
||||||
|
await bot.send_message(callback_query.from_user.id, f"{key}: {value}")
|
||||||
|
|
||||||
|
@dp.callback_query_handler(text="rewrite_order", state="*")
|
||||||
|
async def rewrite_order(callback_query: types.CallbackQuery):
|
||||||
|
await cmd_create_order(callback_query.message)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from aiogram import executor
|
||||||
|
executor.start_polling(dp, skip_updates=True)
|
||||||
Reference in New Issue
Block a user