From 62e1c3a92a1190d3dde831ef835d6b588296493d Mon Sep 17 00:00:00 2001 From: Vlad20250 Date: Wed, 16 Jul 2025 20:15:55 +0300 Subject: [PATCH] =?UTF-8?q?Create=20=D0=BC=D0=B5=D1=82=D1=80=D0=BE=5F?= =?UTF-8?q?=D1=88=D0=BE=D0=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit метро магазін бот --- ...\321\200\320\276_\321\210\320\276\320\277" | 446 ++++++++++++++++++ 1 file changed, 446 insertions(+) create mode 100644 "\320\274\320\265\321\202\321\200\320\276_\321\210\320\276\320\277" diff --git "a/\320\274\320\265\321\202\321\200\320\276_\321\210\320\276\320\277" "b/\320\274\320\265\321\202\321\200\320\276_\321\210\320\276\320\277" new file mode 100644 index 0000000..d5d3154 --- /dev/null +++ "b/\320\274\320\265\321\202\321\200\320\276_\321\210\320\276\320\277" @@ -0,0 +1,446 @@ +import telebot +from telebot.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton, InputFile +import re +from datetime import datetime +import csv +import os + +TOKEN = '8083186134:AAGQrnQy0xph9kSImmI5OXHWp7hatWszzLY' +ADMIN_CHAT_ID = 1712853053 +MONOBANK_CARD = "4441 1110 2811 6410" +MY_TELEGRAM_USERNAME = "@piec0_0eace" +REVIEW_CHANNEL_ID = '@piec_eace_Shop' + +bot = telebot.TeleBot(TOKEN) + +user_carts = {} +cancelled_carts = {} +order_counter = {} +orders_db = {} +reviews_db = {} + +category_items = { + "🛡 Броня": { + "Шлем 6": "5 грн♕", "Броня 6": "5 грн♕", + "Кобра шлем 6": "10 грн♕", "Кобра броня 6": "10 грн♕", + "Сталик шлем 6": "10 грн♕", "Сталик броня 6": "10 грн♕", + "Рюкзак 6": "5 грн♕" + }, + "🔫 Зброя": { + "МК14 виш.": "5 грн♕", "МК14 кб.": "10 грн♕", + "МК14 сф.": "10 грн♕", "МГ3 виш.": "10 грн♕" + }, + "🛒 Сети": { + "Сет 'Еліта'": "20 грн♕", "Сет 'Герой'": "35 грн♕", "Сет 'Легенда'": "35 грн♕" + }, + "🆕 Супроводи": { + "Звичайний на 5 карту": "50 грн♕", "По тіпам на 5 карту": "125 грн♕", + "VIP на 5 карту": "175 грн♕", "Звичайний на 7 карту": "75 грн♕", + "По тіпам на 7 карту": "125 грн♕", "VIP на 7 карту": "200 грн♕", + "VIP GOLD": "250 грн♕" + }, + "💸 Буст": { + "Білети 20шт": "200 грн", "Білети 50шт": "500 грн", "Білети 100шт": "900 грн", + "Баланс 20 млн": "125 грн", "Баланс 50 млн": "300 грн", "Баланс 100 млн": "500 грн", + "Баланс 500 млн": "2100 грн", "Баланс 1 млрд": "4000 грн", + "VIP Баланс 20 млн": "200 грн", "VIP Баланс 50 млн": "400 грн", + "VIP Баланс 100 млн": "700 грн", "VIP Баланс 500 млн": "3250 грн", + "VIP Баланс 1 млрд": "6500 грн" + } +} + +status_map = { + 'pending': '⏳ Очікує', + 'in_progress': '🚧 Виконується', + 'done': '✅ Виконано', + 'rejected': '❌ Відхилено', + 'processing': '🚧 Виконується', + 'completed': '✅ Виконано', + 'cancelled': '❌ Відхилено' +} + +# Підрахунок вартості +def parse_price(price_text): + + numbers = re.findall(r'\d+', price_text) + return int(numbers[0]) if numbers else 0 + +def calculate_total(cart): + return sum(parse_price(item['price']) for item in cart) + +# /start +@bot.message_handler(commands=['start']) +def start(message): + markup = ReplyKeyboardMarkup(resize_keyboard=True) + for category in category_items: + markup.add(KeyboardButton(category)) + markup.add(KeyboardButton("🛒 Кошик"), KeyboardButton("📦 Мої замовлення")) + bot.send_message(message.chat.id, "👋 Ласкаво просимо! Обери категорію:", reply_markup=markup) + +# Категорії +@bot.message_handler(func=lambda m: m.text in category_items) +def show_items(message): + markup = InlineKeyboardMarkup() + for item, price in category_items[message.text].items(): + markup.add(InlineKeyboardButton(f"{item} - {price}", callback_data=f"add:{item}")) + bot.send_message(message.chat.id, f"🔽 Обери товар у категорії {message.text}:", reply_markup=markup) + +# Додати в кошик +@bot.callback_query_handler(func=lambda call: call.data.startswith("add:")) +def add_to_cart(call): + item = call.data.split(":")[1] + price = None + for cat in category_items: + if item in category_items[cat]: + price = category_items[cat][item] + break + if not price: + bot.answer_callback_query(call.id, "❌ Не знайдено") + return + user_carts.setdefault(call.from_user.id, []).append({"item": item, "price": price}) + bot.answer_callback_query(call.id, f"✅ {item} додано у кошик") + +# Кошик +@bot.message_handler(func=lambda m: m.text == "🛒 Кошик") +def view_cart(message): + cart = user_carts.get(message.from_user.id, []) + if not cart: + bot.send_message(message.chat.id, "🛒 Ваш кошик порожній") + return + total = calculate_total(cart) + + text = "🛒 Ваші товари:\n" + "\n".join([f"- {i['item']} ({i['price']})" for i in cart]) + f"\n\n💰 Всього: {total} грн" + markup = InlineKeyboardMarkup() + markup.add(InlineKeyboardButton("✅ Оформити замовлення", callback_data="checkout")) + markup.add(InlineKeyboardButton("🗑 Очистити кошик", callback_data="clearcart")) + bot.send_message(message.chat.id, text, reply_markup=markup) + +@bot.callback_query_handler(func=lambda call: call.data == "clearcart") +def clear_cart(call): + uid = call.from_user.id + + user_carts[uid] = [] + bot.answer_callback_query(call.id, "🗑 Кошик очищено") + +# Оформити замовлення +@bot.callback_query_handler(func=lambda call: call.data == "checkout") +def ask_player_id(call): + + cart = user_carts.get(call.from_user.id, []) + if not cart: + bot.answer_callback_query(call.id, "❌ Ваш кошик порожній. Додайте товари перед оформленням.") + return + + bot.send_message(call.from_user.id, "🎮 Введіть ID гравця (або нік):") + + bot.register_next_step_handler(call.message, complete_order) + +def complete_order(message): + user_id = message.from_user.id + cart = user_carts.get(user_id, []) + if not cart: + bot.send_message(user_id, "❌ Кошик порожній. Будь ласка, додайте товари перед оформленням.") + return + + total = calculate_total(cart) + order_counter.setdefault(user_id, 0) + order_counter[user_id] += 1 + counter = order_counter[user_id] + order_id = f"{user_id}_{counter}" + + order = { + "order_id": order_id, + "user_id": user_id, + "username": message.from_user.username if message.from_user.username else "N/A", + "player_id": message.text, + "cart": cart, + "total": total, + "status": "pending" + } + orders_db[order_id] = order + user_carts[user_id] = [] + + admin_markup = InlineKeyboardMarkup() + admin_markup.add( + InlineKeyboardButton("🚧 Виконується", callback_data=f"progress:{order_id}"), + InlineKeyboardButton("✅ Виконано", callback_data=f"done:{order_id}"), + InlineKeyboardButton("❌ Відхилити", callback_data=f"reject:{order_id}") + ) + order_text = f"📦 НОВЕ ЗАМОВЛЕННЯ #{order_id}\n👤 @{order['username']} ({user_id})\n🎮 ID гравця: {order['player_id']}\n💰 Сума: {total} грн\n🛒 Товари:\n" + "\n".join([f"- {i['item']} ({i['price']})" for i in cart]) + bot.send_message(ADMIN_CHAT_ID, order_text, reply_markup=admin_markup) + bot.send_message(user_id, f"✅ Замовлення #{order_id} створено!\n💳 Оплата на карту: {MONOBANK_CARD}\nЗвʼяжіться з продавцем: {MY_TELEGRAM_USERNAME}") + +@bot.callback_query_handler(func=lambda call: call.data.startswith(("done:", "progress:", "reject:"))) +def update_status_legacy(call): + action, order_id = call.data.split(":") + if order_id in orders_db: + + new_status = { + 'done': 'completed', + 'progress': 'processing', + 'reject': 'cancelled' + }[action] + orders_db[order_id]['status'] = new_status + status_text = status_map[new_status] + bot.send_message(orders_db[order_id]['user_id'], f"ℹ️ Статус замовлення #{order_id} оновлено: {status_text}") + bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=None) + else: + bot.answer_callback_query(call.id, "❌ Замовлення не знайдено") + +# /myorders +@bot.message_handler(commands=['myorders', 'мої_замовлення']) +def my_orders(message): + uid = message.from_user.id + + my = [v for v in orders_db.values() if v.get('user_id') == uid] + if not my: + bot.send_message(uid, "📦 У вас немає замовлень.") + return + + for o in my: + status_display = status_map.get(o.get('status', 'unknown'), 'Невідомий статус') + bot.send_message(uid, f"#{o['order_id']} - {status_display} - {o['total']} грн") + + +@bot.message_handler(commands=['findorder', 'знайти_замовлення']) +def find_order(message): + if message.chat.id != ADMIN_CHAT_ID: + return + msg = bot.send_message(message.chat.id, "🔍 Введи ID замовлення:") + bot.register_next_step_handler(msg, show_order_info) + +def show_order_info(message): + order_id = message.text.strip() + order = orders_db.get(order_id) + if not order: + bot.send_message(message.chat.id, "❌ Не знайдено замовлення з таким ID.") + return + + text = f"📦 ЗАМОВЛЕННЯ #{order_id}\n👤 @{order['username']} ({order['user_id']})\n🎮 ID гравця: {order['player_id']}\n💰 Сума: {order['total']} грн\nСтатус: {status_map[order['status']]}\nТовари:\n" + "\n".join([f"- {i['item']} ({i['price']})" for i in order['cart']]) + bot.send_message(message.chat.id, text) + +# /allorders (Admin only) +@bot.message_handler(commands=['allorders', 'всі_замовлення']) +def all_orders(message): + if message.chat.id != ADMIN_CHAT_ID: + return + if not orders_db: + bot.send_message(message.chat.id, "❌ Немає замовлень.") + return + + for order in orders_db.values(): + status_display = status_map.get(order.get('status', 'unknown'), 'Невідомий статус') + bot.send_message(message.chat.id, f"#{order['order_id']} - {status_display} - {order['total']} грн") + +# /exportorders (Admin only) +@bot.message_handler(commands=['exportorders', 'експорт_замовлень']) +def export_orders(message): + if message.chat.id != ADMIN_CHAT_ID: + return + filename = "orders_export.csv" + try: + with open(filename, "w", newline='', encoding='utf-8') as csvfile: + fieldnames = ['order_id', 'user_id', 'username', 'player_id', 'total', 'status', 'items'] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + for order in orders_db.values(): + writer.writerow({ + 'order_id': order.get('order_id', 'N/A'), + 'user_id': order.get('user_id', 'N/A'), + 'username': order.get('username', 'N/A'), + 'player_id': order.get('player_id', 'N/A'), + 'total': order.get('total', 0), + 'status': order.get('status', 'N/A'), + 'items': "; ".join([item.get('item', 'N/A') for item in order.get('cart', [])]) + }) + bot.send_document(message.chat.id, InputFile(filename)) + except Exception as e: + bot.send_message(message.chat.id, f"❌ Помилка при експорті замовлень: {e}") + finally: + if os.path.exists(filename): + os.remove(filename) + +# /ordersbyuser (Admin only) +@bot.message_handler(commands=['ordersbyuser', 'замовлення_по_користувачу']) +def orders_by_user(message): + if message.chat.id != ADMIN_CHAT_ID: + return + msg = bot.send_message(message.chat.id, "🔎 Введи user_id для перегляду замовлень:") + bot.register_next_step_handler(msg, show_orders_for_user) + +def show_orders_for_user(message): + try: + uid = int(message.text.strip()) + user_orders = [v for v in orders_db.values() if v.get('user_id') == uid] + if not user_orders: + bot.send_message(message.chat.id, "❌ Замовлення не знайдені для цього користувача.") + return + for order in user_orders: + status_display = status_map.get(order.get('status', 'unknown'), 'Невідомий статус') + bot.send_message(message.chat.id, f"#{order['order_id']} ({status_display}) - {order['total']} грн") + except ValueError: + bot.send_message(message.chat.id, "❌ Некоректний user_id. Будь ласка, введіть числове значення.") + except Exception as e: + bot.send_message(message.chat.id, f"❌ Виникла помилка: {e}") + + +# Адмін-панель +@bot.message_handler(commands=['admin', 'адмін']) +def admin_panel(message): + if message.chat.id != ADMIN_CHAT_ID: + bot.send_message(message.chat.id, "⛔ Доступ заборонено.") + return + + markup = InlineKeyboardMarkup(row_width=2) + markup.add( + InlineKeyboardButton("📦 Всі замовлення", callback_data="admin_allorders"), + InlineKeyboardButton("🔎 Пошук замовлення", callback_data="admin_findorder"), + InlineKeyboardButton("👤 За user ID", callback_data="admin_ordersbyuser"), + InlineKeyboardButton("📤 Експорт CSV", callback_data="admin_exportorders") + ) + bot.send_message(message.chat.id, "🛠 Адмін-панель\nОберіть дію:", reply_markup=markup, parse_mode="HTML") + +# Обробка кнопок з адмін-панелі +@bot.callback_query_handler(func=lambda call: call.data.startswith("admin_")) +def handle_admin_action(call): + if call.message.chat.id != ADMIN_CHAT_ID: + bot.answer_callback_query(call.id, "⛔ Доступ заборонено.") + return + + action = call.data + + if action == "admin_allorders": + if not orders_db: + bot.send_message(call.message.chat.id, "❌ Немає замовлень.") + bot.answer_callback_query(call.id) + return + + for order_id, order in orders_db.items(): + status_display = status_map.get(order.get('status', 'unknown'), 'Невідомий статус') + msg = f"🆔 {order_id} — {status_display} — {order.get('total', 0)} грн" + markup = InlineKeyboardMarkup() + + if order['status'] == "pending": + markup.add( + InlineKeyboardButton("🚧 Виконується", callback_data=f"confirm_{order_id}"), + InlineKeyboardButton("❌ Відхилити", callback_data=f"reject_{order_id}") + ) + elif order['status'] == "processing": + markup.add( + InlineKeyboardButton("✅ Виконано", callback_data=f"complete_{order_id}") + ) + bot.send_message(call.message.chat.id, msg, reply_markup=markup) + + elif action == "admin_findorder": + msg = bot.send_message(call.message.chat.id, "🔎 Введи ID замовлення:") + bot.register_next_step_handler(msg, show_order_info) + + elif action == "admin_ordersbyuser": + msg = bot.send_message(call.message.chat.id, "🧑 Введи user_id:") + bot.register_next_step_handler(msg, show_orders_for_user) + + elif action == "admin_exportorders": + export_orders(call.message) + + bot.answer_callback_query(call.id) + +# Обробка статусів: підтвердження, виконання, відхилення +@bot.callback_query_handler(func=lambda call: call.data.startswith(("confirm_", "reject_", "complete_"))) +def handle_order_status_change(call): + if call.message.chat.id != ADMIN_CHAT_ID: + bot.answer_callback_query(call.id, "⛔ Доступ заборонено.") + return + + action, order_id = call.data.split("_", 1) + order = orders_db.get(order_id) + + if not order: + bot.answer_callback_query(call.id, "❌ Замовлення не знайдено") + return + + user_id = order["user_id"] + + if action == "confirm": + order["status"] = "processing" + markup = InlineKeyboardMarkup().add( + InlineKeyboardButton("✅ Виконано", callback_data=f"complete_{order_id}") + ) + bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=markup) + bot.send_message(user_id, f"🚧 Ваше замовлення *{order_id}* зараз виконується.", parse_mode="Markdown") + bot.send_message(call.message.chat.id, f"🚧 Статус {order_id} змінено на *Виконується*.", parse_mode="Markdown") + + elif action == "complete": + order["status"] = "completed" + bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=None) + bot.send_message(user_id, f"✅ Ваше замовлення *{order_id}* виконано!", parse_mode="Markdown") + bot.send_message(call.message.chat.id, f"✅ Статус {order_id} змінено на *Виконано*.", parse_mode="Markdown") + send_review_rating_request(user_id, order_id) + + elif action == "reject": + order["status"] = "cancelled" + bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=None) + bot.send_message(user_id, f"❌ Ваше замовлення *{order_id}* відхилено.", parse_mode="Markdown") + bot.send_message(call.message.chat.id, f"❌ Статус {order_id} змінено на *Відхилено*.", parse_mode="Markdown") + + bot.answer_callback_query(call.id) + +# ⭐ Запит на зірки +def send_review_rating_request(user_id, order_id): + markup = InlineKeyboardMarkup(row_width=5) + buttons = [InlineKeyboardButton(f"{i}⭐", callback_data=f"reviewstars_{order_id}_{i}") for i in range(1, 6)] + markup.add(*buttons) + bot.send_message( + user_id, + f"✅ Ваше замовлення #{order_id} виконано!\n\n📊 Будь ласка, оцініть сервіс:", + reply_markup=markup + ) + +@bot.callback_query_handler(func=lambda call: call.data.startswith("reviewstars_")) +def handle_review_stars(call): + try: + _, order_id, stars = call.data.split("_", 2) + stars = int(stars) + user_id = call.from_user.id + reviews_db[order_id] = {"user_id": user_id, "stars": stars, "text": ""} + bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=None) + bot.send_message( + call.message.chat.id, + f"⭐ Ви поставили {stars} з 5. Тепер напишіть свій відгук текстом у відповіді:" + ) + bot.register_next_step_handler(call.message, lambda msg: save_review_text(msg, order_id, stars)) + except Exception as e: + print(f"[review stars error] {e}") + bot.answer_callback_query(call.id, "❌ Сталася помилка. Спробуйте ще раз.") + +# 💬 Збереження тексту + публікація +def save_review_text(message, order_id, stars): + text = message.text + user_id = message.from_user.id + + + if order_id in reviews_db: + reviews_db[order_id]["text"] = text + else: + reviews_db[order_id] = {"user_id": user_id, "stars": stars, "text": text} + + bot.send_message(message.chat.id, "✅ Дякуємо за ваш відгук!") + bot.send_message( + ADMIN_CHAT_ID, + f"💬 Відгук по замовленню #{order_id} від покупця:\n\n" + f"⭐ {stars} з 5\n{text}", + parse_mode="HTML" + ) + + try: + star_line = "⭐" * stars + bot.send_message( + REVIEW_CHANNEL_ID, + f"🛒 Новий відгук\n\n{star_line}\n{text}", + parse_mode="HTML" + ) + except Exception as e: + print(f"[publish review error] {e}") + bot.send_message(ADMIN_CHAT_ID, f"❌ Помилка при публікації відгуку в канал: {e}") + +print("🤖 Бот запущено") +bot.polling(none_stop=True)