routineadm / app.py
flpolprojects's picture
Update app.py
21d6b00 verified
raw
history blame
10.9 kB
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()
# Обработчики для бота (пользовательская часть)
@bot.message_handler(commands=['start'])
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)
@bot.message_handler(content_types=['text'])
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
@bot.callback_query_handler(func=lambda call: call.data.startswith('add_'))
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)
@bot.callback_query_handler(func=lambda call: call.data.startswith('complete_'))
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>
"""
@app.route('/')
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
@app.route('/add_product', methods=['POST'])
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
@app.route('/delete_product/<int:product_id>', methods=['POST'])
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()