diff --git a/InDMCategories.py b/InDMCategories.py deleted file mode 100644 index f2c8527501..0000000000 --- a/InDMCategories.py +++ /dev/null @@ -1,62 +0,0 @@ - - -from datetime import * -from flask_session import Session -import telebot -from flask import Flask, request -from telebot import types -import os -import os.path -from InDMDevDB import * -from dotenv import load_dotenv -load_dotenv('config.env') - -# Bot connection -bot = telebot.TeleBot(f"{os.getenv('TELEGRAM_BOT_TOKEN')}", threaded=False) -StoreCurrency = f"{os.getenv('STORE_CURRENCY')}" - -class CategoriesDatas: - def get_category_products(message, input_cate): - id = message.from_user.id - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - buyer_id = message.from_user.id - buyer_username = message.from_user.username - all_categories = GetDataFromDB.GetCategoryIDsInDB() - categories = [] - for catnum, catname in all_categories: - catnames = catname.upper() - categories.append(catnames) - - def checkint(): - try: - input_cat = int(input_cate) - return input_cat - except: - return input_cate - input_category = checkint() - if isinstance(input_category, int) == True: - product_cate = GetDataFromDB.Get_A_CategoryName(input_category) - if f"{product_cate}" in f"{categories}": - product_category = product_cate.upper() - product_list = GetDataFromDB.GetProductInfoByCTGName(product_category) - print(product_list) - if product_list == []: - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - key1 = types.KeyboardButton(text="Shop Items πŸ›’") - key2 = types.KeyboardButton(text="My Orders πŸ›") - key3 = types.KeyboardButton(text="Support πŸ“ž") - keyboard.add(key1) - keyboard.add(key2, key3) - bot.send_message(id, f"No Product in the store", reply_markup=keyboard) - else: - bot.send_message(id, f"{product_cate} Gategory's Products") - keyboard = types.InlineKeyboardMarkup() - for productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory in product_list: - keyboard.add(types.InlineKeyboardButton(text="BUY NOW πŸ’°", callback_data=f"getproduct_{productnumber}")) - bot.send_photo(id, photo=f"{productimagelink}", caption=f"Product ID πŸͺͺ: /{productnumber}\n\nProduct Name πŸ“¦: {productname}\n\nProduct Price πŸ’°: {productprice} {StoreCurrency}\n\nProducts In Stock πŸ›: {productquantity}\n\nProduct Description πŸ’¬: {productdescription}", reply_markup=keyboard) - - #bot.send_message(id, "πŸ’‘ Click on a Product ID to select the product purchase") - else: - print("Wrong commmand !!!") diff --git a/InDMDevDB.py b/InDMDevDB.py deleted file mode 100644 index b1302e08cf..0000000000 --- a/InDMDevDB.py +++ /dev/null @@ -1,871 +0,0 @@ -import sqlite3 -from datetime import datetime -import threading -import logging - -# Configure logging -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -# Database configuration -DB_FILE = 'InDMDevDBShop.db' -db_connection = sqlite3.connect(DB_FILE, check_same_thread=False) -db_connection.row_factory = sqlite3.Row # Enable dict-like access to rows -cursor = db_connection.cursor() -db_lock = threading.Lock() - -class CreateTables: - """Database table creation and management""" - - @staticmethod - def create_all_tables(): - """Create all necessary database tables""" - try: - with db_lock: - # Create ShopUserTable - cursor.execute("""CREATE TABLE IF NOT EXISTS ShopUserTable( - id INTEGER PRIMARY KEY AUTOINCREMENT, - user_id INTEGER UNIQUE NOT NULL, - username TEXT, - wallet INTEGER DEFAULT 0, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - )""") - - # Create ShopAdminTable - cursor.execute("""CREATE TABLE IF NOT EXISTS ShopAdminTable( - id INTEGER PRIMARY KEY AUTOINCREMENT, - admin_id INTEGER UNIQUE NOT NULL, - username TEXT, - wallet INTEGER DEFAULT 0, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - )""") - - # Create ShopProductTable - cursor.execute("""CREATE TABLE IF NOT EXISTS ShopProductTable( - id INTEGER PRIMARY KEY AUTOINCREMENT, - productnumber INTEGER UNIQUE NOT NULL, - admin_id INTEGER NOT NULL, - username TEXT, - productname TEXT NOT NULL, - productdescription TEXT, - productprice INTEGER DEFAULT 0, - productimagelink TEXT, - productdownloadlink TEXT, - productkeysfile TEXT, - productquantity INTEGER DEFAULT 0, - productcategory TEXT DEFAULT 'Default Category', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (admin_id) REFERENCES ShopAdminTable(admin_id) - )""") - - # Create ShopOrderTable - cursor.execute("""CREATE TABLE IF NOT EXISTS ShopOrderTable( - id INTEGER PRIMARY KEY AUTOINCREMENT, - buyerid INTEGER NOT NULL, - buyerusername TEXT, - productname TEXT NOT NULL, - productprice TEXT NOT NULL, - orderdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - paidmethod TEXT DEFAULT 'NO', - productdownloadlink TEXT, - productkeys TEXT, - buyercomment TEXT, - ordernumber INTEGER UNIQUE NOT NULL, - productnumber INTEGER NOT NULL, - payment_id TEXT, - FOREIGN KEY (buyerid) REFERENCES ShopUserTable(user_id), - FOREIGN KEY (productnumber) REFERENCES ShopProductTable(productnumber) - )""") - - # Create ShopCategoryTable - cursor.execute("""CREATE TABLE IF NOT EXISTS ShopCategoryTable( - id INTEGER PRIMARY KEY AUTOINCREMENT, - categorynumber INTEGER UNIQUE NOT NULL, - categoryname TEXT NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - )""") - - # Create PaymentMethodTable - cursor.execute("""CREATE TABLE IF NOT EXISTS PaymentMethodTable( - id INTEGER PRIMARY KEY AUTOINCREMENT, - admin_id INTEGER, - username TEXT, - method_name TEXT UNIQUE NOT NULL, - token_keys_clientid TEXT, - secret_keys TEXT, - activated TEXT DEFAULT 'NO', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - )""") - - db_connection.commit() - logger.info("All database tables created successfully") - - except Exception as e: - logger.error(f"Error creating database tables: {e}") - db_connection.rollback() - raise - -# Initialize tables -CreateTables.create_all_tables() - -class CreateDatas: - """Database data creation and insertion operations""" - - @staticmethod - def add_user(user_id, username): - """Add a new user to the database""" - try: - with db_lock: - cursor.execute( - "INSERT OR IGNORE INTO ShopUserTable (user_id, username, wallet) VALUES (?, ?, ?)", - (user_id, username, 0) - ) - db_connection.commit() - logger.info(f"User added: {username} (ID: {user_id})") - return True - except Exception as e: - logger.error(f"Error adding user {username}: {e}") - db_connection.rollback() - return False - - @staticmethod - def add_admin(admin_id, username): - """Add a new admin to the database""" - try: - with db_lock: - cursor.execute( - "INSERT OR IGNORE INTO ShopAdminTable (admin_id, username, wallet) VALUES (?, ?, ?)", - (admin_id, username, 0) - ) - db_connection.commit() - logger.info(f"Admin added: {username} (ID: {admin_id})") - return True - except Exception as e: - logger.error(f"Error adding admin {username}: {e}") - db_connection.rollback() - return False - - @staticmethod - def add_product(productnumber, admin_id, username): - """Add a new product to the database""" - try: - with db_lock: - cursor.execute(""" - INSERT INTO ShopProductTable - (productnumber, admin_id, username, productname, productdescription, - productprice, productimagelink, productdownloadlink, productkeysfile, - productquantity, productcategory) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """, (productnumber, admin_id, username, 'NIL', 'NIL', 0, 'NIL', - 'https://nil.nil', 'NIL', 0, 'Default Category')) - db_connection.commit() - logger.info(f"Product {productnumber} added by admin {username}") - return True - except Exception as e: - logger.error(f"Error adding product {productnumber}: {e}") - db_connection.rollback() - return False - - # Backward compatibility methods - @staticmethod - def AddAuser(user_id, username): - """Backward compatibility wrapper for add_user""" - return CreateDatas.add_user(user_id, username) - - @staticmethod - def AddAdmin(admin_id, username): - """Backward compatibility wrapper for add_admin""" - return CreateDatas.add_admin(admin_id, username) - - @staticmethod - def AddProduct(productnumber, admin_id, username): - """Backward compatibility wrapper for add_product""" - return CreateDatas.add_product(productnumber, admin_id, username) - - @staticmethod - def AddOrder(buyer_id, username, productname, productprice, orderdate, paidmethod, - productdownloadlink, productkeys, ordernumber, productnumber, payment_id): - """Add a new order to the database""" - try: - with db_lock: - cursor.execute(""" - INSERT INTO ShopOrderTable - (buyerid, buyerusername, productname, productprice, orderdate, - paidmethod, productdownloadlink, productkeys, buyercomment, - ordernumber, productnumber, payment_id) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """, (buyer_id, username, productname, productprice, orderdate, - paidmethod, productdownloadlink, productkeys, 'NIL', - ordernumber, productnumber, payment_id)) - db_connection.commit() - logger.info(f"Order {ordernumber} added for user {username}") - return True - except Exception as e: - logger.error(f"Error adding order {ordernumber}: {e}") - db_connection.rollback() - return False - - def AddCategory(categorynumber, categoryname): - try: - AddData = f"Insert into ShopCategoryTable (categorynumber, categoryname) values('{categorynumber}', '{categoryname}')" - connected.execute(AddData) - DBConnection.commit() - except Exception as e: - print(e) - - def AddEmptyRow(): - AddData = f"Insert into PaymentMethodTable (admin_id, username, method_name, activated) values('None', 'None', 'None', 'None')" - connected.execute(AddData) - DBConnection.commit() - - def AddCryptoPaymentMethod(id, username, token_keys_clientid, secret_keys, method_name): - try: - connected.execute(f"UPDATE PaymentMethodTable SET admin_id = ?, username = ?, token_keys_clientid = ?, secret_keys = ?, activated = 'NO' WHERE method_name = '{method_name}'", (id, username, token_keys_clientid, secret_keys)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateOrderConfirmed(paidmethod, ordernumber): - try: - connected.execute(f"UPDATE ShopOrderTable SET paidmethod = ? WHERE ordernumber = ?", (paidmethod, ordernumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdatePaymentMethodToken(id, username, token_keys_clientid, method_name): - try: - connected.execute(f"UPDATE PaymentMethodTable SET admin_id = '{id}', username = '{username}', token_keys_clientid = '{token_keys_clientid}' WHERE method_name = '{method_name}'") - DBConnection.commit() - except Exception as e: - print(e) - - def UpdatePaymentMethodSecret(id, username, secret_keys, method_name): - try: - connected.execute(f"UPDATE PaymentMethodTable SET admin_id = '{id}', username = '{username}', secret_keys = '{secret_keys}' WHERE method_name = '{method_name}'") - DBConnection.commit() - except Exception as e: - print(e) - - def Update_A_Category(categoryname, categorynumber): - try: - connected.execute("UPDATE ShopCategoryTable SET categoryname = ? WHERE categorynumber = ?", (categoryname, categorynumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateOrderComment(buyercomment, ordernumber): - try: - connected.execute(f"UPDATE ShopOrderTable SET buyercomment = ? WHERE ordernumber = ?", (buyercomment, ordernumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateOrderPaymentMethod(paidmethod, ordernumber): - try: - connected.execute(f"UPDATE ShopOrderTable SET paidmethod = ? WHERE ordernumber = ?", (paidmethod, ordernumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateOrderPurchasedKeys(productkeys, ordernumber): - try: - connected.execute(f"UPDATE ShopOrderTable SET productkeys = ? WHERE ordernumber = ?", (productkeys, ordernumber)) - DBConnection.commit() - except Exception as e: - print(e) - - - def AddPaymentMethod(id, username, method_name): - AddData = f"Insert into PaymentMethodTable (admin_id, username, method_name, activated) values('{id}', '{username}', '{method_name}', 'YES')" - connected.execute(AddData) - DBConnection.commit() - - def UpdateProductName(productname, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productname = ? WHERE productnumber = ?", (productname, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateProductDescription(productdescription, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productdescription = ? WHERE productnumber = ?", (productdescription, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateProductPrice(productprice, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productprice = ? WHERE productnumber = ?", (productprice, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateProductproductimagelink(productimagelink, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productimagelink = ? WHERE productnumber = ?", (productimagelink, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateProductproductdownloadlink(productdownloadlink, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productdownloadlink = ? WHERE productnumber = ?", (productdownloadlink, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateProductKeysFile(productkeysfile, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productkeysfile = ? WHERE productnumber = ?", (productkeysfile, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateProductQuantity(productquantity, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productquantity = ? WHERE productnumber = ?", (productquantity, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateProductCategory(productcategory, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productcategory = ? WHERE productnumber = ?", (productcategory, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def UpdateProductQuantity(productquantity, productnumber): - try: - connected.execute(f"UPDATE ShopProductTable SET productquantity = ? WHERE productnumber = ?", (productquantity, productnumber)) - DBConnection.commit() - except Exception as e: - print(e) - - def Update_All_ProductCategory(new_category, productcategory): - try: - connected.execute(f"UPDATE ShopProductTable SET productcategory = ? WHERE productcategory = ?", (new_category, productcategory)) - DBConnection.commit() - except Exception as e: - print(e) - -class GetDataFromDB: - """Database query operations""" - - @staticmethod - def GetUserWalletInDB(userid): - """Get user wallet balance from database""" - try: - with db_lock: - cursor.execute("SELECT wallet FROM ShopUserTable WHERE user_id = ?", (userid,)) - result = cursor.fetchone() - return result[0] if result else 0 - except Exception as e: - logger.error(f"Error getting user wallet for {userid}: {e}") - return 0 - - def GetUserNameInDB(userid): - try: - connected.execute(f"SELECT username FROM ShopUserTable WHERE user_id = '{userid}'") - shopuser = connected.fetchone()[0] - return shopuser - except Exception as e: - print(e) - return "" - - def GetAdminNameInDB(userid): - try: - connected.execute(f"SELECT username FROM ShopAdminTable WHERE admin_id = '{userid}'") - shopuser = connected.fetchone()[0] - return shopuser - except Exception as e: - print(e) - return "" - - def GetUserIDsInDB(): - try: - connected.execute(f"SELECT user_id FROM ShopUserTable") - shopuser = connected.fetchall() - return shopuser - except Exception as e: - print(e) - return None - - def GetProductName(productnumber): - try: - connected.execute(f"SELECT productname FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productname = connected.fetchone()[0] - return productname - except Exception as e: - print(e) - return None - - def GetProductDescription(productnumber): - try: - connected.execute(f"SELECT productdescription FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productdescription = connected.fetchone()[0] - return productdescription - except Exception as e: - print(e) - return None - - def GetProductPrice(productnumber): - try: - connected.execute(f"SELECT productprice FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productprice = connected.fetchone()[0] - return productprice - except Exception as e: - print(e) - return None - - def GetProductImageLink(productnumber): - try: - connected.execute(f"SELECT productimagelink FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productimagelink = connected.fetchone()[0] - return productimagelink - except Exception as e: - print(e) - return None - - def GetProductDownloadLink(productnumber): - try: - connected.execute(f"SELECT productdownloadlink FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productimagelink = connected.fetchone()[0] - return productimagelink - except Exception as e: - print(e) - return None - - def GetProductNumber(productnumber): - try: - connected.execute(f"SELECT productnumber FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productnumbers = connected.fetchone()[0] - return productnumbers - except Exception as e: - print(e) - return None - - def GetProductQuantity(productnumber): - try: - connected.execute(f"SELECT productquantity FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productprice = connected.fetchone()[0] - return productprice - except Exception as e: - print(e) - return None - - def GetProduct_A_Category(productnumber): - try: - connected.execute(f"SELECT productcategory FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productcategory = connected.fetchone()[0] - return productcategory - except Exception as e: - print(e) - return None - - def Get_A_CategoryName(categorynumber): - try: - connected.execute(f"SELECT DISTINCT categoryname FROM ShopCategoryTable WHERE categorynumber = '{categorynumber}'") - productcategory = connected.fetchone()[0] - if productcategory is not None: - return productcategory - else: - return None - except Exception as e: - print(e) - return None - - def GetCategoryIDsInDB(): - try: - connected.execute(f"SELECT categorynumber, categoryname FROM ShopCategoryTable") - categories = connected.fetchall() - if categories is not None: - return categories - else: - return None - except Exception as e: - print(e) - return None - - def GetCategoryNumProduct(productcategory): - try: - connected.execute(f"SELECT COUNT(*) FROM ShopProductTable WHERE productcategory = '{productcategory}'") - categories = connected.fetchall() - if categories is not None: - return categories - else: - return None - except Exception as e: - print(e) - return None - - def GetProduct_A_AdminID(productnumber): - try: - connected.execute(f"SELECT admin_id FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productcategory = connected.fetchone()[0] - return productcategory - except Exception as e: - print(e) - return None - - def GetAdminIDsInDB(): - try: - connected.execute(f"SELECT admin_id FROM ShopAdminTable") - shopadmin = connected.fetchall() - return shopadmin - except Exception as e: - print(e) - return None - - def GetAdminUsernamesInDB(): - try: - shopadmin = [] - connected.execute(f"SELECT username FROM ShopAdminTable") - shopadmin = connected.fetchall() - return shopadmin - except Exception as e: - print(e) - return None - - def GetProductNumberName(): - try: - productnumbers_name = [] - connected.execute(f"SELECT DISTINCT productnumber, productname FROM ShopProductTable") - productnumbers_name = connected.fetchall() - if productnumbers_name is not None: - return productnumbers_name - else: - return None - except Exception as e: - print(e) - return None - - def GetProductInfos(): - try: - productnumbers_name = [] - connected.execute(f"SELECT DISTINCT productnumber, productname, productprice FROM ShopProductTable") - productnumbers_name = connected.fetchall() - if productnumbers_name is not None: - return productnumbers_name - else: - return None - except Exception as e: - print(e) - return None - - def GetProductInfo(): - try: - productnumbers_name = [] - connected.execute(f"SELECT DISTINCT productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory FROM ShopProductTable") - productnumbers_name = connected.fetchall() - if productnumbers_name is not None: - return productnumbers_name - else: - return None - except Exception as e: - print(e) - return None - - def GetProductInfoByCTGName(productcategory): - try: - productnumbers_name = [] - connected.execute(f"SELECT DISTINCT productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory FROM ShopProductTable WHERE productcategory = '{productcategory}'") - productnumbers_name = connected.fetchall() - if productnumbers_name is not None: - return productnumbers_name - else: - return None - except Exception as e: - print(e) - return None - - def GetProductInfoByPName(productnumber): - try: - productnumbers_name = [] - connected.execute(f"SELECT DISTINCT productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory FROM ShopProductTable WHERE productnumber = '{productnumber}'") - productnumbers_name = connected.fetchall() - if productnumbers_name is not None: - return productnumbers_name - else: - return None - except Exception as e: - print(e) - return None - - def GetUsersInfo(): - try: - user_infos = [] - connected.execute(f"SELECT DISTINCT user_id, username, wallet FROM ShopUserTable") - user_infos = connected.fetchall() - if user_infos is not None: - return user_infos - else: - return None - except Exception as e: - print(e) - return None - - def AllUsers(): - try: - connected.execute(f"SELECT COUNT(user_id) FROM ShopUserTable") - alluser = connected.fetchall() - if alluser is not None: - return alluser - else: - return 0 - except Exception as e: - print(e) - return 0 - - def AllAdmins(): - try: - connected.execute(f"SELECT COUNT(admin_id) FROM ShopAdminTable") - alladmin = connected.fetchall() - if alladmin is not None: - return alladmin - else: - return 0 - except Exception as e: - print(e) - return 0 - - def AllProducts(): - try: - connected.execute(f"SELECT COUNT(productnumber) FROM ShopProductTable") - allproduct = connected.fetchall() - if allproduct is not None: - return allproduct - else: - return 0 - except Exception as e: - print(e) - return 0 - - def AllOrders(): - try: - connected.execute(f"SELECT COUNT(buyerid) FROM ShopOrderTable") - allorder = connected.fetchall() - if allorder is not None: - return allorder - else: - return 0 - except Exception as e: - print(e) - return 0 - - def GetAdminsInfo(): - try: - admin_infos = [] - connected.execute(f"SELECT DISTINCT admin_id, username, wallet FROM ShopAdminTable") - admin_infos = connected.fetchall() - if admin_infos is not None: - return admin_infos - else: - return None - except Exception as e: - print(e) - return None - - def GetOrderInfo(): - try: - order_infos = [] - connected.execute(f"SELECT DISTINCT ordernumber, productname, buyerusername FROM ShopOrderTable") - order_infos = connected.fetchall() - if order_infos is not None: - return order_infos - else: - return None - except Exception as e: - print(e) - return None - - def GetPaymentMethods(): - try: - payment_method = [] - connected.execute(f"SELECT DISTINCT method_name, activated, username FROM PaymentMethodTable") - payment_method = connected.fetchall() - if payment_method is not None: - return payment_method - else: - return None - except Exception as e: - print(e) - return None - - def GetPaymentMethodsAll(method_name): - try: - payment_method = [] - connected.execute(f"SELECT DISTINCT method_name, token_keys_clientid, secret_keys FROM PaymentMethodTable WHERE method_name = '{method_name}'") - payment_method = connected.fetchall() - if payment_method is not None: - return payment_method - else: - return None - except Exception as e: - print(e) - return None - - def GetPaymentMethodTokenKeysCleintID(method_name): - try: - connected.execute(f"SELECT DISTINCT token_keys_clientid FROM PaymentMethodTable WHERE method_name = '{method_name}'") - payment_method = connected.fetchone()[0] - if payment_method is not None: - return payment_method - else: - return None - except Exception as e: - print(e) - return None - - def GetPaymentMethodSecretKeys(method_name): - try: - connected.execute(f"SELECT DISTINCT secret_keys FROM PaymentMethodTable WHERE method_name = '{method_name}'") - payment_method = connected.fetchone()[0] - if payment_method is not None: - return payment_method - else: - return None - except Exception as e: - print(e) - return None - - def GetAllPaymentMethodsInDB(): - try: - payment_methods = [] - connected.execute(f"SELECT DISTINCT method_name FROM PaymentMethodTable") - payment_methods = connected.fetchall() - if payment_methods is not None: - return payment_methods - else: - return None - except Exception as e: - print(e) - return None - - def GetProductCategories(): - try: - productcategory = [] - connected.execute(f"SELECT DISTINCT productcategory FROM ShopProductTable") - productcategory = connected.fetchall() - return productcategory - except Exception as e: - print(e) - return "Default Category" - - def GetProductIDs(): - try: - productnumbers = [] - connected.execute(f"SELECT productnumber FROM ShopProductTable") - productnumbers = connected.fetchall() - return productnumbers - except Exception as e: - print(e) - return None - - def GetOrderDetails(ordernumber): - try: - order_details = [] - connected.execute(f"SELECT DISTINCT buyerid, buyerusername, productname, productprice, orderdate, paidmethod, productdownloadlink, productkeys, buyercomment, ordernumber, productnumber FROM ShopOrderTable WHERE ordernumber = '{ordernumber}' AND paidmethod != 'NO'") - order_details = connected.fetchall() - if order_details is not None: - return order_details - else: - return None - except Exception as e: - print(e) - return None - - def GetOrderIDs_Buyer(buyerid): - try: - productnumbers = [] - connected.execute(f"SELECT ordernumber FROM ShopOrderTable WHERE buyerid = '{buyerid}' AND paidmethod != 'NO' ") - productnumbers = connected.fetchall() - return productnumbers - except Exception as e: - print(e) - return None - - def GetOrderIDs(): - try: - productnumbers = [] - connected.execute(f"SELECT ordernumber FROM ShopOrderTable") - productnumbers = connected.fetchall() - return productnumbers - except Exception as e: - print(e) - return None - - def GetAllUnfirmedOrdersUser(buyerid): - try: - payment_method = [] - connected.execute(f"SELECT DISTINCT ordernumber, productname, buyerusername, payment_id, productnumber FROM ShopOrderTable WHERE paidmethod = 'NO' AND buyerid = '{buyerid}' AND payment_id != ordernumber") - payment_method = connected.fetchall() - if payment_method is not None: - return payment_method - else: - return None - except Exception as e: - print(e) - return None - - -class CleanData: - def __init__(self) -> None: - pass - - def CleanShopUserTable(): - try: - connected.execute("DELETE FROM ShopUserTable") - DBConnection.commit() - except Exception as e: - print(e) - - def CleanShopProductTable(): - try: - connected.execute("DELETE FROM ShopProductTable") - DBConnection.commit() - except Exception as e: - print(e) - - def delete_an_order(user_id, ordernumber): - try: - connected.execute(f"DELETE FROM ShopOrderTable WHERE user_id = '{user_id}' AND ordernumber = '{ordernumber}'") - DBConnection.commit() - except Exception as e: - print(e) - - def delete_a_product(productnumber): - try: - connected.execute(f"DELETE FROM ShopProductTable WHERE productnumber = '{productnumber}'") - DBConnection.commit() - except Exception as e: - print(e) - - def delete_an_order(ordernumber): - try: - connected.execute(f"DELETE FROM ShopOrderTable WHERE ordernumber = '{ordernumber}'") - DBConnection.commit() - except Exception as e: - print(e) - - def delete_a_payment_method(method_name): - try: - connected.execute(f"DELETE FROM PaymentMethodTable WHERE method_name = '{method_name}'") - DBConnection.commit() - except Exception as e: - print(e) - - def delete_a_category(categorynumber): - try: - connected.execute(f"DELETE FROM ShopCategoryTable WHERE categorynumber = '{categorynumber}'") - DBConnection.commit() - except Exception as e: - print(e) - - - - - - - diff --git a/config.env b/config.env index 86bcdf2b33..cab5bc79e5 100644 --- a/config.env +++ b/config.env @@ -1,3 +1,7 @@ -NGROK_HTTPS_URL=https://sample.app -TELEGRAM_BOT_TOKEN=00000000000:rtrtirtitrsample +# These values should be set as secrets in your Render environment, not here. +TELEGRAM_BOT_TOKEN= +DATABASE_URL= + +# You can keep non-secret configuration here. STORE_CURRENCY=USD +NGROK_HTTPS_URL= diff --git a/purchase.py b/purchase.py deleted file mode 100644 index 78289284c0..0000000000 --- a/purchase.py +++ /dev/null @@ -1,88 +0,0 @@ -from datetime import * -from flask_session import Session -import telebot -from flask import Flask, request -from telebot import types -import os -import os.path -from InDMDevDB import * -from dotenv import load_dotenv -load_dotenv('config.env') - - -# M""M M"""""""`YM M""""""'YMM M"""""`'"""`YM M""""""'YMM MM""""""""`M M""MMMMM""M -# M M M mmmm. M M mmmm. `M M mm. mm. M M mmmm. `M MM mmmmmmmM M MMMMM M -# M M M MMMMM M M MMMMM M M MMM MMM M M MMMMM M M` MMMM M MMMMP M -# M M M MMMMM M M MMMMM M M MMM MMM M M MMMMM M MM MMMMMMMM M MMMM' .M -# M M M MMMMM M M MMMM' .M M MMM MMM M M MMMM' .M MM MMMMMMMM M MMP' .MM -# M M M MMMMM M M .MM M MMM MMM M M .MM MM .M M .dMMM -# MMMM MMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM MMMMMMMMMMM - -# Bot connection -bot = telebot.TeleBot(f"{os.getenv('TELEGRAM_BOT_TOKEN')}", threaded=False) -StoreCurrency = f"{os.getenv('STORE_CURRENCY')}" - -class UserOperations: - def shop_items(message): - id = message.from_user.id - usname = message.chat.username - products_list = GetDataFromDB.GetProductInfo() - id = message.from_user.id - all_categories = GetDataFromDB.GetCategoryIDsInDB() - keyboard = types.InlineKeyboardMarkup() - if all_categories == []: - bot.send_message(id, "⚠️ No Product available at the moment, kindly check back soon ") - else: - for catnum, catname in all_categories: - c_catname = catname.upper() - products_category = GetDataFromDB.GetCategoryNumProduct(c_catname) - for ctg in products_category: - products_in_category = ctg[0] - text_but = f"🏷 {catname} ({products_in_category})" - text_cal = f"getcats_{catnum}" - keyboard.add(types.InlineKeyboardButton(text=text_but, callback_data=text_cal)) - - - bot.send_message(id, f"CATEGORIES:", reply_markup=keyboard) - bot.send_message(id, "List completed βœ…", reply_markup=types.ReplyKeyboardRemove()) - for productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory in products_list: - list_m = [productnumber, productname, productprice] - - #@bot.callback_query_handler(func=lambda call: True) - def callback_query(call): - if call.data == "check": - check_command(call.message) - else: - print("Ok") - - def purchase_a_products(message, input_cate): - id = message.from_user.id - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - def checkint(): - try: - input_cat = int(input_cate) - return input_cat - except: - return input_cate - - input_product_id = checkint() - if isinstance(input_product_id, int) == True: - product_list = GetDataFromDB.GetProductInfoByPName(input_product_id) - if f"{input_product_id}" in f"{product_list}": - key1 = types.KeyboardButton(text="Bitcoin ΰΈΏ") - keyboard.add(key1) - for productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory in product_list: - list_m = [productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory] - bot.send_message(id, "πŸ’‘ Select a Payment method to pay for this product πŸ‘‡", reply_markup=keyboard) - global order_info - order_info = list_m - else: - print("Wrong command !!!") - def orderdata(): - try: - 1==1 - print(order_info) - return order_info - except: - return None diff --git a/render.yaml b/render.yaml new file mode 100644 index 0000000000..d1797bc3b0 --- /dev/null +++ b/render.yaml @@ -0,0 +1,24 @@ +databases: + - name: bot-database + databaseName: bot_database + user: bot_user + +services: + - type: web + name: telegram-store-bot + env: python + buildCommand: "pip install -r requirements.txt" + startCommand: "gunicorn store_main:flask_app" + envVars: + - key: PYTHON_VERSION + value: "3.11.8" + - key: TELEGRAM_BOT_TOKEN + sync: false + - key: STORE_CURRENCY + value: USD + - key: SECRET_KEY + generateValue: true + - key: DATABASE_URL + fromDatabase: + name: bot-database + property: connectionString diff --git a/requirements.txt b/requirements.txt index 7713b0345f..880af5251c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,6 @@ urllib3==2.2.3 watchdog==6.0.0 python-dotenv==1.0.1 Flask==3.0.3 -Flask-Session==0.8.0 \ No newline at end of file +Flask-Session==0.8.0 +gunicorn==22.0.0 +psycopg2-binary==2.9.9 \ No newline at end of file diff --git a/store_main.py b/store_main.py index 9a9afc6448..c57ceee2ef 100644 --- a/store_main.py +++ b/store_main.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import flask from datetime import datetime import requests @@ -11,15 +12,10 @@ import os import os.path import re -from InDMDevDB import * -from purchase import * -from InDMCategories import * from telebot.types import LabeledPrice, PreCheckoutQuery, SuccessfulPayment, ShippingOption import json from dotenv import load_dotenv - -# Load environment variables -load_dotenv('config.env') +import psycopg2 # Configure logging logging.basicConfig( @@ -32,73 +28,798 @@ ) logger = logging.getLogger(__name__) -# M""M M"""""""`YM M""""""'YMM M"""""`'"""`YM M""""""'YMM MM""""""""`M M""MMMMM""M -# M M M mmmm. M M mmmm. `M M mm. mm. M M mmmm. `M MM mmmmmmmM M MMMMM M -# M M M MMMMM M M MMMMM M M MMM MMM M M MMMMM M M` MMMM M MMMMP M -# M M M MMMMM M M MMMMM M M MMM MMM M M MMMMM M MM MMMMMMMM M MMMM' .M -# M M M MMMMM M M MMMM' .M M MMM MMM M M MMMM' .M MM MMMMMMMM M MMP' .MM -# M M M MMMMM M M .MM M MMM MMM M M .MM MM .M M .dMMM -# MMMM MMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM MMMMMMMMMMM - -# Flask connection -flask_app = Flask(__name__) -flask_app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secret-key-here') +# Load environment variables +load_dotenv('config.env') -# Bot connection -webhook_url = os.getenv('NGROK_HTTPS_URL') -bot_token = os.getenv('TELEGRAM_BOT_TOKEN') +# Bot instance +bot = telebot.TeleBot(os.getenv('TELEGRAM_BOT_TOKEN'), threaded=False) store_currency = os.getenv('STORE_CURRENCY', 'USD') -if not webhook_url or not bot_token: - logger.error("Missing required environment variables: NGROK_HTTPS_URL or TELEGRAM_BOT_TOKEN") - exit(1) - -bot = telebot.TeleBot(bot_token, threaded=False) - -# Set up webhook -try: - bot.remove_webhook() - bot.set_webhook(url=webhook_url) - logger.info(f"Webhook set successfully to {webhook_url}") -except Exception as e: - logger.error(f"Failed to set webhook: {e}") - exit(1) - +# Database +DATABASE_URL = os.getenv("DATABASE_URL") +logger.info(f"DATABASE_URL: {DATABASE_URL}") -# Process webhook calls -logger.info("Shop Started!") +if not DATABASE_URL: + raise ValueError("DATABASE_URL environment variable not set. Please set it in your Render environment.") -@flask_app.route('/', methods=['GET', 'POST']) -def webhook(): - """Handle incoming webhook requests from Telegram""" - try: - if flask.request.headers.get('content-type') == 'application/json': - json_string = flask.request.get_data().decode('utf-8') - update = telebot.types.Update.de_json(json_string) - bot.process_new_updates([update]) - return '' - else: - logger.warning("Invalid content type in webhook request") - flask.abort(403) - except Exception as e: - logger.error(f"Error processing webhook: {e}") - flask.abort(500) +def get_db_connection(): + """Establish and return a database connection""" + conn = psycopg2.connect(DATABASE_URL) + return conn -# Initialize payment settings -def get_payment_api_key(): - """Get payment API key from database""" - try: - api_key = GetDataFromDB.GetPaymentMethodTokenKeysCleintID("Bitcoin") - return api_key - except Exception as e: - logger.error(f"Error getting payment API key: {e}") - return None - -NOWPAYMENTS_API_KEY = get_payment_api_key() -BASE_CURRENCY = store_currency +class DBManager: + @staticmethod + def initialize_database(): + conn = get_db_connection() + if conn: + try: + cur = conn.cursor() + cur.execute(""" + CREATE TABLE IF NOT EXISTS users ( + id BIGINT PRIMARY KEY, + usname VARCHAR(255), + wallet INTEGER DEFAULT 0 + ); + """) + cur.execute(""" + CREATE TABLE IF NOT EXISTS admins ( + id BIGINT PRIMARY KEY, + usname VARCHAR(255) + ); + """) + cur.execute(""" + CREATE TABLE IF NOT EXISTS products ( + productnumber BIGINT PRIMARY KEY, + adminid BIGINT, + adminusname VARCHAR(255), + productname VARCHAR(255), + productdescription TEXT, + productprice NUMERIC(10, 2), + productimagelink TEXT, + productcategory VARCHAR(255), + productkeysfile TEXT, + productquantity INTEGER, + productdownloadlink TEXT + ); + """) + cur.execute(""" + CREATE TABLE IF NOT EXISTS orders ( + ordernumber BIGINT PRIMARY KEY, + buyerid BIGINT, + buyerusername VARCHAR(255), + productname VARCHAR(255), + productprice NUMERIC(10, 2), + orderdate TIMESTAMP, + paidmethod VARCHAR(255), + productdownloadlink TEXT, + productkeys TEXT, + productnumber BIGINT, + payment_id VARCHAR(255), + buyercomment TEXT + ); + """) + cur.execute(""" + CREATE TABLE IF NOT EXISTS categories ( + categorynumber BIGINT PRIMARY KEY, + categoryname VARCHAR(255) + ); + """) + cur.execute(""" + CREATE TABLE IF NOT EXISTS paymentmethods ( + methodname VARCHAR(255) PRIMARY KEY, + adminid BIGINT, + adminusname VARCHAR(255), + token_clientid_keys TEXT, + sectret_keys TEXT + ); + """) + conn.commit() + logger.info("Database tables initialized successfully.") + except psycopg2.Error as e: + logger.error(f"Error initializing database tables: {e}") + conn.rollback() + finally: + cur.close() + conn.close() + +DBManager.initialize_database() + +class CreateDatas: + """Database data creation and insertion operations""" + + @staticmethod + def AddAuser(user_id, username): + """Add a new user to the database or do nothing if user exists.""" + conn = get_db_connection() + cur = conn.cursor() + cur.execute("INSERT INTO users (id, usname, wallet) VALUES (%s, %s, %s) ON CONFLICT (id) DO NOTHING", (user_id, username, 0)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def AddAdmin(admin_id, username): + """Add a new admin to the database or do nothing if admin exists.""" + conn = get_db_connection() + cur = conn.cursor() + cur.execute("INSERT INTO admins (id, usname) VALUES (%s, %s) ON CONFLICT (id) DO NOTHING", (admin_id, username)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def AddProduct(productnumber, admin_id, username): + """Add a new product with default values.""" + conn = get_db_connection() + cur = conn.cursor() + cur.execute(""" + INSERT INTO products + (productnumber, adminid, adminusname, productname, productdescription, productprice, productimagelink, productdownloadlink, productkeysfile, productquantity, productcategory) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + """, (productnumber, admin_id, username, 'NIL', 'NIL', 0, 'NIL', 'https://nil.nil', 'NIL', 0, 'Default Category')) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def AddOrder(buyer_id, username, productname, productprice, orderdate, paidmethod, productdownloadlink, productkeys, ordernumber, productnumber, payment_id): + """Add a new order to the database.""" + conn = get_db_connection() + cur = conn.cursor() + cur.execute(""" + INSERT INTO orders + (buyerid, buyerusername, productname, productprice, orderdate, paidmethod, productdownloadlink, productkeys, buyercomment, ordernumber, productnumber, payment_id) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + """, (buyer_id, username, productname, productprice, orderdate, paidmethod, productdownloadlink, productkeys, 'NIL', ordernumber, productnumber, payment_id)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def AddCategory(categorynumber, categoryname): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("INSERT INTO categories (categorynumber, categoryname) VALUES (%s, %s) ON CONFLICT (categorynumber) DO NOTHING", (categorynumber, categoryname)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def AddPaymentMethod(id, username, method_name): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("INSERT INTO paymentmethods (adminid, adminusname, methodname) VALUES (%s, %s, %s) ON CONFLICT (methodname) DO NOTHING", (id, username, method_name)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateOrderConfirmed(paidmethod, ordernumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE orders SET paidmethod = %s WHERE ordernumber = %s", (paidmethod, ordernumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdatePaymentMethodToken(id, username, token_keys_clientid, method_name): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE paymentmethods SET adminid = %s, adminusname = %s, token_clientid_keys = %s WHERE method_name = %s", (id, username, token_keys_clientid, method_name)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdatePaymentMethodSecret(id, username, secret_keys, method_name): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE paymentmethods SET adminid = %s, adminusname = %s, sectret_keys = %s WHERE method_name = %s", (id, username, secret_keys, method_name)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def Update_A_Category(categoryname, categorynumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE categories SET categoryname = %s WHERE categorynumber = %s", (categoryname, categorynumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateOrderComment(buyercomment, ordernumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE orders SET buyercomment = %s WHERE ordernumber = %s", (buyercomment, ordernumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateOrderPaymentMethod(paidmethod, ordernumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE orders SET paidmethod = %s WHERE ordernumber = %s", (paidmethod, ordernumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateOrderPurchasedKeys(productkeys, ordernumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE orders SET productkeys = %s WHERE ordernumber = %s", (productkeys, ordernumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateProductName(productname, productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productname = %s WHERE productnumber = %s", (productname, productnumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateProductDescription(productdescription, productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productdescription = %s WHERE productnumber = %s", (productdescription, productnumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateProductPrice(productprice, productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productprice = %s WHERE productnumber = %s", (productprice, productnumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateProductproductimagelink(productimagelink, productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productimagelink = %s WHERE productnumber = %s", (productimagelink, productnumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateProductproductdownloadlink(productdownloadlink, productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productdownloadlink = %s WHERE productnumber = %s", (productdownloadlink, productnumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateProductKeysFile(productkeysfile, productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productkeysfile = %s WHERE productnumber = %s", (productkeysfile, productnumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateProductQuantity(productquantity, productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productquantity = %s WHERE productnumber = %s", (productquantity, productnumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def UpdateProductCategory(productcategory, productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productcategory = %s WHERE productnumber = %s", (productcategory, productnumber)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def Update_All_ProductCategory(new_category, productcategory): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("UPDATE products SET productcategory = %s WHERE productcategory = %s", (new_category, productcategory)) + conn.commit() + cur.close() + conn.close() + +class GetDataFromDB: + """Database query operations""" + + @staticmethod + def GetUserWalletInDB(userid): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT wallet FROM users WHERE id = %s", (userid,)) + result = cur.fetchone() + cur.close() + conn.close() + return result[0] if result else 0 + + @staticmethod + def GetUserNameInDB(userid): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT usname FROM users WHERE id = %s", (userid,)) + shopuser = cur.fetchone() + cur.close() + conn.close() + return shopuser[0] if shopuser else "" + + @staticmethod + def GetAdminNameInDB(userid): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT usname FROM admins WHERE id = %s", (userid,)) + shopuser = cur.fetchone() + cur.close() + conn.close() + return shopuser[0] if shopuser else "" + + @staticmethod + def GetUserIDsInDB(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT id FROM users") + shopuser = cur.fetchall() + cur.close() + conn.close() + return shopuser + + @staticmethod + def GetProductName(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productname FROM products WHERE productnumber = %s", (productnumber,)) + productname = cur.fetchone() + cur.close() + conn.close() + return productname[0] if productname else None + + @staticmethod + def GetProductDescription(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productdescription FROM products WHERE productnumber = %s", (productnumber,)) + productdescription = cur.fetchone() + cur.close() + conn.close() + return productdescription[0] if productdescription else None + + @staticmethod + def GetProductPrice(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productprice FROM products WHERE productnumber = %s", (productnumber,)) + productprice = cur.fetchone() + cur.close() + conn.close() + return productprice[0] if productprice else None + + @staticmethod + def GetProductImageLink(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productimagelink FROM products WHERE productnumber = %s", (productnumber,)) + productimagelink = cur.fetchone() + cur.close() + conn.close() + return productimagelink[0] if productimagelink else None + + @staticmethod + def GetProductDownloadLink(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productdownloadlink FROM products WHERE productnumber = %s", (productnumber,)) + productdownloadlink = cur.fetchone() + cur.close() + conn.close() + return productdownloadlink[0] if productdownloadlink else None + + @staticmethod + def GetProductNumber(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productnumber FROM products WHERE productnumber = %s", (productnumber,)) + productnumbers = cur.fetchone() + cur.close() + conn.close() + return productnumbers[0] if productnumbers else None + + @staticmethod + def GetProductQuantity(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productquantity FROM products WHERE productnumber = %s", (productnumber,)) + productquantity = cur.fetchone() + cur.close() + conn.close() + return productquantity[0] if productquantity else None + + @staticmethod + def GetProduct_A_Category(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productcategory FROM products WHERE productnumber = %s", (productnumber,)) + productcategory = cur.fetchone() + cur.close() + conn.close() + return productcategory[0] if productcategory else None + + @staticmethod + def Get_A_CategoryName(categorynumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT categoryname FROM categories WHERE categorynumber = %s", (categorynumber,)) + productcategory = cur.fetchone() + cur.close() + conn.close() + return productcategory[0] if productcategory else None + + @staticmethod + def GetCategoryIDsInDB(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT categorynumber, categoryname FROM categories") + categories = cur.fetchall() + cur.close() + conn.close() + return categories + + @staticmethod + def GetCategoryNumProduct(productcategory): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT COUNT(*) FROM products WHERE productcategory = %s", (productcategory,)) + categories = cur.fetchall() + cur.close() + conn.close() + return categories + + @staticmethod + def GetProduct_A_AdminID(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT adminid FROM products WHERE productnumber = %s", (productnumber,)) + admin_id = cur.fetchone() + cur.close() + conn.close() + return admin_id[0] if admin_id else None + + @staticmethod + def GetAdminIDsInDB(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT id FROM admins") + shopadmin = cur.fetchall() + cur.close() + conn.close() + return shopadmin + + @staticmethod + def GetAdminUsernamesInDB(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT usname FROM admins") + shopadmin = cur.fetchall() + cur.close() + conn.close() + return shopadmin + + @staticmethod + def GetProductNumberName(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productnumber, productname FROM products") + productnumbers_name = cur.fetchall() + cur.close() + conn.close() + return productnumbers_name + + @staticmethod + def GetProductInfos(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productnumber, productname, productprice FROM products") + productnumbers_name = cur.fetchall() + cur.close() + conn.close() + return productnumbers_name + + @staticmethod + def GetProductInfo(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory FROM products") + productnumbers_name = cur.fetchall() + cur.close() + conn.close() + return productnumbers_name + + @staticmethod + def GetProductInfoByCTGName(productcategory): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory FROM products WHERE productcategory = %s", (productcategory,)) + productnumbers_name = cur.fetchall() + cur.close() + conn.close() + return productnumbers_name + + @staticmethod + def GetProductInfoByPName(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory FROM products WHERE productnumber = %s", (productnumber,)) + productnumbers_name = cur.fetchall() + cur.close() + conn.close() + return productnumbers_name + + @staticmethod + def GetUsersInfo(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT id, usname, wallet FROM users") + user_infos = cur.fetchall() + cur.close() + conn.close() + return user_infos + + @staticmethod + def AllUsers(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT COUNT(id) FROM users") + alluser = cur.fetchall() + cur.close() + conn.close() + return alluser if alluser else 0 + + @staticmethod + def AllAdmins(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT COUNT(id) FROM admins") + alladmin = cur.fetchall() + cur.close() + conn.close() + return alladmin if alladmin else 0 + + @staticmethod + def AllProducts(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT COUNT(productnumber) FROM products") + allproduct = cur.fetchall() + cur.close() + conn.close() + return allproduct if allproduct else 0 + + @staticmethod + def AllOrders(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT COUNT(ordernumber) FROM orders") + allorder = cur.fetchall() + cur.close() + conn.close() + return allorder if allorder else 0 + + @staticmethod + def GetAdminsInfo(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT id, usname, wallet FROM admins") + admin_infos = cur.fetchall() + cur.close() + conn.close() + return admin_infos + + @staticmethod + def GetOrderInfo(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT ordernumber, productname, buyerusername FROM orders") + order_infos = cur.fetchall() + cur.close() + conn.close() + return order_infos + + @staticmethod + def GetPaymentMethods(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT method_name, adminusname FROM paymentmethods") # 'activated' column doesn't exist + payment_method = cur.fetchall() + cur.close() + conn.close() + return payment_method + + @staticmethod + def GetPaymentMethodsAll(method_name): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT methodname, token_clientid_keys, sectret_keys FROM paymentmethods WHERE methodname = %s", (method_name,)) + payment_method = cur.fetchall() + cur.close() + conn.close() + return payment_method + + @staticmethod + def GetPaymentMethodTokenKeysCleintID(method_name): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT token_clientid_keys FROM paymentmethods WHERE methodname = %s", (method_name,)) + payment_method = cur.fetchone() + cur.close() + conn.close() + return payment_method[0] if payment_method else None + + @staticmethod + def GetPaymentMethodSecretKeys(method_name): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT sectret_keys FROM paymentmethods WHERE methodname = %s", (method_name,)) + payment_method = cur.fetchone() + cur.close() + conn.close() + return payment_method[0] if payment_method else None + + @staticmethod + def GetAllPaymentMethodsInDB(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT methodname FROM paymentmethods") + payment_methods = cur.fetchall() + cur.close() + conn.close() + return payment_methods + + @staticmethod + def GetProductCategories(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT DISTINCT productcategory FROM products") + productcategory = cur.fetchall() + cur.close() + conn.close() + return productcategory + + @staticmethod + def GetProductIDs(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT productnumber FROM products") + productnumbers = cur.fetchall() + cur.close() + conn.close() + return productnumbers + + @staticmethod + def GetOrderDetails(ordernumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT buyerid, buyerusername, productname, productprice, orderdate, paidmethod, productdownloadlink, productkeys, buyercomment, ordernumber, productnumber FROM orders WHERE ordernumber = %s AND paidmethod != 'NO'", (ordernumber,)) + order_details = cur.fetchall() + cur.close() + conn.close() + return order_details + + @staticmethod + def GetOrderIDs_Buyer(buyerid): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT ordernumber FROM orders WHERE buyerid = %s AND paidmethod != 'NO'", (buyerid,)) + productnumbers = cur.fetchall() + cur.close() + conn.close() + return productnumbers + + @staticmethod + def GetOrderIDs(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT ordernumber FROM orders") + productnumbers = cur.fetchall() + cur.close() + conn.close() + return productnumbers + + @staticmethod + def GetAllUnfirmedOrdersUser(buyerid): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("SELECT ordernumber, productname, buyerusername, payment_id, productnumber FROM orders WHERE paidmethod = 'NO' AND buyerid = %s AND payment_id != ordernumber", (buyerid,)) + payment_method = cur.fetchall() + cur.close() + conn.close() + return payment_method + +class CleanData: + """Database data deletion operations""" + + @staticmethod + def CleanShopUserTable(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("DELETE FROM users") + conn.commit() + cur.close() + conn.close() + + @staticmethod + def CleanShopProductTable(): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("DELETE FROM products") + conn.commit() + cur.close() + conn.close() + + @staticmethod + def delete_a_product(productnumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("DELETE FROM products WHERE productnumber = %s", (productnumber,)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def delete_an_order(ordernumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("DELETE FROM orders WHERE ordernumber = %s", (ordernumber,)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def delete_a_payment_method(method_name): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("DELETE FROM paymentmethods WHERE methodname = %s", (method_name,)) + conn.commit() + cur.close() + conn.close() + + @staticmethod + def delete_a_category(categorynumber): + conn = get_db_connection() + cur = conn.cursor() + cur.execute("DELETE FROM categories WHERE categorynumber = %s", (categorynumber,)) + conn.commit() + cur.close() + conn.close() + +# Set webhook +WEBHOOK_URL = os.getenv("RENDER_EXTERNAL_URL") +if WEBHOOK_URL: + logger.info(f"Found RENDER_EXTERNAL_URL: {WEBHOOK_URL}") + bot.remove_webhook() + time.sleep(0.5) + bot.set_webhook(url=WEBHOOK_URL) + logger.info("Webhook set successfully to the Render external URL.") +else: + logger.info("RENDER_EXTERNAL_URL not set. Assuming local development (polling).") -# Create main keyboard +# Utils def create_main_keyboard(): """Create the main user keyboard""" keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) @@ -110,328 +831,36 @@ def create_main_keyboard(): keyboard.add(key2, key3) return keyboard -keyboard = create_main_keyboard() - - -##################WELCOME MESSAGE + BUTTONS START######################### -#Function to list Products and Categories -@bot.callback_query_handler(func=lambda call: True) -def callback_query(call): - """Handle callback queries from inline keyboards""" - try: - if call.data.startswith("getcats_"): - input_catees = call.data.replace('getcats_','') - CategoriesDatas.get_category_products(call, input_catees) - elif call.data.startswith("getproduct_"): - input_cate = call.data.replace('getproduct_','') - UserOperations.purchase_a_products(call, input_cate) - elif call.data.startswith("managecats_"): - input_cate = call.data.replace('managecats_','') - manage_categoriesbutton(call, input_cate) +# Purchase +class UserOperations: + def shop_items(message): + id = message.from_user.id + usname = message.chat.username + products_list = GetDataFromDB.GetProductInfo() + id = message.from_user.id + all_categories = GetDataFromDB.GetCategoryIDsInDB() + keyboard = types.InlineKeyboardMarkup() + if all_categories == []: + bot.send_message(id, "⚠️ No Product available at the moment, kindly check back soon") else: - logger.warning(f"Unknown callback data: {call.data}") - except Exception as e: - logger.error(f"Error handling callback query: {e}") - bot.send_message(call.message.chat.id, "An error occurred. Please try again.") - - -#Function to list Products -def is_product_command(message): - """Check if message is a product command""" - try: - pattern = r'/\d{8}$' - return bool(re.match(pattern, message)) - except Exception as e: - logger.error(f"Error checking product command: {e}") - return False -@bot.message_handler(content_types=["text"], func=lambda message: is_product_command(message.text)) -def products_get(message): - """Handle product selection""" - try: - UserOperations.purchase_a_products(message) - except Exception as e: - logger.error(f"Error processing product selection: {e}") - bot.send_message(message.chat.id, "Error processing your request. Please try again.") -#Start command handler and function -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Home 🏘") -@bot.message_handler(commands=['start']) -def send_welcome(message): - try: - print(NOWPAYMENTS_API_KEY) - 1==1 - try: - id = message.from_user.id - usname = message.chat.username - admins = GetDataFromDB.GetAdminIDsInDB() - user_s = GetDataFromDB.AllUsers() - for a_user_s in user_s: - all_user_s = a_user_s[0] - admin_s = GetDataFromDB.AllAdmins() - for a_admin_s in admin_s: - all_admin_s = a_admin_s[0] - product_s = GetDataFromDB.AllProducts() - for a_product_s in product_s: - all_product_s = a_product_s[0] - orders_s = GetDataFromDB.AllOrders() - for a_orders_s in orders_s: - all_orders_s = a_orders_s[0] - - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - - if admins == []: - users = GetDataFromDB.GetUserIDsInDB() - if f"{id}" not in f"{users}": - CreateDatas.AddAuser(id,usname) - user_type = "Shop Admin" - CreateDatas.AddAdmin(id,usname) - key0 = types.KeyboardButton(text="Manage Products πŸ’Ό") - key1 = types.KeyboardButton(text="Manage Categories πŸ’Ό") - key2 = types.KeyboardButton(text="Manage Orders πŸ›") - key3 = types.KeyboardButton(text="Payment Methods πŸ’³") - key4 = types.KeyboardButton(text="News To Users πŸ“£") - key5 = types.KeyboardButton(text="Switch To User πŸ™β€β™‚οΈ") - keyboardadmin.add(key0) - keyboardadmin.add(key1, key2) - keyboardadmin.add(key3, key4) - keyboardadmin.add(key5) - store_statistics = f"βž–βž–βž–Store's Statistics πŸ“Šβž–βž–βž–\n\n\nTotal Users πŸ™β€β™‚οΈ: {all_user_s}\n\nTotal Admins 🀴: {all_admin_s}\n\nTotal Products 🏷: {all_product_s}\n\nTotal Orders πŸ›: {all_orders_s}\n\n\nβž–βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–" - user_data = "0" - bot.send_photo(chat_id=message.chat.id, photo="https://i.ibb.co/9vctwpJ/IMG-1235.jpg", caption=f"Dear {user_type},\n\nYour Wallet Balance: $ {user_data} πŸ’° \n\n{store_statistics}", reply_markup=keyboardadmin) - elif f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - users = GetDataFromDB.GetUserIDsInDB() - if f"{id}" not in f"{users}": - CreateDatas.AddAuser(id,usname) - user_type = "Shop Admin" - key0 = types.KeyboardButton(text="Manage Products πŸ’Ό") - key1 = types.KeyboardButton(text="Manage Categories πŸ’Ό") - key2 = types.KeyboardButton(text="Manage Orders πŸ›") - key3 = types.KeyboardButton(text="Payment Methods πŸ’³") - key4 = types.KeyboardButton(text="News To Users πŸ“£") - key5 = types.KeyboardButton(text="Switch To User πŸ™β€β™‚οΈ") - keyboardadmin.add(key0) - keyboardadmin.add(key1, key2) - keyboardadmin.add(key3, key4) - keyboardadmin.add(key5) - - store_statistics = f"βž–βž–βž–Store's Statistics πŸ“Šβž–βž–βž–\n\n\nTotal Users πŸ™β€β™‚οΈ: {all_user_s}\n\nTotal Admins 🀴: {all_admin_s}\n\nTotal Products 🏷: {all_product_s}\n\nTotal Orders πŸ›: {all_orders_s}\n\n\nβž–βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–" - user_data = "0" - bot.send_photo(chat_id=message.chat.id, photo="https://i.ibb.co/9vctwpJ/IMG-1235.jpg", caption=f"Dear {user_type},\n\nWelcome! 🀝\n\n{store_statistics}", reply_markup=keyboardadmin) - - else: - users = GetDataFromDB.GetUserIDsInDB() - if f"{id}" in f"{users}": - user_type = "Customer" - user_data = GetDataFromDB.GetUserWalletInDB(id) - else: - CreateDatas.AddAuser(id,usname) - user_type = "Customer" - user_data = GetDataFromDB.GetUserWalletInDB(id) - bot.send_photo(chat_id=message.chat.id, photo="https://i.ibb.co/9vctwpJ/IMG-1235.jpg", caption=f"Dear {user_type},\n\nWelcome! 🀝\n\nBrowse our products, make purchases, and enjoy fast delivery! \nType /browse to start shopping. \n\nπŸ’¬ Need help? \nContact our support team anytime.", reply_markup=keyboard) - except Exception as e: - print(e) - admin_switch_user(message) - except Exception as e: - print(e) + for catnum, catname in all_categories: + c_catname = catname.upper() + products_category = GetDataFromDB.GetCategoryNumProduct(c_catname) + for ctg in products_category: + products_in_category = ctg[0] + text_but = f"🏷 {catname} ({products_in_category})" + text_cal = f"getcats_{catnum}" + keyboard.add(types.InlineKeyboardButton(text=text_but, callback_data=text_cal)) -#Switch admin to user handler -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Switch To User πŸ™β€β™‚οΈ") -def admin_switch_user(message): - id = message.from_user.id - usname = message.chat.username - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - - users = GetDataFromDB.GetUserIDsInDB() - if f"{id}" in f"{users}": - user_type = "Customer" - key1 = types.KeyboardButton(text="Shop Items πŸ›’") - key2 = types.KeyboardButton(text="My Orders πŸ›") - key3 = types.KeyboardButton(text="Support πŸ“ž") - key4 = types.KeyboardButton(text="Home 🏘") - keyboard.add(key1) - keyboard.add(key2, key3) - keyboard.add(key4) - user_data = GetDataFromDB.GetUserWalletInDB(id) - else: - CreateDatas.AddAuser(id,usname) - user_type = "Customer" - key1 = types.KeyboardButton(text="Shop Items πŸ›’") - key2 = types.KeyboardButton(text="My Orders πŸ›") - key3 = types.KeyboardButton(text="Support πŸ“ž") - key4 = types.KeyboardButton(text="Home 🏘") - keyboard.add(key1) - keyboard.add(key2, key3) - keyboard.add(key4) - user_data = GetDataFromDB.GetUserWalletInDB(id) - bot.send_photo(chat_id=message.chat.id, photo="https://i.ibb.co/9vctwpJ/IMG-1235.jpg", caption=f"Dear {user_type},\n\nYour Wallet Balance: $ {user_data} πŸ’° \n\nBrowse our products, make purchases, and enjoy fast delivery! \nType /browse to start shopping. \n\nπŸ’¬ Need help? \nContact our support team anytime.", reply_markup=keyboard) - bot.send_message(id, "You are on User Mode βœ…\nSend /start command or press Home 🏘 button to switch back to Admin Mode", reply_markup=keyboard) - -#Command handler to manage products -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Manage Products πŸ’Ό") -def ManageProducts(message): - id = message.from_user.id - name = message.from_user.first_name - usname = message.chat.username - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="Add New Product βž•") - key2 = types.KeyboardButton(text="List Product 🏷") - key3 = types.KeyboardButton(text="Delete Product πŸ—‘οΈ") - key4 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2, key3) - keyboardadmin.add(key4) - - bot.send_message(id, "Choose an action to perform βœ…", reply_markup=keyboardadmin) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Command handler to add product -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Add New Product βž•") -def AddProductsMNG(message): - id = message.from_user.id - name = message.from_user.first_name - usname = message.chat.username - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - msg = bot.send_message(id, "Reply With Your Product Name or Tittle: βœ…") - new_product_number = random.randint(10000000,99999999) - productnumber = f"{new_product_number}" - CreateDatas.AddProduct(productnumber, id, usname) - global productnumbers - productnumbers = productnumber - bot.register_next_step_handler(msg, add_a_product_name) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Function to add product name -def add_a_product_name(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - try: - id = message.from_user.id - productname = message.text - msg = bot.send_message(id, "Reply With Your Product Description: βœ…") - CreateDatas.UpdateProductName(productname, productnumbers) - bot.register_next_step_handler(msg, add_a_product_decription) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, add_a_product_name) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Function to add product describtion -def add_a_product_decription(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - try: - id = message.from_user.id - description = message.text - msg = bot.send_message(id, "Reply With Your Product Price: βœ…") - CreateDatas.UpdateProductDescription(description, productnumbers) - bot.register_next_step_handler(msg, add_a_product_price) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, add_a_product_decription) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) + bot.send_message(id, "CATEGORIES:", reply_markup=keyboard) + bot.send_message(id, "List completed βœ…", reply_markup=types.ReplyKeyboardRemove()) + for productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory in products_list: + list_m = [productnumber, productname, productprice] -#Function to add product price -def add_a_product_price(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - try: - id = message.from_user.id - price = message.text - msg = bot.send_message(id, "Attach Your Product Photo: βœ…") - CreateDatas.UpdateProductPrice(price, productnumbers) - bot.register_next_step_handler(msg, add_a_product_photo_link) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, add_a_product_price) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Function to add product photo -def add_a_product_photo_link(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - try: - id = message.from_user.id - image_link = message.photo[0].file_id - all_categories = GetDataFromDB.GetCategoryIDsInDB() - if all_categories == []: - msg = bot.send_message(id, "Please reply with a new category's name") - CreateDatas.UpdateProductproductimagelink(image_link, productnumbers) - bot.register_next_step_handler(msg, add_a_product_category) - else: - bot.send_message(id, f"CATEGORIES πŸ‘‡") - for catnum, catname in all_categories: - bot.send_message(id, f"{catname} - ID: /{catnum} βœ…") - - msg = bot.send_message(id, "Click on a Category ID to select Category for this Product: βœ…\n\n⚠️Or Write A New Category", reply_markup=types.ReplyKeyboardRemove()) - CreateDatas.UpdateProductproductimagelink(image_link, productnumbers) - bot.register_next_step_handler(msg, add_a_product_category) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, add_a_product_photo_link) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Function to add product category -def add_a_product_category(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": + def purchase_a_products(message, input_cate): + id = message.from_user.id keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) keyboard.row_width = 2 - id = message.from_user.id - input_cat = message.text - all_categories = GetDataFromDB.GetCategoryIDsInDB() - input_cate = input_cat[1:99] - - categories = [] - for catnum, catname in all_categories: - catnames = catname.upper() - categories.append(catnames) - def checkint(): try: input_cat = int(input_cate) @@ -439,610 +868,28 @@ def checkint(): except: return input_cate - input_category = checkint() - if isinstance(input_category, int) == True: - product_cate = GetDataFromDB.Get_A_CategoryName(input_category) - product_category = product_cate.upper() - if f"{product_category}" not in f"{categories}" or f"{product_category}" == "NONE": - msg = bot.send_message(id, "Please reply with a new category's name", reply_markup=types.ReplyKeyboardRemove()) - bot.register_next_step_handler(msg, add_a_product_category) - elif f"{product_category}" in f"{categories}": - msg = bot.send_message(id, "Attach Your Producy Keys In A Text File: βœ…\n\n⚠️ Please Arrange Your Product Keys In the Text File, One Product Key Per Line In The File\n\n\n⚠️ Reply With Skip to skip this step if this Product has no Product Keys") - CreateDatas.UpdateProductCategory(product_category, productnumbers) - bot.register_next_step_handler(msg, add_a_product_keys_file) - else: - new_category_number = random.randint(1000,9999) - input_cate = input_cat.upper() - CreateDatas.AddCategory(new_category_number, input_cate) - bot.send_message(id, f"New Category created successfully - {input_cat}") - msg = bot.send_message(id, "Attach Your Producy Keys In A Text File: βœ…\n\n⚠️ Please Arrange Your Product Keys In the Text File, One Product Key Per Line In The File\n\n\n⚠️ Reply With Skip to skip this step if this Product has no Product Keys") - CreateDatas.UpdateProductCategory(input_cate, productnumbers) - bot.register_next_step_handler(msg, add_a_product_keys_file) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Function to add product file for keys -def add_a_product_keys_file(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - try: - id = message.from_user.id - if message.text and message.text.upper() == "SKIP": - msg = bot.send_message(id, "Reply With Download Link For This Product\n\nThis will be the Link customer will have access to after they have paid: βœ…\n\n\n⚠️ Reply With Skip to skip this step if this Product has no Product Download Link") - bot.register_next_step_handler(msg, add_a_product_download_link) - elif message.document: - keys_folder = "Keys" - if not "Keys" in os.listdir(): - try: - os.mkdir("Keys") - except Exception as e: - print(e) - else: - pass - KeysFiles = f"{keys_folder}/{productnumbers}.txt" - file = message.document - file_info = bot.get_file(file.file_id) - file_path = file_info.file_path - file_name = os.path.join(f"{KeysFiles}") - downloaded_file = bot.download_file(file_path) - with open(file_name, 'wb') as new_file: - new_file.write(downloaded_file) - bot.reply_to(message, f'File f"{productnumbers}.txt" saved successfully.') - CreateDatas.UpdateProductKeysFile(KeysFiles, productnumbers) - quantity = open(file_name, 'r').read().splitlines() - with open(file_name, 'r') as all: - all_quantity = all.read() - all_quantities = len(all_quantity.split('\n')) - CreateDatas.UpdateProductQuantity(all_quantities, productnumbers) - msg = bot.send_message(id, "Reply With Download Link For This Product\n\nThis will be the Link customer will have access to after they have paid: βœ…\n\n\n⚠️ Reply With Skip to skip this step if this Product has no Product Download Link") - bot.register_next_step_handler(msg, add_a_product_download_link) + input_product_id = checkint() + if isinstance(input_product_id, int) == True: + product_list = GetDataFromDB.GetProductInfoByPName(input_product_id) + if f"{input_product_id}" in f"{product_list}": + keyboard2 = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) + key1 = types.KeyboardButton(text="Bitcoin ΰΈΏ") + keyboard2.add(key1) + for productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory in product_list: + list_m = [productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory] + bot.send_message(id, "πŸ’‘ Select a Payment method to pay for this product πŸ‘‡", reply_markup=keyboard2) else: - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, add_a_product_keys_file) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, add_a_product_keys_file) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Function to add product download link -def add_a_product_download_link(message): - try: - id = message.from_user.id - download_link = message.text - if message.text and message.text.upper() == "SKIP": - bot.send_message(id, "Download Link Skipped βœ…") - else: - CreateDatas.UpdateProductproductdownloadlink(download_link, productnumbers) - CreateDatas.UpdateProductQuantity(int(100), productnumbers) - - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="Add New Product βž•") - key2 = types.KeyboardButton(text="List Product 🏷") - key3 = types.KeyboardButton(text="Delete Product πŸ—‘οΈ") - key4 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2, key3) - keyboardadmin.add(key4) - productimage = GetDataFromDB.GetProductImageLink(productnumbers) - productname = GetDataFromDB.GetProductName(productnumbers) - productnumber = GetDataFromDB.GetProductNumber(productnumbers) - productdescription = GetDataFromDB.GetProductDescription(productnumbers) - productprice = GetDataFromDB.GetProductPrice(productnumbers) - productquantity = GetDataFromDB.GetProductQuantity(productnumbers) - captions = f"\n\n\nProduct Tittle: {productname}\n\n\nProduct Number: `{productnumber}`\n\n\nProduct Price: {productprice} {store_currency} πŸ’°\n\n\nQuantity Avaialble: {productquantity} \n\n\nProduct Description: {productdescription}" - bot.send_photo(chat_id=message.chat.id, photo=f"{productimage}", caption=f"{captions}", parse_mode='Markdown') - bot.send_message(id, "Product Successfully Added βœ…\n\nWhat will you like to do next ?", reply_markup=keyboardadmin) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, add_a_product_download_link) + print("Wrong command !!!") -#Command handler and functions to delete product -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Delete Product πŸ—‘οΈ") -def DeleteProductsMNG(message): - try: +# Categories +class CategoriesDatas: + def get_category_products(message, input_cate): id = message.from_user.id - - - admins = GetDataFromDB.GetAdminIDsInDB() - productnumber_name = GetDataFromDB.GetProductNumberName() - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - if productnumber_name == []: - msg = bot.send_message(id, "No product available, please send /start command to start creating products") - bot.register_next_step_handler(msg, send_welcome) - else: - bot.send_message(id, f"πŸ‘‡Product ID --- Product NameπŸ‘‡") - for pid, tittle in productnumber_name: - bot.send_message(id, f"/{pid} - `{tittle}`", parse_mode="Markdown") - msg = bot.send_message(id, "Click on a Product ID of the product you want to delete: βœ…", parse_mode="Markdown") - bot.register_next_step_handler(msg, delete_a_product) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - pass -def delete_a_product(message): - #try: - id = message.from_user.id - productnu = message.text - productnumber = productnu[1:99] - productnum = GetDataFromDB.GetProductIDs() - productnums = [] - for productn in productnum: - productnums.append(productn[0]) - print(productnums) - if int(productnumber) in productnums: - try: - global productnumbers - productnumbers = productnumber - except Exception as e: - print(e) - - - admins = GetDataFromDB.GetAdminIDsInDB() - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="Add New Product βž•") - key2 = types.KeyboardButton(text="List Product 🏷") - key3 = types.KeyboardButton(text="Delete Product πŸ—‘οΈ") - key4 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2, key3) - keyboardadmin.add(key4) - CleanData.delete_a_product(productnumber) - msg = bot.send_message(id, "Deleted successfully πŸ—‘οΈ\n\n\nWhat will you like to do next ?\n\nSelect one of buttons πŸ‘‡", reply_markup=keyboardadmin, parse_mode="Markdown") - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - else: - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, delete_a_product) - pass - #except Exception as e: - #print(e) - #msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - #bot.register_next_step_handler(msg, delete_a_product) - #pass - -#Command handler and fucntion to shop Items -@bot.message_handler(commands=['browse']) -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Shop Items πŸ›’") -def shop_items(message): - UserOperations.shop_items(message) - - -# Dictionary to store Bitcoint payment data -bitcoin_payment_data = {} - -# Function to get BTC amount for the given fiat amount -def get_btc_amount(fiat_amount, currency): - url = f'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies={currency.lower()}' - response = requests.get(url) - if response.status_code == 200: - price = response.json()['bitcoin'][currency.lower()] - btc_amount = int(fiat_amount) / int(price) - return btc_amount - else: - print(f"Error fetching BTC price: {response.status_code} - {response.text}") - return None - -# Function to create a new payment -def create_payment_address(btc_amount): - url = 'https://api.nowpayments.io/v1/payment' - headers = { - 'x-api-key': NOWPAYMENTS_API_KEY, - 'Content-Type': 'application/json' - } - data = { - 'price_amount': btc_amount, - 'price_currency': 'btc', - 'pay_currency': 'btc', - 'ipn_callback_url': 'https://api.nowpayments.io/ipn', - 'order_id': '5555555555', - 'order_description': 'Payment for Order' - } - response = requests.post(url, json=data, headers=headers) - if response.status_code == 201: - return response.json()['pay_address'], response.json()['payment_id'] - else: - print(f"Error creating payment address: {response.status_code} - {response.text}") - return None, None - -# Function to check the payment status -def check_payment_status(payment_id): - url = f'https://api.nowpayments.io/v1/payment/{payment_id}' - headers = { - 'x-api-key': NOWPAYMENTS_API_KEY - } - response = requests.get(url, headers=headers) - if response.status_code == 200: - return response.json()['payment_status'] - else: - print(f"Error checking payment status: {response.status_code} - {response.text}") - return None - - -# Command handler to pay with Bitcoin -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Bitcoin ΰΈΏ") -def bitcoin_pay_command(message): - id = message.from_user.id - username = message.from_user.username - - - order_info = UserOperations.orderdata() - new_order = order_info - new_orders = order_info - if f"{order_info}" == "None": - bot.send_message(id, "No order found !", reply_markup=keyboard, parse_mode="Markdown") - else: - if int(f"{order_info[6]}") < int(1): - bot.send_message(id, "This Item is soldout !!!", reply_markup=keyboard, parse_mode="Markdown") - else: - try: - fiat_amount = new_order[2] - btc_amount = get_btc_amount(fiat_amount, store_currency) - if btc_amount: - payment_address, payment_id = create_payment_address(btc_amount) - if payment_address and payment_id: - bitcoin_payment_data[message.from_user.id] = { - 'payment_id': payment_id, - 'address': payment_address, - 'status': 'waiting', - 'fiat_amount': fiat_amount, - 'btc_amount': btc_amount - } - try: - now = datetime.now() - orderdate = now.strftime("%Y-%m-%d %H:%M:%S") - ordernumber = random.randint(10000,99999) - paidmethod = "NO" - add_key = "NIL" - productdownloadlink = GetDataFromDB.GetProductDownloadLink(new_orders[0]) - - CreateDatas.AddOrder(id, username,new_orders[1], new_orders[2], orderdate, paidmethod, productdownloadlink, add_key, ordernumber, new_orders[0], payment_id) - except Exception as e: - print(e) - pass - keyboard2 = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard2.row_width = 2 - key1 = types.KeyboardButton(text="Check Payment Status βŒ›") - keyboard2.add(key1) - bot.send_message(id, f"Please send extact {btc_amount:.8f} BTC (approximately {fiat_amount} {store_currency}) to the following Bitcoin", reply_markup=types.ReplyKeyboardRemove()) - bot.send_message(message.chat.id, f"Address: `{payment_address}`", reply_markup=keyboard2, parse_mode='Markdown') - bot.send_message(message.chat.id, f"Please stay on this page and click on Check Payment Status βŒ› button until payment is confirmed", reply_markup=keyboard2, parse_mode='Markdown') - - else: - bot.send_message(message.chat.id, "Error creating payment address. Please try again later.\n\nOR Amount value is too small") - else: - bot.send_message(message.chat.id, "Error converting amount to BTC. Please try again later.") - except (IndexError, ValueError): - bot.send_message(message.chat.id, f"Invalid command.") - -# Command handler and function to Check bitcoin payment status -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Check Payment Status βŒ›") -def bitcoin_check_command(message): - id = message.from_user.id - orders = GetDataFromDB.GetAllUnfirmedOrdersUser(id) - if orders == [] or orders == "None": - bot.send_message(message.chat.id, "No order found !") - else: - for ordernumber, productname, buyerusername, payment_id, productnumber in orders: - status = check_payment_status(payment_id) - if status: - if status == 'finished': - try: - keys_folder = 'Keys' - keys_location = f"{keys_folder}/{productnumber}.txt" - all_key = open(f"{keys_location}", 'r').read().splitlines() - def keeys(): - if all_key == []: - return "NIL" - else: - return all_key - all_keys = keeys() - for a_key in all_keys: - 1==1 - productkeys = a_key - - name_file = keys_location - with open(f'{name_file}', 'r') as file: - lines = file.readlines() - with open(f'{name_file}', 'w') as file: - for line in lines: - if f"{productkeys}" not in line: - file.write(line) - file.truncate() - except: - pass - - def check_if_keys(): - try: - return productkeys - except: - return "NIL" - - add_key = check_if_keys() - - bot.send_message(message.chat.id, "Payment received and confirmed!") - CreateDatas.UpdateOrderPurchasedKeys(add_key, ordernumber) - CreateDatas.UpdateOrderPaymentMethod("Bitcoin", ordernumber) - product_list = GetDataFromDB.GetProductInfoByPName(productnumber) - for productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory in product_list: - list_m = [productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory] - new_quantity = int(f"{productquantity}") - int(1) - CreateDatas.UpdateProductQuantity(int(new_quantity), productnumber) - msg = bot.send_message(message.chat.id, "Payment successful βœ…") - msg = bot.send_message(message.chat.id, "Would you like to write a note to the Seller ?") - msg = bot.send_message(message.chat.id, "Reply with your note or reply with NIL to proceed") - global order_number - order_number = ordernumber - bot.register_next_step_handler(msg, complete_order) - else: - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - key1 = types.KeyboardButton(text="Check Payment Status βŒ›") - key2 = types.KeyboardButton(text="Home 🏘") - keyboard.add(key1) - keyboard.add(key2) - bot.send_message(message.chat.id, f"Your payment is {status} for Order ID: {ordernumber}", reply_markup=keyboard) - - else: - bot.send_message(message.chat.id, f"No order found with pending payment confirmation !") - bot.send_message(message.chat.id, "Done βœ…") - -def complete_order(message): - id = message.from_user.id - input_commend = message.text - CreateDatas.UpdateOrderComment(input_commend, order_number) - order_details = GetDataFromDB.GetOrderDetails(order_number) - for buyerid, buyerusername, productname, productprice, orderdate, paidmethod, productdownloadlink, productkeys, buyercomment, ordernumber, productnumber in order_details: - print(f"{order_details}") - bot.send_message(message.chat.id, "Thank for your order 🀝") - msg = f"YOUR NEW ORDER βœ…\n\n\nOrder πŸ†”: {ordernumber}\nOrder Date πŸ—“: {orderdate}\nProduct Name πŸ“¦: {productname}\nProduct πŸ†”:{productnumber}\nProduct Price πŸ’°: {productprice} {store_currency}\nPayment Method πŸ’³: {paidmethod}\nProduct Keys πŸ”‘: {productkeys}\nDownload ‡️: {productdownloadlink}" - bot.send_message(id, text=f"{msg}", reply_markup=keyboard) - admin_id = GetDataFromDB.GetProduct_A_AdminID(productnumber) - bot.send_message(admin_id, text=f"{msg}", reply_markup=keyboard) - -#Command handler and function to List My Orders πŸ› -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "My Orders πŸ›") -def MyOrdersList(message): - id = message.from_user.id - - - my_orders = GetDataFromDB.GetOrderIDs_Buyer(id) - if my_orders == [] or my_orders == "None": - bot.send_message(id, "You have not completed any order yet, please purchase an Item now", reply_markup=keyboard) - else: - for my_order in my_orders: - order_details = GetDataFromDB.GetOrderDetails(my_order[0]) - for buyerid, buyerusername, productname, productprice, orderdate, paidmethod, productdownloadlink, productkeys, buyercomment, ordernumber, productnumber in order_details: - msg = f"{productname} ORDERED ON {orderdate} βœ…\n\n\nOrder πŸ†”: {ordernumber}\nOrder Date πŸ—“: {orderdate}\nProduct Name πŸ“¦: {productname}\nProduct πŸ†”:{productnumber}\nProduct Price πŸ’°: {productprice} {store_currency}\nPayment Method πŸ’³: {paidmethod}\nProduct Keys πŸ”‘: {productkeys}\nDownload ‡️: {productdownloadlink}" - bot.send_message(id, text=f"{msg}") - bot.send_message(id, "List completed βœ…", reply_markup=keyboard) - -#Command handler and function to list Store Supports πŸ“ž -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Support πŸ“ž") -def ContactSupport(message): - id = message.from_user.id - admin_usernames = GetDataFromDB.GetAdminUsernamesInDB() - for usernames in admin_usernames: - bot.send_message(id, f"Contact us @{usernames[0]}", reply_markup=keyboard) - -#Command handler and function to add New Category -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Add New Category βž•") -def AddNewCategoryMNG(message): - try: - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - msg = bot.send_message(id, "Reply with name you want to name your new category", reply_markup=keyboard) - bot.register_next_step_handler(msg, manage_categories) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, AddNewCategoryMNG) - -#Command handler and function to List Category -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "List Categories 🏷") -def ListCategoryMNG(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - try: - id = message.from_user.id - all_categories = GetDataFromDB.GetCategoryIDsInDB() - key1 = types.KeyboardButton(text="Add New Category βž•") - key2 = types.KeyboardButton(text="List Categories 🏷") - key3 = types.KeyboardButton(text="Edit Category Name ✏️") - key4 = types.KeyboardButton(text="Delete Category πŸ—‘οΈ") - key5 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1, key2) - keyboardadmin.add(key3, key4) - keyboardadmin.add(key5) - if all_categories == []: - msg = bot.send_message(id, "No Category in your Store !!!", reply_markup=keyboardadmin) - else: - keyboardadmin = types.InlineKeyboardMarkup() - for catnum, catname in all_categories: - text_but = f"🏷 {catname}" - text_cal = f"listcats_{catnum}" - keyboardadmin.add(types.InlineKeyboardButton(text=text_but, callback_data=text_cal)) - bot.send_message(id, f"CATEGORIES:", reply_markup=keyboardadmin) - bot.send_message(id, "List completed βœ…") - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, ManageCategoryMNG) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Command handler and function to Delete Category -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Delete Category πŸ—‘οΈ") -def AddNewCategoryMNG(message): - try: - id = message.from_user.id - - - admins = GetDataFromDB.GetAdminIDsInDB() - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - try: - nen_category_name = "Deleted" - try: - CreateDatas.Update_All_ProductCategory(nen_category_name, product_cate) - except Exception as e: - print(e) - product_cate = GetDataFromDB.Get_A_CategoryName(category_number) - msg = bot.send_message(id, f"{product_cate} successfully deleted πŸ—‘οΈ", reply_markup=keyboardadmin) - CleanData.delete_a_category(category_number) - bot.register_next_step_handler(msg, send_welcome) - - except: - msg = bot.send_message(id, "Category not found !!!", reply_markup=keyboardadmin) - bot.register_next_step_handler(msg, send_welcome) - - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, AddNewCategoryMNG) - -#Command handler and functions to Edit Category Name -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Edit Category Name ✏️") -def EditCategoryNameMNG(message): - try: - id = message.from_user.id - - - admins = GetDataFromDB.GetAdminIDsInDB() - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="Add New Category βž•") - key2 = types.KeyboardButton(text="List Categories 🏷") - key3 = types.KeyboardButton(text="Edit Category Name ✏️") - key4 = types.KeyboardButton(text="Delete Category πŸ—‘οΈ") - key5 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1, key2) - keyboardadmin.add(key3, key4) - keyboardadmin.add(key5) - try: - product_cate = GetDataFromDB.Get_A_CategoryName(category_number) - msg = bot.send_message(id, f"Current Category's Name: {product_cate} \n\n\nReply with your new Category's name") - bot.register_next_step_handler(msg, edit_a_category_name) - except: - msg = bot.send_message(id, "Category to edit not found !!!", reply_markup=keyboardadmin) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, EditCategoryNameMNG) -def edit_a_category_name(message): - try: - id = message.from_user.id - - - admins = GetDataFromDB.GetAdminIDsInDB() - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - try: - nen_category_n = message.text - nen_category_name = nen_category_n.upper() - product_cate = GetDataFromDB.Get_A_CategoryName(category_number) - try: - CreateDatas.Update_All_ProductCategory(nen_category_name, product_cate) - except Exception as e: - print(e) - CreateDatas.Update_A_Category(nen_category_name, category_number) - msg = bot.send_message(id, "Category's name successfully updated: βœ…", reply_markup=keyboardadmin) - bot.register_next_step_handler(msg, send_welcome) - - except: - msg = bot.send_message(id, "Category not found !!!", reply_markup=keyboardadmin) - bot.register_next_step_handler(msg, send_welcome) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, AddNewCategoryMNG) - -#Command handler and function to Manage Category -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Manage Categories πŸ’Ό") -def ManageCategoryMNG(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - try: - id = message.from_user.id - all_categories = GetDataFromDB.GetCategoryIDsInDB() - if all_categories == []: - msg = bot.send_message(id, "No Category in your Store !!!\n\n\nPlease reply with a new category's name to create Category") - bot.register_next_step_handler(msg, manage_categories) - else: - keyboardadmin = types.InlineKeyboardMarkup() - for catnum, catname in all_categories: - text_but = f"🏷 {catname}" - text_cal = f"managecats_{catnum}" - keyboardadmin.add(types.InlineKeyboardButton(text=text_but, callback_data=text_cal)) - bot.send_message(id, f"CATEGORIES:", reply_markup=keyboardadmin) - - keyboard1 = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard1.row_width = 2 - key1 = types.KeyboardButton(text="Add New Category βž•") - key2 = types.KeyboardButton(text="Home 🏘") - keyboard1.add(key1) - keyboard1.add(key2) - msg = bot.send_message(id, "Select Category you want to manage: βœ…\n\nOr Create new Category", reply_markup=keyboard1) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, ManageCategoryMNG) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -def manage_categories(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - input_cat = message.text + keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) + keyboard.row_width = 2 + buyer_id = message.from_user.id + buyer_username = message.from_user.username all_categories = GetDataFromDB.GetCategoryIDsInDB() - input_cate = input_cat categories = [] for catnum, catname in all_categories: catnames = catname.upper() @@ -1054,397 +901,73 @@ def checkint(): return input_cat except: return input_cate - input_category = checkint() if isinstance(input_category, int) == True: product_cate = GetDataFromDB.Get_A_CategoryName(input_category) - product_category = product_cate.upper() - if f"{product_category}" not in f"{categories}" or f"{product_category}" == "NONE": - msg = bot.send_message(id, "Category not found !!!\n\n\nPlease reply with a new category's name to create category") - bot.register_next_step_handler(msg, manage_categories) - elif f"{product_category}" in f"{categories}": - category_num = input_cate - key1 = types.KeyboardButton(text="Add New Category βž•") - key2 = types.KeyboardButton(text="List Categories 🏷") - key3 = types.KeyboardButton(text="Edit Category Name ✏️") - key4 = types.KeyboardButton(text="Delete Category πŸ—‘οΈ") - key5 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1, key2) - keyboardadmin.add(key3, key4) - keyboardadmin.add(key5) - bot.send_message(id, f"What will you like to do next ?", reply_markup=keyboardadmin) - else: - new_category_number = random.randint(1000,9999) - input_cate = input_cat.upper() - CreateDatas.AddCategory(new_category_number, input_cate) - key1 = types.KeyboardButton(text="Add New Category βž•") - key2 = types.KeyboardButton(text="Manage Categories πŸ’Ό") - key3 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2) - keyboardadmin.add(key3) - bot.send_message(id, f"New Category {input_cat} created successfully\n\n\nWhat will you like to do next ?", reply_markup=keyboardadmin) - category_num = new_category_number - global category_number - category_number = category_num - - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) + if f"{product_cate}" in f"{categories}": + product_category = product_cate.upper() + product_list = GetDataFromDB.GetProductInfoByCTGName(product_category) + print(product_list) + if product_list == []: + bot.send_message(id, "No Product in the store", reply_markup=create_main_keyboard()) + else: + bot.send_message(id, f"{product_cate} Category's Products") + for productnumber, productname, productprice, productdescription, productimagelink, productdownloadlink, productquantity, productcategory in product_list: + keyboard2 = types.InlineKeyboardMarkup() + keyboard2.add(types.InlineKeyboardButton(text="BUY NOW πŸ’°", callback_data=f"getproduct_{productnumber}")) + bot.send_photo(id, photo=f"{productimagelink}", caption=f"Product ID πŸͺͺ: /{productnumber}\n\nProduct Name πŸ“¦: {productname}\n\nProduct Price πŸ’°: {productprice} {store_currency}\n\nProducts In Stock πŸ›: {productquantity}\n\nProduct Description πŸ’¬: {productdescription}", reply_markup=keyboard2) -def manage_categoriesbutton(message, input_c): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - id = message.from_user.id - all_categories = GetDataFromDB.GetCategoryIDsInDB() - input_cate = input_c - categories = [] - for catnum, catname in all_categories: - catnames = catname.upper() - categories.append(catnames) - input_category = input_cate - product_cate = GetDataFromDB.Get_A_CategoryName(input_category) - product_category = product_cate.upper() - if f"{product_category}" not in f"{categories}" or f"{product_category}" == "NONE": - msg = bot.send_message(id, "Category not found !!!\n\n\nPlease reply with a new category's name to create category") - bot.register_next_step_handler(msg, manage_categoriesbutton) - elif f"{product_category}" in f"{categories}": - category_num = input_cate - key1 = types.KeyboardButton(text="Add New Category βž•") - key2 = types.KeyboardButton(text="List Categories 🏷") - key3 = types.KeyboardButton(text="Edit Category Name ✏️") - key4 = types.KeyboardButton(text="Delete Category πŸ—‘οΈ") - key5 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1, key2) - keyboardadmin.add(key3, key4) - keyboardadmin.add(key5) - bot.send_message(id, f"What will you like to do next ?", reply_markup=keyboardadmin) - - global category_number - category_number = category_num - print(category_number) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Command handler and function to List Product -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "List Product 🏷") -def LISTProductsMNG(message): - id = message.from_user.id - keyboarda = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboarda.row_width = 2 - admins = GetDataFromDB.GetAdminIDsInDB() - productinfos = GetDataFromDB.GetProductInfos() - if f"{id}" in f"{admins}": - keyboard = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboard.row_width = 2 - if productinfos == []: - msg = bot.send_message(id, "No product available, please send /start command to start creating products") - bot.register_next_step_handler(msg, send_welcome) - else: - keyboard = types.InlineKeyboardMarkup() - for pid, tittle, price in productinfos: - text_but = f"πŸ’Ό {tittle} - {price} {store_currency}" - text_cal = f"getproductig_{pid}" - keyboard.add(types.InlineKeyboardButton(text=text_but, callback_data=text_cal)) - bot.send_message(id, f"PRODUCTS:", reply_markup=keyboard) - key1 = types.KeyboardButton(text="Add New Product βž•") - key2 = types.KeyboardButton(text="List Product 🏷") - key3 = types.KeyboardButton(text="Delete Product πŸ—‘οΈ") - key4 = types.KeyboardButton(text="Home 🏘") - keyboarda.add(key1) - keyboarda.add(key2, key3) - keyboarda.add(key4) - msg = bot.send_message(id, "List Finished: βœ…", reply_markup=keyboarda, parse_mode="Markdown") + else: + print("Wrong command !!!") - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) +# Flask App +flask_app = Flask(__name__) +flask_app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secret-key-here') -#Command handler and functions to Message All Store Users -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "News To Users πŸ“£") -def MessageAllUsers(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - msg = bot.send_message(id, f"This Bot is about to Broadcast mesage to all Shop Users\n\n\nReply with the message you want to Broadcast: βœ…") - bot.register_next_step_handler(msg, message_all_users) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) -def message_all_users(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - +@flask_app.route('/', methods=['GET', 'POST']) +def webhook(): + """Handle incoming webhook requests from Telegram.""" + if flask.request.method == 'GET': + return 'Bot is running!', 200 - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 + if flask.request.headers.get('content-type') == 'application/json': try: - key1 = types.KeyboardButton(text="Manage Products πŸ’Ό") - key2 = types.KeyboardButton(text="Manage Orders πŸ›") - key3 = types.KeyboardButton(text="Payment Methods πŸ’³") - key4 = types.KeyboardButton(text="News To Users πŸ“£") - key5 = types.KeyboardButton(text="Switch To User πŸ™β€β™‚οΈ") - keyboardadmin.add(key1, key2) - keyboardadmin.add(key3, key4) - keyboardadmin.add(key5) - input_message = message.text - all_users = GetDataFromDB.GetUsersInfo() - if all_users == []: - msg = bot.send_message(id, "No user available in your store, /start", reply_markup=keyboardadmin) - else: - bot.send_message(id, "Now Broadcasting Message To All Users: βœ…") - for uid, uname, uwallet in all_users: - try: - bot.send_message(uid, f"{input_message}") - bot.send_message(id, f"Message successfully sent βœ… To: @`{uname}`") - time.sleep(0.5) - except: - bot.send_message(id, f"User @{uid} has blocked the bot - {uname} ") - bot.send_message(id, f"Broadcast Completed βœ…", reply_markup=keyboardadmin) + json_string = flask.request.get_data().decode('utf-8') + update = telebot.types.Update.de_json(json_string) + bot.process_new_updates([update]) + return '', 200 except Exception as e: - print(e) - bot.send_message(id, "Error 404 🚫, try again with corrected input.") - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - - -#Command handler and function to Manage Orders -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Manage Orders πŸ›") -def ManageOrders(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": # ✏️ - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="List Orders πŸ›") - key2 = types.KeyboardButton(text="Delete Order πŸ—‘οΈ") - key3 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2, key3) - bot.send_message(id, "Choose an action to perform βœ…", reply_markup=keyboardadmin) + logger.error(f"Error processing update: {e}") + return 'Error processing update', 500 else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Command handler and function to List All Orders -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "List Orders πŸ›") -def ListOrders(message): - try: - id = message.from_user.id - - - admins = GetDataFromDB.GetAdminIDsInDB() - all_orders = GetDataFromDB.GetOrderInfo() - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - if all_orders == []: - bot.send_message(id, "No Order available in your store, /start") - else: - bot.send_message(id, "Your Oders List: βœ…") - bot.send_message(id, f"πŸ‘‡ OrderID - ProductName - BuyerUserNameπŸ‘‡") - for ordernumber, productname, buyerusername in all_orders: - import time - time.sleep(0.5) - bot.send_message(id, f"`{ordernumber}` - `{productname}` - @{buyerusername}") - key1 = types.KeyboardButton(text="List Orders πŸ›") - key2 = types.KeyboardButton(text="Delete Order πŸ—‘οΈ") - key3 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2, key3) - bot.send_message(id, f"List Completed βœ…", reply_markup=keyboardadmin) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - except Exception as e: - print(e) - bot.send_message(id, "Error 404 🚫, try again with corrected input.") + logger.warning(f"Invalid webhook request received. Content-Type: {flask.request.headers.get('content-type')}") + return 'Invalid request', 403 +# Main bot handlers +@bot.message_handler(commands=['start']) +def send_welcome(message): + """Send a welcome message and the main keyboard.""" + CreateDatas.AddAuser(message.from_user.id, message.chat.username) + bot.reply_to(message, "Welcome to the Store Bot!", reply_markup=create_main_keyboard()) -#Command handler and functions to Delete Order -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Delete Order πŸ—‘οΈ") -def DeleteOrderMNG(message): - try: - id = message.from_user.id - - - admins = GetDataFromDB.GetAdminIDsInDB() - all_orders = GetDataFromDB.GetOrderInfo() - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - if all_orders == []: - key1 = types.KeyboardButton(text="List Orders πŸ›") - key2 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2) - bot.send_message(id, "No Order available in your store, /start", reply_markup=keyboardadmin) - else: - bot.send_message(id, f"πŸ‘‡ OrderID - ProductName - BuyerUserName πŸ‘‡") - for ordernumber, productname, buyerusername in all_orders: - bot.send_message(id, f"/{ordernumber} - `{productname}` - @{buyerusername}", parse_mode="Markdown") - msg = bot.send_message(id, "Click on an Order ID of the order you want to delete: βœ…", parse_mode="Markdown") - bot.register_next_step_handler(msg, delete_an_order) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, DeleteOrderMNG) -def delete_an_order(message): +@bot.callback_query_handler(func=lambda call: True) +def callback_query(call): + """Handle callback queries from inline keyboards""" try: - id = message.from_user.id - ordernu = message.text - ordernumber = ordernu[1:99] - ordernum = GetDataFromDB.GetOrderIDs() - ordernumbers = [] - for ordern in ordernum: - ordernumbers.append(ordern[0]) - if f"{ordernumber}" in f"{ordernumbers}": - try: - global ordernums - ordernums = ordernumber - except Exception as e: - print(e) - - - admins = GetDataFromDB.GetAdminIDsInDB() - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="List Orders πŸ›") - key2 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2) - CleanData.delete_an_order(ordernumber) - msg = bot.send_message(id, "Deleted successfully πŸ—‘οΈ\n\n\nWhat will you like to do next ?\n\nSelect one of buttons πŸ‘‡", reply_markup=keyboardadmin, parse_mode="Markdown") - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) + if call.data.startswith("getcats_"): + input_catees = call.data.replace('getcats_','') + CategoriesDatas.get_category_products(call, input_catees) + elif call.data.startswith("getproduct_"): + input_cate = call.data.replace('getproduct_','') + UserOperations.purchase_a_products(call, input_cate) + elif call.data.startswith("managecats_"): + input_cate = call.data.replace('managecats_','') + manage_categoriesbutton(call, input_cate) else: - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, delete_an_order) + logger.warning(f"Unknown callback data: {call.data}") except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, delete_an_order) - -#Command handler and function to Manage Payment Methods -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Payment Methods πŸ’³") -def PaymentMethodMNG(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - - - if f"{id}" in f"{admins}": - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - key1 = types.KeyboardButton(text="Add Bitcoin Method βž•") - key2 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - keyboardadmin.add(key2) - bot.send_message(id, "Choose an action to perform βœ…", reply_markup=keyboardadmin) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - - -#Command handler and function to Add API Keys for Bitcoin Payment Method -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Add Bitcoin Method βž•") -def AddBitcoinAPIKey(message): - id = message.from_user.id - username = message.from_user.username - admins = GetDataFromDB.GetAdminIDsInDB() - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - edit_methods = "Bitcoin" - global edit_method - edit_method = edit_methods - all_pay_methods = GetDataFromDB.GetPaymentMethodsAll(edit_method) - if f"{id}" in f"{admins}": - - if f"{edit_method}" in f"{all_pay_methods}": - bot.send_message(id, f"{edit_method} Payment method is already added βœ…", reply_markup=keyboardadmin) - else: - CreateDatas.AddPaymentMethod(id, username, edit_method) - - try: - for method_name, token_clientid_keys, sectret_keys in all_pay_methods: - all = method_name, token_clientid_keys, sectret_keys - msg = bot.send_message(id, f"Reply With Your {edit_method} API Key for your NowPayments Account (https://account.nowpayments.io/create-account?link_id=3539852335): βœ…") - bot.register_next_step_handler(msg, add_bitcoin_api_key) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, AddBitcoinAPIKey) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) -def add_bitcoin_api_key(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - if f"{id}" in f"{admins}": - try: - key1 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - id = message.from_user.id - api_key = message.text - username = message.from_user.username - CreateDatas.UpdatePaymentMethodToken(id, username, api_key, edit_method) - bot.send_message(id, "Bitcoin Added successfully βœ…", reply_markup=keyboardadmin) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, AddBitcoinAPIKey) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) - -#Command handler and function to Add API Secret Key for Bitcoin Payment Method -@bot.message_handler(content_types=["text"], func=lambda message: message.text == "Add Bitcoin Secret βž•") -def AddBitcoinSecretKey(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - all_pay_methods = GetDataFromDB.GetPaymentMethodsAll(edit_method) - if f"{id}" in f"{admins}": - try: - for method_name, token_clientid_keys, sectret_keys in all_pay_methods: - all = method_name, token_clientid_keys, sectret_keys - msg = bot.send_message(id, f"Reply With Your {edit_method} API Key for your NowPayments Account (https://account.nowpayments.io/create-account?link_id=3539852335): βœ…") - bot.register_next_step_handler(msg, add_bitcoin_secret_key) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, AddBitcoinSecretKey) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboardadmin) -def add_bitcoin_secret_key(message): - id = message.from_user.id - admins = GetDataFromDB.GetAdminIDsInDB() - keyboardadmin = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True) - keyboardadmin.row_width = 2 - if f"{id}" in f"{admins}": - try: - key1 = types.KeyboardButton(text="Home 🏘") - keyboardadmin.add(key1) - id = message.from_user.id - api_key = message.text - username = message.from_user.username - CreateDatas.UpdatePaymentMethodSecret(id, username, api_key, edit_method) - bot.send_message(id, "Added successfully βœ…", reply_markup=keyboardadmin) - except Exception as e: - print(e) - msg = bot.send_message(id, "Error 404 🚫, try again with corrected input.") - bot.register_next_step_handler(msg, AddBitcoinSecretKey) - else: - bot.send_message(id, "⚠️ Only Admin can use this command !!!", reply_markup=keyboard) + logger.error(f"Error handling callback query: {e}") + bot.send_message(call.message.chat.id, "An error occurred. Please try again.") if __name__ == '__main__': try: diff --git a/utils.py b/utils.py deleted file mode 100644 index 7aeb55e4ce..0000000000 --- a/utils.py +++ /dev/null @@ -1,215 +0,0 @@ -""" -Utility functions for the Telegram Store Bot -""" - -import re -import logging -from typing import Optional, Union - -logger = logging.getLogger(__name__) - -class InputValidator: - """Input validation and sanitization utilities""" - - @staticmethod - def validate_user_id(user_id: Union[str, int]) -> Optional[int]: - """Validate and convert user ID to integer""" - try: - user_id = int(user_id) - if user_id > 0: - return user_id - return None - except (ValueError, TypeError): - return None - - @staticmethod - def validate_username(username: str) -> Optional[str]: - """Validate and sanitize username""" - if not username or not isinstance(username, str): - return None - - # Remove potentially dangerous characters - sanitized = re.sub(r'[<>"\';]', '', username.strip()) - - # Check if username is reasonable length - if 1 <= len(sanitized) <= 50: - return sanitized - return None - - @staticmethod - def validate_product_number(product_number: Union[str, int]) -> Optional[int]: - """Validate product number""" - try: - product_number = int(product_number) - if 10000000 <= product_number <= 99999999: # 8 digits - return product_number - return None - except (ValueError, TypeError): - return None - - @staticmethod - def validate_price(price: Union[str, int, float]) -> Optional[float]: - """Validate price value""" - try: - price = float(price) - if price >= 0: - return round(price, 2) - return None - except (ValueError, TypeError): - return None - - @staticmethod - def validate_quantity(quantity: Union[str, int]) -> Optional[int]: - """Validate quantity value""" - try: - quantity = int(quantity) - if quantity >= 0: - return quantity - return None - except (ValueError, TypeError): - return None - - @staticmethod - def sanitize_text(text: str, max_length: int = 1000) -> Optional[str]: - """Sanitize text input""" - if not text or not isinstance(text, str): - return None - - # Remove potentially dangerous characters - sanitized = re.sub(r'[<>"\';]', '', text.strip()) - - # Check length - if len(sanitized) <= max_length: - return sanitized - return sanitized[:max_length] - -class SecurityUtils: - """Security-related utility functions""" - - @staticmethod - def is_valid_url(url: str) -> bool: - """Check if URL is valid and safe""" - if not url or not isinstance(url, str): - return False - - # Basic URL validation - url_pattern = re.compile( - r'^https?://' # http:// or https:// - r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' # domain... - r'localhost|' # localhost... - r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip - r'(?::\d+)?' # optional port - r'(?:/?|[/?]\S+)$', re.IGNORECASE) - - return bool(url_pattern.match(url)) - - @staticmethod - def sanitize_sql_input(value: str) -> str: - """Basic SQL injection prevention""" - if not value: - return "" - - # Remove or escape potentially dangerous SQL characters - dangerous_chars = ["'", '"', ';', '--', '/*', '*/', 'xp_', 'sp_'] - sanitized = str(value) - - for char in dangerous_chars: - sanitized = sanitized.replace(char, '') - - return sanitized.strip() - -class ErrorHandler: - """Centralized error handling""" - - @staticmethod - def handle_database_error(error: Exception, operation: str) -> str: - """Handle database-related errors""" - logger.error(f"Database error in {operation}: {error}") - return "Database error occurred. Please try again later." - - @staticmethod - def handle_api_error(error: Exception, api_name: str) -> str: - """Handle API-related errors""" - logger.error(f"API error in {api_name}: {error}") - return f"Error connecting to {api_name}. Please try again later." - - @staticmethod - def handle_user_error(error: Exception, operation: str) -> str: - """Handle user input errors""" - logger.warning(f"User error in {operation}: {error}") - return "Invalid input. Please check your input and try again." - -class MessageFormatter: - """Message formatting utilities""" - - @staticmethod - def format_product_info(product_data: dict) -> str: - """Format product information for display""" - return f""" -🏷️ **Product Details** - -**Name:** {product_data.get('name', 'N/A')} -**Price:** {product_data.get('price', 0)} {product_data.get('currency', 'USD')} -**Description:** {product_data.get('description', 'No description')} -**Quantity:** {product_data.get('quantity', 0)} -**Category:** {product_data.get('category', 'Uncategorized')} - """.strip() - - @staticmethod - def format_order_info(order_data: dict) -> str: - """Format order information for display""" - return f""" -πŸ“¦ **Order Details** - -**Order ID:** {order_data.get('id', 'N/A')} -**Product:** {order_data.get('product_name', 'N/A')} -**Price:** {order_data.get('price', 0)} {order_data.get('currency', 'USD')} -**Date:** {order_data.get('date', 'N/A')} -**Status:** {order_data.get('status', 'N/A')} - """.strip() - - @staticmethod - def format_error_message(error_type: str, user_friendly: bool = True) -> str: - """Format error messages for users""" - if user_friendly: - return f"❌ {error_type}. Please try again or contact support." - return f"Error: {error_type}" - -class CacheManager: - """Simple in-memory cache manager""" - - def __init__(self): - self.cache = {} - - def get(self, key: str): - """Get value from cache""" - return self.cache.get(key) - - def set(self, key: str, value, ttl: int = 300): - """Set value in cache with TTL (Time To Live)""" - import time - self.cache[key] = { - 'value': value, - 'expires': time.time() + ttl - } - - def is_expired(self, key: str) -> bool: - """Check if cache entry is expired""" - import time - if key not in self.cache: - return True - return time.time() > self.cache[key]['expires'] - - def clear_expired(self): - """Clear expired cache entries""" - import time - current_time = time.time() - expired_keys = [ - key for key, data in self.cache.items() - if current_time > data['expires'] - ] - for key in expired_keys: - del self.cache[key] - -# Global cache instance -cache = CacheManager() \ No newline at end of file