Spaces:
Sleeping
Sleeping
| import telebot | |
| from telebot import types | |
| from flask import Flask, request, jsonify, render_template_string | |
| import threading | |
| import json | |
| from datetime import datetime | |
| import os | |
| import logging | |
| # Настройка логирования | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| # Инициализация бота и Flask | |
| BOT_TOKEN = '7734802681:AAGKHGG8O9uNk64JWTHH5yqXzvSxCcoLUdA' | |
| bot = telebot.TeleBot(BOT_TOKEN) | |
| app = Flask(__name__) | |
| # Путь для хранения данных (товары и заказы) | |
| DATA_FILE = 'data.json' | |
| # Загрузка или создание данных | |
| def load_data(): | |
| try: | |
| if os.path.exists(DATA_FILE): | |
| with open(DATA_FILE, 'r', encoding='utf-8') as f: | |
| return json.load(f) | |
| return {'products': [], 'orders': []} | |
| except Exception as e: | |
| logger.error(f"Ошибка при загрузке данных: {e}") | |
| return {'products': [], 'orders': []} | |
| def save_data(data): | |
| try: | |
| with open(DATA_FILE, 'w', encoding='utf-8') as f: | |
| json.dump(data, f, ensure_ascii=False, indent=4) | |
| except Exception as e: | |
| logger.error(f"Ошибка при сохранении данных: {e}") | |
| data = load_data() | |
| # Обработчики для бота (пользовательская часть) | |
| def send_welcome(message): | |
| markup = types.ReplyKeyboardMarkup(resize_keyboard=True) | |
| btn1 = types.KeyboardButton("📋 Меню") | |
| btn2 = types.KeyboardButton("🛒 Корзина") | |
| btn3 = types.KeyboardButton("📦 Заказы") | |
| markup.add(btn1, btn2, btn3) | |
| bot.reply_to(message, "Привет! Я твой бот-магазин. Выбери действие:", reply_markup=markup) | |
| def func(message): | |
| if message.text == "📋 Меню": | |
| show_products(message) | |
| elif message.text == "🛒 Корзина": | |
| show_cart(message) | |
| elif message.text == "📦 Заказы": | |
| show_orders(message) | |
| def show_products(message): | |
| if not data['products']: | |
| bot.reply_to(message, "Нет доступных товаров.") | |
| return | |
| for product in data['products']: | |
| bot.reply_to(message, f"🏷 {product['name']} - {product['price']} руб.\nОписание: {product['description']}\n/id: {product['id']}", | |
| reply_markup=get_product_keyboard(product['id'])) | |
| def get_product_keyboard(product_id): | |
| markup = types.InlineKeyboardMarkup() | |
| btn_add = types.InlineKeyboardButton("Добавить в корзину", callback_data=f"add_{product_id}") | |
| markup.add(btn_add) | |
| return markup | |
| def callback_handler(call): | |
| product_id = int(call.data.split('_')[1]) | |
| product = next((p for p in data['products'] if p['id'] == product_id), None) | |
| if product: | |
| user_id = call.from_user.id | |
| cart = next((o for o in data['orders'] if o['user_id'] == user_id and not o['completed']), None) | |
| if not cart: | |
| cart = {'user_id': user_id, 'items': [], 'completed': False, 'date': datetime.now().isoformat()} | |
| data['orders'].append(cart) | |
| cart['items'].append({'product_id': product_id, 'quantity': 1}) | |
| save_data(data) | |
| bot.answer_callback_query(call.id, "Товар добавлен в корзину!") | |
| else: | |
| bot.answer_callback_query(call.id, "Товар не найден.") | |
| def show_cart(message): | |
| user_id = message.from_user.id | |
| cart = next((o for o in data['orders'] if o['user_id'] == user_id and not o['completed']), None) | |
| if not cart or not cart['items']: | |
| bot.reply_to(message, "Ваша корзина пуста.") | |
| return | |
| total = 0 | |
| response = "Ваша корзина:\n" | |
| for item in cart['items']: | |
| product = next(p for p in data['products'] if p['id'] == item['product_id']) | |
| response += f"🏷 {product['name']} - {product['price']} руб. x {item['quantity']}\n" | |
| total += product['price'] * item['quantity'] | |
| response += f"\nИтого: {total} руб." | |
| markup = types.InlineKeyboardMarkup() | |
| btn_complete = types.InlineKeyboardButton("Оформить заказ", callback_data=f"complete_{user_id}") | |
| markup.add(btn_complete) | |
| bot.reply_to(message, response, reply_markup=markup) | |
| def complete_order(call): | |
| user_id = int(call.data.split('_')[1]) | |
| cart = next((o for o in data['orders'] if o['user_id'] == user_id and not o['completed']), None) | |
| if cart: | |
| cart['completed'] = True | |
| save_data(data) | |
| bot.answer_callback_query(call.id, "Заказ успешно оформлен!") | |
| bot.send_message(user_id, "Спасибо за заказ! Мы скоро свяжемся с вами.") | |
| else: | |
| bot.answer_callback_query(call.id, "Корзина пуста или заказ уже оформлен.") | |
| def show_orders(message): | |
| user_id = message.from_user.id | |
| user_orders = [o for o in data['orders'] if o['user_id'] == user_id and o['completed']] | |
| if not user_orders: | |
| bot.reply_to(message, "У вас нет оформленных заказов.") | |
| return | |
| for order in user_orders: | |
| response = "Ваш заказ:\n" | |
| total = 0 | |
| for item in order['items']: | |
| product = next(p for p in data['products'] if p['id'] == item['product_id']) | |
| response += f"🏷 {product['name']} - {product['price']} руб. x {item['quantity']}\n" | |
| total += product['price'] * item['quantity'] | |
| response += f"\nИтого: {total} руб.\nДата: {order['date']}" | |
| bot.reply_to(message, response) | |
| # Админ-панель (Flask) с HTML, CSS и JavaScript в строке | |
| admin_html = """ | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Админ-панель</title> | |
| <style> | |
| body { font-family: Arial, sans-serif; margin: 20px; background-color: #f0f0f0; } | |
| .container { max-width: 800px; margin: 0 auto; } | |
| .product { border: 1px solid #ccc; padding: 15px; margin: 10px 0; background-color: #fff; border-radius: 5px; } | |
| form { background-color: #fff; padding: 15px; border-radius: 5px; margin-bottom: 20px; } | |
| input, textarea { width: 100%; margin: 5px 0; padding: 8px; } | |
| button { background-color: #4CAF50; color: white; padding: 10px 15px; border: none; border-radius: 5px; cursor: pointer; } | |
| button:hover { background-color: #45a049; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Управление товарами</h1> | |
| <form id="addProductForm"> | |
| <input type="text" name="name" placeholder="Название" required><br> | |
| <input type="number" name="price" placeholder="Цена" step="0.01" required><br> | |
| <textarea name="description" placeholder="Описание" required></textarea><br> | |
| <button type="submit">Добавить товар</button> | |
| </form> | |
| <h2>Существующие товары</h2> | |
| {% if products %} | |
| {% for product in products %} | |
| <div class="product"> | |
| {{ product.name }} - {{ product.price }} руб.<br> | |
| {{ product.description }}<br> | |
| <button onclick="deleteProduct({{ product.id }})">Удалить</button> | |
| </div> | |
| {% endfor %} | |
| {% else %} | |
| <p>Нет товаров.</p> | |
| {% endif %} | |
| <h2>Заказы</h2> | |
| {% if orders %} | |
| {% for order in orders %} | |
| <div class="product"> | |
| Пользователь: {{ order.user_id }}<br> | |
| Дата: {{ order.date }}<br> | |
| Товары: {% for item in order.items %} | |
| {{ item.quantity }} x {{ [p.name for p in products if p.id == item.product_id][0] }}<br> | |
| {% endfor %} | |
| </div> | |
| {% endfor %} | |
| {% else %} | |
| <p>Нет заказов.</p> | |
| {% endif %} | |
| </div> | |
| <script> | |
| document.getElementById('addProductForm').onsubmit = async (e) => { | |
| e.preventDefault(); | |
| const formData = new FormData(e.target); | |
| const response = await fetch('/add_product', { method: 'POST', body: formData }); | |
| if (response.ok) window.location.reload(); | |
| }; | |
| async function deleteProduct(productId) { | |
| const response = await fetch(`/delete_product/${productId}`, { method: 'POST' }); | |
| if (response.ok) window.location.reload(); | |
| } | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| def admin_panel(): | |
| try: | |
| return render_template_string(admin_html, products=data['products'], orders=data['orders']) | |
| except Exception as e: | |
| logger.error(f"Ошибка в шаблоне: {e}") | |
| return "Ошибка сервера. Проверь логи.", 500 | |
| def add_product(): | |
| try: | |
| if request.method == 'POST': | |
| name = request.form['name'] | |
| price = float(request.form['price']) | |
| description = request.form['description'] | |
| product_id = max((p['id'] for p in data['products']), default=0) + 1 | |
| data['products'].append({'id': product_id, 'name': name, 'price': price, 'description': description}) | |
| save_data(data) | |
| return jsonify({'status': 'success'}) | |
| except Exception as e: | |
| logger.error(f"Ошибка при добавлении товара: {e}") | |
| return jsonify({'status': 'error', 'message': str(e)}), 500 | |
| def delete_product(product_id): | |
| try: | |
| data['products'] = [p for p in data['products'] if p['id'] != product_id] | |
| save_data(data) | |
| return jsonify({'status': 'success'}) | |
| except Exception as e: | |
| logger.error(f"Ошибка при удалении товара: {e}") | |
| return jsonify({'status': 'error', 'message': str(e)}), 500 | |
| # Запуск бота и Flask в разных потоках | |
| def run_bot(): | |
| try: | |
| bot.polling(none_stop=True) | |
| except Exception as e: | |
| logger.error(f"Ошибка в боте: {e}") | |
| def run_flask(): | |
| try: | |
| app.run(host='0.0.0.0', port=7860) | |
| except Exception as e: | |
| logger.error(f"Ошибка в Flask: {e}") | |
| if __name__ == '__main__': | |
| bot_thread = threading.Thread(target=run_bot) | |
| flask_thread = threading.Thread(target=run_flask) | |
| bot_thread.start() | |
| flask_thread.start() | |
| bot_thread.join() | |
| flask_thread.join() |