Всем хай. Бот позволяет торговать через апи ключи и платежные пароли. отлично подойдет для фермеров. Предметы на продажу выставляются по ценам АВТОБАЯ! Важно!!!!! скриншоты бота: (этот скриншотик старый, кнопки Удалить нету) Функционал: - Добавление аккаунтов через "TOKEN PAY_PASSWORD" - Удаление аккаунтов - Обновление инвентаря на сайте - Быстрая массовая продажа - Продажа поштучно (выбираете сами предмет) - Автовывод средств на основной аккаунт (для этого нужно будет настроить мейн-акк в боте, далее поясню как работает) - Автоподнятие (всегда включайте, ибо маркет раз в 3 минуты будет вырубать продажи, а эта функция включает их снова) - Список аккаунтов Для корректной работы скрипта - необходимо держать включенным либо на сервере либо на пк - MARKET APP с настроенными mafile's, что бы автоматически отправлялись и подтверждались трейды. Автовывод средств на основной аккаунт - это функция которая ВНУТРИ САЙТА переводит бабки на нужный вам аккаунт. Отлично подойдет если вы продали на 1000 аккаунтов по 1 кейсу и хотите вывести кеш Код бота import telebot import sqlite3 import time import threading import logging import requests from telebot import types import json # Импортируем модуль json import sys import os # Замените 'TOKEN' на токен вашего бота BOT_TOKEN = 'TOKEN' # market.csgo.com API URL API_BASE_URL = 'https://market.csgo.com/api/v2' # Валюта по умолчанию DEFAULT_CURRENCY = 'RUB' # Настройка логирования logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Глобальная переменная для бота bot = None # Функция для создания подключения к базе данных def create_connection(): """Создает подключение к базе данных SQLite.""" try: conn = sqlite3.connect('csgoflipbot.db') return conn except Exception as e: logger.error(f"Ошибка при подключении к базе данных: {e}") return None # Функция для создания таблиц в базе данных def create_tables(): """Создает таблицы в базе данных, если они не существуют.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() # Таблица для хранения информации об аккаунтах cursor.execute(''' CREATE TABLE IF NOT EXISTS accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, api_key TEXT NOT NULL UNIQUE, payment_password TEXT NOT NULL, auto_ping INTEGER DEFAULT 0, account_name TEXT, user_id INTEGER NOT NULL, is_main INTEGER DEFAULT 0 ) ''') # Таблица для связи аккаунтов и чатов (для каждого чата свои настройки аккаунтов) cursor.execute(''' CREATE TABLE IF NOT EXISTS chat_accounts ( chat_id INTEGER NOT NULL, account_id INTEGER NOT NULL, user_id INTEGER NOT NULL, PRIMARY KEY (chat_id, account_id), FOREIGN KEY (account_id) REFERENCES accounts (id) ) ''') # Таблица для хранения инвентаря cursor.execute(''' CREATE TABLE IF NOT EXISTS inventory ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, item_id TEXT NOT NULL, market_hash_name TEXT NOT NULL, market_price REAL NOT NULL, FOREIGN KEY (account_id) REFERENCES accounts (id), UNIQUE (account_id, item_id) ) ''') conn.commit() logger.info("Таблицы базы данных успешно созданы.") except Exception as e: logger.error(f"Ошибка при создании таблиц: {e}") finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") # Функция для добавления аккаунта в базу данных def add_account(api_key, payment_password, user_id, account_name=None): """Добавляет новый аккаунт в базу данных.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() cursor.execute( "INSERT INTO accounts (api_key, payment_password, account_name, user_id) VALUES (?, ?, ?, ?)", (api_key, payment_password, account_name, user_id), ) conn.commit() logger.info(f"Аккаунт с API-ключом {api_key} успешно добавлен для пользователя {user_id}.") return True except sqlite3.IntegrityError: logger.warning(f"Аккаунт с API-ключом {api_key} уже существует.") return False except Exception as e: logger.error(f"Ошибка при добавлении аккаунта: {e}") return False finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return False # Функция для получения списка всех аккаунтов def get_all_accounts(user_id=None): """Получает список всех аккаунтов из базы данных. Если user_id указан, возвращает только аккаунты этого пользователя. Если user_id не указан, возвращает все аккаунты в системе.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() if user_id is not None: cursor.execute( "SELECT id, api_key, payment_password, auto_ping, account_name FROM accounts WHERE user_id = ?", (user_id,) ) else: cursor.execute("SELECT id, api_key, payment_password, auto_ping, account_name FROM accounts") accounts = cursor.fetchall() return accounts except Exception as e: logger.error(f"Ошибка при получении списка аккаунтов: {e}") return [] finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return [] # Функция для получения аккаунта по API-ключу def get_account_by_api_key(api_key): """Получает аккаунт из базы данных по API-ключу.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() cursor.execute("SELECT id, api_key, payment_password, auto_ping, account_name FROM accounts WHERE api_key = ?", (api_key,)) account = cursor.fetchone() return account except Exception as e: logger.error(f"Ошибка при получении аккаунта по API-ключу: {e}") return None finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return None # Функция для получения главного аккаунта пользователя def get_main_account(user_id): """Получает главный аккаунт пользователя из базы данных.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() cursor.execute( "SELECT id, api_key, payment_password, auto_ping, account_name FROM accounts WHERE user_id = ? AND is_main = 1", (user_id,) ) account = cursor.fetchone() return account except Exception as e: logger.error(f"Ошибка при получении главного аккаунта: {e}") return None finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return None # Функция для обновления настроек аккаунта def update_account_settings(api_key, auto_ping=None, payment_password=None, account_name=None, is_main=None): """Обновляет настройки аккаунта в базе данных.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() # Обновляем только переданные параметры updates = [] values = [] if auto_ping is not None: updates.append("auto_ping = ?") values.append(auto_ping) if payment_password is not None: updates.append("payment_password = ?") values.append(payment_password) if account_name is not None: updates.append("account_name = ?") values.append(account_name) if is_main is not None: # Если устанавливаем новый главный аккаунт, сбрасываем флаг у других аккаунтов этого пользователя if is_main == 1: account = get_account_by_api_key(api_key) if account: # Получаем user_id из базы данных cursor.execute("SELECT user_id FROM accounts WHERE api_key = ?", (api_key,)) user_id_result = cursor.fetchone() if user_id_result: user_id = user_id_result[0] cursor.execute( "UPDATE accounts SET is_main = 0 WHERE user_id = ? AND api_key != ?", (user_id, api_key) ) updates.append("is_main = ?") values.append(is_main) if not updates: return True # Ничего не обновлено query = f"UPDATE accounts SET {', '.join(updates)} WHERE api_key = ?" values.append(api_key) cursor.execute(query, tuple(values)) conn.commit() logger.info(f"Настройки аккаунта с API-ключом {api_key} успешно обновлены.") return True except Exception as e: logger.error(f"Ошибка при обновлении настроек аккаунта: {e}") return False finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return False # Функция для выполнения запросов к API market.csgo.com def make_api_request(api_key, method, params=None, use_post=False): """Выполняет запрос к API market.csgo.com с обработкой ошибок.""" url = f"{API_BASE_URL}/{method}?key={api_key}" # Добавляем api_key в URL try: if use_post: response = requests.post(url, data=params) else: if params: response = requests.get(url, params=params) else: response = requests.get(url) response.raise_for_status() # Поднимает исключение для HTTP ошибок return response.json() except requests.exceptions.RequestException as e: logger.error(f"Ошибка при выполнении запроса {method}: {e}") return None except json.JSONDecodeError: logger.error(f"Ошибка декодирования JSON ответа от {method}") return None # Функция для получения инвентаря аккаунта def get_inventory(api_key): """Получает инвентарь аккаунта с использованием API market.csgo.com.""" return make_api_request(api_key, 'my-inventory') def get_bid_ask_price(api_key, market_hash_name, phase=None): """Получает актуальные цены bid-ask для предмета.""" url = f"{API_BASE_URL}/bid-ask" params = { 'key': api_key, 'hash_name': market_hash_name } if phase: params['phase'] = phase try: response = requests.get(url, params=params) response.raise_for_status() data = response.json() # Получаем максимальную цену из bid if data.get('bid'): max_bid = max(float(bid['price']) for bid in data['bid']) return max_bid return None except Exception as e: logger.error(f"Ошибка при получении bid-ask цен: {e}") return None def store_inventory_in_db(api_key, inventory_data): """Сохраняет инвентарь в базу данных.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() account_id = get_account_by_api_key(api_key)[0] # Получаем ID аккаунта # Очищаем старые записи для этого аккаунта cursor.execute("DELETE FROM inventory WHERE account_id = ?", (account_id,)) for item in inventory_data.get('items', []): item_id = item.get('id') market_hash_name = item.get('market_hash_name') if item_id and market_hash_name: # Получаем актуальную цену через bid-ask current_price = get_bid_ask_price(api_key, market_hash_name) if current_price is None: current_price = item.get('market_price', 0) # Используем старую цену как запасной вариант cursor.execute( "INSERT INTO inventory (account_id, item_id, market_hash_name, market_price) VALUES (?, ?, ?, ?)", (account_id, item_id, market_hash_name, current_price) ) conn.commit() logger.info(f"Инвентарь аккаунта {api_key} успешно сохранен в базе данных.") except Exception as e: logger.error(f"Ошибка при сохранении инвентаря в базу данных: {e}") finally: conn.close() # Функция для выставления предмета на продажу def add_to_sale(api_key, item_id, price, currency=DEFAULT_CURRENCY): """Выставляет предмет на продажу на market.csgo.com.""" # Преобразуем цену в копейки (умножаем на 100 и убираем десятичную часть) price_in_cents = int(float(price) * 100) params = {'id': item_id, 'price': price_in_cents, 'cur': currency} logger.info(f"Выставление предмета {item_id} на продажу. Цена в копейках: {price_in_cents}") return make_api_request(api_key, 'add-to-sale', params) # Функция для получения баланса аккаунта def get_balance(api_key): """Получает баланс аккаунта.""" return make_api_request(api_key, 'get-money') # Функция для перевода средств def transfer_money(api_key, payment_password, amount, user_api_key): """Переводит средства с аккаунта.""" # Преобразуем сумму в копейки (умножаем на 100 и убираем десятичную часть) amount_in_cents = int(float(amount) * 100) url = f"{API_BASE_URL}/money-send/{amount_in_cents}/{user_api_key}?key={api_key}&pay_pass={payment_password}" try: response = requests.get(url) # Изменен метод на GET response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: logger.error(f"Ошибка при выполнении запроса money-send: {e}") return None except json.JSONDecodeError: logger.error(f"Ошибка декодирования JSON ответа от money-send") return None # Функция для обновления инвентаря def update_inventory(api_key): """Запрашивает обновление кеша инвентаря.""" return make_api_request(api_key, 'update-inventory') # Функция для пинга новых предметов def ping_new_items(api_key): """Отправляет POST запрос на ping-new endpoint.""" return make_api_request(api_key, 'ping-new', use_post=True) # Функция для получения списка аккаунтов, привязанных к чату def get_chat_accounts(chat_id, user_id): """Получает список API-ключей аккаунтов, привязанных к чату для конкретного пользователя.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() cursor.execute( "SELECT a.api_key FROM accounts a INNER JOIN chat_accounts ca ON a.id = ca.account_id WHERE ca.chat_id = ? AND ca.user_id = ?", (chat_id, user_id), ) accounts = [row[0] for row in cursor.fetchall()] return accounts except Exception as e: logger.error(f"Ошибка при получении аккаунтов чата {chat_id}: {e}") return [] finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return [] # Функция для привязки аккаунта к чату def add_account_to_chat(chat_id, api_key, user_id): """Привязывает аккаунт к чату для конкретного пользователя.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() account_id = get_account_by_api_key(api_key)[0] cursor.execute( "INSERT INTO chat_accounts (chat_id, account_id, user_id) VALUES (?, ?, ?)", (chat_id, account_id, user_id), ) conn.commit() logger.info(f"Аккаунт {api_key} привязан к чату {chat_id} для пользователя {user_id}.") return True except Exception as e: logger.error(f"Ошибка при привязке аккаунта к чату: {e}") return False finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return False # Функция для отвязки аккаунта от чата def remove_account_from_chat(chat_id, api_key, user_id): """Отвязывает аккаунт от чата для конкретного пользователя.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() account_id = get_account_by_api_key(api_key)[0] cursor.execute( "DELETE FROM chat_accounts WHERE chat_id = ? AND account_id = ? AND user_id = ?", (chat_id, account_id, user_id), ) conn.commit() logger.info(f"Аккаунт {api_key} отвязан от чата {chat_id} для пользователя {user_id}.") return True except Exception as e: logger.error(f"Ошибка при отвязке аккаунта от чата: {e}") return False finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return False # Функция для запуска пинга новых предметов для всех аккаунтов с auto_ping = 1 def start_auto_ping(bot): """Запускает периодический пинг новых предметов для аккаунтов с auto_ping = 1.""" def ping_loop(): while True: accounts = get_all_accounts() for account in accounts: account_id, api_key, _, auto_ping, _ = account if auto_ping == 1: try: response = ping_new_items(api_key) if response: logger.info(f"Успешно отправлен ping-new для аккаунта {api_key}.") else: logger.warning(f"Не удалось отправить ping-new для аккаунта {api_key}.") except Exception as e: logger.error(f"Ошибка при выполнении ping-new для аккаунта {api_key}: {e}") time.sleep(180) # Интервал 3 минуты (180 секунд) # Запускаем пинг в отдельном потоке threading.Thread(target=ping_loop, daemon=True).start() def get_main_menu_keyboard(): """Создает основную клавиатуру меню.""" markup = types.InlineKeyboardMarkup(row_width=2) buttons = [ types.InlineKeyboardButton("Добавить аккаунт", callback_data="add_account"), types.InlineKeyboardButton("Список аккаунтов", callback_data="list_accounts"), types.InlineKeyboardButton("Установить главный аккаунт", callback_data="set_main_account"), types.InlineKeyboardButton("Вывод средств", callback_data="show_balance"), types.InlineKeyboardButton("Выставить предметы", callback_data="add_to_sale"), types.InlineKeyboardButton("Обновить инвентарь", callback_data="update_inventory"), types.InlineKeyboardButton("Включить автоподнятие", callback_data="enable_ping"), types.InlineKeyboardButton("Выключить автоподнятие", callback_data="disable_ping"), types.InlineKeyboardButton("Удалить аккаунт", callback_data="delete_account") ] markup.add(*buttons) return markup def get_cancel_keyboard(): """Создает инлайн клавиатуру с кнопкой отмены.""" markup = types.InlineKeyboardMarkup() cancel_button = types.InlineKeyboardButton("Отменить", callback_data="cancel") delete_account_button = types.InlineKeyboardButton("Удалить аккаунт", callback_data="delete_account") markup.add(cancel_button, delete_account_button) return markup def handle_enable_auto_ping(message): """Обрабатывает включение автоподнятия для аккаунта.""" global bot chat_id = message.chat.id api_key = message.text logger.info(f"Попытка включения автоподнятия для аккаунта {api_key}") # Проверяем существование аккаунта account = get_account_by_api_key(api_key) if not account: logger.warning(f"Аккаунт с API ключом {api_key} не найден") bot.send_message(chat_id, "Аккаунт с таким API-ключом не найден.") return # Обновляем настройки аккаунта if update_account_settings(api_key, auto_ping=1): logger.info(f"Автоподнятие успешно включено для аккаунта {api_key}") bot.send_message(chat_id, "Автоподнятие успешно включено.") else: logger.error(f"Не удалось включить автоподнятие для аккаунта {api_key}") bot.send_message(chat_id, "Не удалось включить автоподнятие.") def handle_update_inventory(message): """Обрабатывает запрос на обновление инвентаря.""" global bot chat_id = message.chat.id api_key = message.text logger.info(f"Попытка обновления инвентаря для аккаунта {api_key}") # Проверяем существование аккаунта account = get_account_by_api_key(api_key) if not account: logger.warning(f"Аккаунт с API ключом {api_key} не найден") bot.send_message(chat_id, "Аккаунт с таким API-ключом не найден.") return # Обновляем инвентарь result = update_inventory(api_key) if result and result.get('success'): logger.info(f"Инвентарь успешно обновлен для аккаунта {api_key}") bot.send_message(chat_id, "Инвентарь успешно обновлен.") else: logger.error(f"Не удалось обновить инвентарь для аккаунта {api_key}") bot.send_message(chat_id, "Не удалось обновить инвентарь.") def handle_disable_auto_ping(message): """Обрабатывает выключение автоподнятия для аккаунта.""" global bot chat_id = message.chat.id api_key = message.text logger.info(f"Попытка выключения автоподнятия для аккаунта {api_key}") # Проверяем существование аккаунта account = get_account_by_api_key(api_key) if not account: logger.warning(f"Аккаунт с API ключом {api_key} не найден") bot.send_message(chat_id, "Аккаунт с таким API-ключом не найден.") return # Обновляем настройки аккаунта if update_account_settings(api_key, auto_ping=0): logger.info(f"Автоподнятие успешно выключено для аккаунта {api_key}") bot.send_message(chat_id, "Автоподнятие успешно выключено.") else: logger.error(f"Не удалось выключить автоподнятие для аккаунта {api_key}") bot.send_message(chat_id, "Не удалось выключить автоподнятие.") def handle_bind_account(message): """Обрабатывает привязку аккаунта к чату.""" global bot chat_id = message.chat.id user_id = message.from_user.id api_key = message.text logger.info(f"Попытка привязки аккаунта {api_key} к чату {chat_id}") # Проверяем существование аккаунта account = get_account_by_api_key(api_key) if not account: logger.warning(f"Аккаунт с API ключом {api_key} не найден") bot.send_message(chat_id, "Аккаунт с таким API-ключом не найден.") return # Привязываем аккаунт к чату if add_account_to_chat(chat_id, api_key, user_id): logger.info(f"Аккаунт {api_key} успешно привязан к чату {chat_id}") bot.send_message(chat_id, "Аккаунт успешно привязан к чату.") else: logger.error(f"Не удалось привязать аккаунт {api_key} к чату {chat_id}") bot.send_message(chat_id, "Не удалось привязать аккаунт к чату.") def handle_unbind_account(message): """Отвязывает аккаунт от чата.""" chat_id = message.chat.id api_key = message.text if remove_account_from_chat(chat_id, api_key): bot.send_message(chat_id, "Аккаунт успешно отвязан от чата.") else: bot.send_message(chat_id, "Не удалось отвязать аккаунт от чата.") def handle_list_chat_accounts(message): """Выводит список аккаунтов, привязанных к чату.""" chat_id = message.chat.id accounts = get_chat_accounts(chat_id) if accounts: message_text = "Аккаунты, привязанные к этому чату:\n" for api_key in accounts: message_text += f"- {api_key}\n" bot.send_message(chat_id, message_text) else: bot.send_message(chat_id, "К этому чату не привязаны аккаунты.") def handle_transfer_confirmation(message, account_balances): """Обрабатывает подтверждение перевода средств.""" chat_id = message.chat.id user_id = message.from_user.id text = message.text if text == "Подтвердить": # Получаем главный аккаунт пользователя main_account = get_main_account(user_id) if not main_account: bot.send_message(chat_id, "Сначала установите главный аккаунт.") return main_api_key = main_account[1] # api_key is at index 1 for api_key, balance in account_balances: if api_key != main_api_key: # Пропускаем главный аккаунт account = get_account_by_api_key(api_key) if account: payment_password = account[2] transfer_result = transfer_money(api_key, payment_password, balance, main_api_key) if transfer_result and transfer_result.get('success'): bot.send_message(chat_id, f"Средства ({balance} {DEFAULT_CURRENCY}) успешно переведены с аккаунта {api_key}.") else: bot.send_message(chat_id, f"Не удалось перевести средства с аккаунта {api_key}.") else: Python import telebot import sqlite3 import time import threading import logging import requests from telebot import types import json # Импортируем модуль json import sys import os # Замените 'TOKEN' на токен вашего бота BOT_TOKEN = 'TOKEN' # market.csgo.com API URL API_BASE_URL = 'https://market.csgo.com/api/v2' # Валюта по умолчанию DEFAULT_CURRENCY = 'RUB' # Настройка логирования logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Глобальная переменная для бота bot = None # Функция для создания подключения к базе данных def create_connection(): """Создает подключение к базе данных SQLite.""" try: conn = sqlite3.connect('csgoflipbot.db') return conn except Exception as e: logger.error(f"Ошибка при подключении к базе данных: {e}") return None # Функция для создания таблиц в базе данных def create_tables(): """Создает таблицы в базе данных, если они не существуют.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() # Таблица для хранения информации об аккаунтах cursor.execute(''' CREATE TABLE IF NOT EXISTS accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, api_key TEXT NOT NULL UNIQUE, payment_password TEXT NOT NULL, auto_ping INTEGER DEFAULT 0, account_name TEXT, user_id INTEGER NOT NULL, is_main INTEGER DEFAULT 0 ) ''') # Таблица для связи аккаунтов и чатов (для каждого чата свои настройки аккаунтов) cursor.execute(''' CREATE TABLE IF NOT EXISTS chat_accounts ( chat_id INTEGER NOT NULL, account_id INTEGER NOT NULL, user_id INTEGER NOT NULL, PRIMARY KEY (chat_id, account_id), FOREIGN KEY (account_id) REFERENCES accounts (id) ) ''') # Таблица для хранения инвентаря cursor.execute(''' CREATE TABLE IF NOT EXISTS inventory ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, item_id TEXT NOT NULL, market_hash_name TEXT NOT NULL, market_price REAL NOT NULL, FOREIGN KEY (account_id) REFERENCES accounts (id), UNIQUE (account_id, item_id) ) ''') conn.commit() logger.info("Таблицы базы данных успешно созданы.") except Exception as e: logger.error(f"Ошибка при создании таблиц: {e}") finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") # Функция для добавления аккаунта в базу данных def add_account(api_key, payment_password, user_id, account_name=None): """Добавляет новый аккаунт в базу данных.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() cursor.execute( "INSERT INTO accounts (api_key, payment_password, account_name, user_id) VALUES (?, ?, ?, ?)", (api_key, payment_password, account_name, user_id), ) conn.commit() logger.info(f"Аккаунт с API-ключом {api_key} успешно добавлен для пользователя {user_id}.") return True except sqlite3.IntegrityError: logger.warning(f"Аккаунт с API-ключом {api_key} уже существует.") return False except Exception as e: logger.error(f"Ошибка при добавлении аккаунта: {e}") return False finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return False # Функция для получения списка всех аккаунтов def get_all_accounts(user_id=None): """Получает список всех аккаунтов из базы данных. Если user_id указан, возвращает только аккаунты этого пользователя. Если user_id не указан, возвращает все аккаунты в системе.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() if user_id is not None: cursor.execute( "SELECT id, api_key, payment_password, auto_ping, account_name FROM accounts WHERE user_id = ?", (user_id,) ) else: cursor.execute("SELECT id, api_key, payment_password, auto_ping, account_name FROM accounts") accounts = cursor.fetchall() return accounts except Exception as e: logger.error(f"Ошибка при получении списка аккаунтов: {e}") return [] finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return [] # Функция для получения аккаунта по API-ключу def get_account_by_api_key(api_key): """Получает аккаунт из базы данных по API-ключу.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() cursor.execute("SELECT id, api_key, payment_password, auto_ping, account_name FROM accounts WHERE api_key = ?", (api_key,)) account = cursor.fetchone() return account except Exception as e: logger.error(f"Ошибка при получении аккаунта по API-ключу: {e}") return None finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return None # Функция для получения главного аккаунта пользователя def get_main_account(user_id): """Получает главный аккаунт пользователя из базы данных.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() cursor.execute( "SELECT id, api_key, payment_password, auto_ping, account_name FROM accounts WHERE user_id = ? AND is_main = 1", (user_id,) ) account = cursor.fetchone() return account except Exception as e: logger.error(f"Ошибка при получении главного аккаунта: {e}") return None finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return None # Функция для обновления настроек аккаунта def update_account_settings(api_key, auto_ping=None, payment_password=None, account_name=None, is_main=None): """Обновляет настройки аккаунта в базе данных.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() # Обновляем только переданные параметры updates = [] values = [] if auto_ping is not None: updates.append("auto_ping = ?") values.append(auto_ping) if payment_password is not None: updates.append("payment_password = ?") values.append(payment_password) if account_name is not None: updates.append("account_name = ?") values.append(account_name) if is_main is not None: # Если устанавливаем новый главный аккаунт, сбрасываем флаг у других аккаунтов этого пользователя if is_main == 1: account = get_account_by_api_key(api_key) if account: # Получаем user_id из базы данных cursor.execute("SELECT user_id FROM accounts WHERE api_key = ?", (api_key,)) user_id_result = cursor.fetchone() if user_id_result: user_id = user_id_result[0] cursor.execute( "UPDATE accounts SET is_main = 0 WHERE user_id = ? AND api_key != ?", (user_id, api_key) ) updates.append("is_main = ?") values.append(is_main) if not updates: return True # Ничего не обновлено query = f"UPDATE accounts SET {', '.join(updates)} WHERE api_key = ?" values.append(api_key) cursor.execute(query, tuple(values)) conn.commit() logger.info(f"Настройки аккаунта с API-ключом {api_key} успешно обновлены.") return True except Exception as e: logger.error(f"Ошибка при обновлении настроек аккаунта: {e}") return False finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return False # Функция для выполнения запросов к API market.csgo.com def make_api_request(api_key, method, params=None, use_post=False): """Выполняет запрос к API market.csgo.com с обработкой ошибок.""" url = f"{API_BASE_URL}/{method}?key={api_key}" # Добавляем api_key в URL try: if use_post: response = requests.post(url, data=params) else: if params: response = requests.get(url, params=params) else: response = requests.get(url) response.raise_for_status() # Поднимает исключение для HTTP ошибок return response.json() except requests.exceptions.RequestException as e: logger.error(f"Ошибка при выполнении запроса {method}: {e}") return None except json.JSONDecodeError: logger.error(f"Ошибка декодирования JSON ответа от {method}") return None # Функция для получения инвентаря аккаунта def get_inventory(api_key): """Получает инвентарь аккаунта с использованием API market.csgo.com.""" return make_api_request(api_key, 'my-inventory') def get_bid_ask_price(api_key, market_hash_name, phase=None): """Получает актуальные цены bid-ask для предмета.""" url = f"{API_BASE_URL}/bid-ask" params = { 'key': api_key, 'hash_name': market_hash_name } if phase: params['phase'] = phase try: response = requests.get(url, params=params) response.raise_for_status() data = response.json() # Получаем максимальную цену из bid if data.get('bid'): max_bid = max(float(bid['price']) for bid in data['bid']) return max_bid return None except Exception as e: logger.error(f"Ошибка при получении bid-ask цен: {e}") return None def store_inventory_in_db(api_key, inventory_data): """Сохраняет инвентарь в базу данных.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() account_id = get_account_by_api_key(api_key)[0] # Получаем ID аккаунта # Очищаем старые записи для этого аккаунта cursor.execute("DELETE FROM inventory WHERE account_id = ?", (account_id,)) for item in inventory_data.get('items', []): item_id = item.get('id') market_hash_name = item.get('market_hash_name') if item_id and market_hash_name: # Получаем актуальную цену через bid-ask current_price = get_bid_ask_price(api_key, market_hash_name) if current_price is None: current_price = item.get('market_price', 0) # Используем старую цену как запасной вариант cursor.execute( "INSERT INTO inventory (account_id, item_id, market_hash_name, market_price) VALUES (?, ?, ?, ?)", (account_id, item_id, market_hash_name, current_price) ) conn.commit() logger.info(f"Инвентарь аккаунта {api_key} успешно сохранен в базе данных.") except Exception as e: logger.error(f"Ошибка при сохранении инвентаря в базу данных: {e}") finally: conn.close() # Функция для выставления предмета на продажу def add_to_sale(api_key, item_id, price, currency=DEFAULT_CURRENCY): """Выставляет предмет на продажу на market.csgo.com.""" # Преобразуем цену в копейки (умножаем на 100 и убираем десятичную часть) price_in_cents = int(float(price) * 100) params = {'id': item_id, 'price': price_in_cents, 'cur': currency} logger.info(f"Выставление предмета {item_id} на продажу. Цена в копейках: {price_in_cents}") return make_api_request(api_key, 'add-to-sale', params) # Функция для получения баланса аккаунта def get_balance(api_key): """Получает баланс аккаунта.""" return make_api_request(api_key, 'get-money') # Функция для перевода средств def transfer_money(api_key, payment_password, amount, user_api_key): """Переводит средства с аккаунта.""" # Преобразуем сумму в копейки (умножаем на 100 и убираем десятичную часть) amount_in_cents = int(float(amount) * 100) url = f"{API_BASE_URL}/money-send/{amount_in_cents}/{user_api_key}?key={api_key}&pay_pass={payment_password}" try: response = requests.get(url) # Изменен метод на GET response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: logger.error(f"Ошибка при выполнении запроса money-send: {e}") return None except json.JSONDecodeError: logger.error(f"Ошибка декодирования JSON ответа от money-send") return None # Функция для обновления инвентаря def update_inventory(api_key): """Запрашивает обновление кеша инвентаря.""" return make_api_request(api_key, 'update-inventory') # Функция для пинга новых предметов def ping_new_items(api_key): """Отправляет POST запрос на ping-new endpoint.""" return make_api_request(api_key, 'ping-new', use_post=True) # Функция для получения списка аккаунтов, привязанных к чату def get_chat_accounts(chat_id, user_id): """Получает список API-ключей аккаунтов, привязанных к чату для конкретного пользователя.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() cursor.execute( "SELECT a.api_key FROM accounts a INNER JOIN chat_accounts ca ON a.id = ca.account_id WHERE ca.chat_id = ? AND ca.user_id = ?", (chat_id, user_id), ) accounts = [row[0] for row in cursor.fetchall()] return accounts except Exception as e: logger.error(f"Ошибка при получении аккаунтов чата {chat_id}: {e}") return [] finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return [] # Функция для привязки аккаунта к чату def add_account_to_chat(chat_id, api_key, user_id): """Привязывает аккаунт к чату для конкретного пользователя.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() account_id = get_account_by_api_key(api_key)[0] cursor.execute( "INSERT INTO chat_accounts (chat_id, account_id, user_id) VALUES (?, ?, ?)", (chat_id, account_id, user_id), ) conn.commit() logger.info(f"Аккаунт {api_key} привязан к чату {chat_id} для пользователя {user_id}.") return True except Exception as e: logger.error(f"Ошибка при привязке аккаунта к чату: {e}") return False finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return False # Функция для отвязки аккаунта от чата def remove_account_from_chat(chat_id, api_key, user_id): """Отвязывает аккаунт от чата для конкретного пользователя.""" conn = create_connection() if conn is not None: try: cursor = conn.cursor() account_id = get_account_by_api_key(api_key)[0] cursor.execute( "DELETE FROM chat_accounts WHERE chat_id = ? AND account_id = ? AND user_id = ?", (chat_id, account_id, user_id), ) conn.commit() logger.info(f"Аккаунт {api_key} отвязан от чата {chat_id} для пользователя {user_id}.") return True except Exception as e: logger.error(f"Ошибка при отвязке аккаунта от чата: {e}") return False finally: conn.close() else: logger.error("Не удалось подключиться к базе данных.") return False # Функция для запуска пинга новых предметов для всех аккаунтов с auto_ping = 1 def start_auto_ping(bot): """Запускает периодический пинг новых предметов для аккаунтов с auto_ping = 1.""" def ping_loop(): while True: accounts = get_all_accounts() for account in accounts: account_id, api_key, _, auto_ping, _ = account if auto_ping == 1: try: response = ping_new_items(api_key) if response: logger.info(f"Успешно отправлен ping-new для аккаунта {api_key}.") else: logger.warning(f"Не удалось отправить ping-new для аккаунта {api_key}.") except Exception as e: logger.error(f"Ошибка при выполнении ping-new для аккаунта {api_key}: {e}") time.sleep(180) # Интервал 3 минуты (180 секунд) # Запускаем пинг в отдельном потоке threading.Thread(target=ping_loop, daemon=True).start() def get_main_menu_keyboard(): """Создает основную клавиатуру меню.""" markup = types.InlineKeyboardMarkup(row_width=2) buttons = [ types.InlineKeyboardButton("Добавить аккаунт", callback_data="add_account"), types.InlineKeyboardButton("Список аккаунтов", callback_data="list_accounts"), types.InlineKeyboardButton("Установить главный аккаунт", callback_data="set_main_account"), types.InlineKeyboardButton("Вывод средств", callback_data="show_balance"), types.InlineKeyboardButton("Выставить предметы", callback_data="add_to_sale"), types.InlineKeyboardButton("Обновить инвентарь", callback_data="update_inventory"), types.InlineKeyboardButton("Включить автоподнятие", callback_data="enable_ping"), types.InlineKeyboardButton("Выключить автоподнятие", callback_data="disable_ping"), types.InlineKeyboardButton("Удалить аккаунт", callback_data="delete_account") ] markup.add(*buttons) return markup def get_cancel_keyboard(): """Создает инлайн клавиатуру с кнопкой отмены.""" markup = types.InlineKeyboardMarkup() cancel_button = types.InlineKeyboardButton("Отменить", callback_data="cancel") delete_account_button = types.InlineKeyboardButton("Удалить аккаунт", callback_data="delete_account") markup.add(cancel_button, delete_account_button) return markup def handle_enable_auto_ping(message): """Обрабатывает включение автоподнятия для аккаунта.""" global bot chat_id = message.chat.id api_key = message.text logger.info(f"Попытка включения автоподнятия для аккаунта {api_key}") # Проверяем существование аккаунта account = get_account_by_api_key(api_key) if not account: logger.warning(f"Аккаунт с API ключом {api_key} не найден") bot.send_message(chat_id, "Аккаунт с таким API-ключом не найден.") return # Обновляем настройки аккаунта if update_account_settings(api_key, auto_ping=1): logger.info(f"Автоподнятие успешно включено для аккаунта {api_key}") bot.send_message(chat_id, "Автоподнятие успешно включено.") else: logger.error(f"Не удалось включить автоподнятие для аккаунта {api_key}") bot.send_message(chat_id, "Не удалось включить автоподнятие.") def handle_update_inventory(message): """Обрабатывает запрос на обновление инвентаря.""" global bot chat_id = message.chat.id api_key = message.text logger.info(f"Попытка обновления инвентаря для аккаунта {api_key}") # Проверяем существование аккаунта account = get_account_by_api_key(api_key) if not account: logger.warning(f"Аккаунт с API ключом {api_key} не найден") bot.send_message(chat_id, "Аккаунт с таким API-ключом не найден.") return # Обновляем инвентарь result = update_inventory(api_key) if result and result.get('success'): logger.info(f"Инвентарь успешно обновлен для аккаунта {api_key}") bot.send_message(chat_id, "Инвентарь успешно обновлен.") else: logger.error(f"Не удалось обновить инвентарь для аккаунта {api_key}") bot.send_message(chat_id, "Не удалось обновить инвентарь.") def handle_disable_auto_ping(message): """Обрабатывает выключение автоподнятия для аккаунта.""" global bot chat_id = message.chat.id api_key = message.text logger.info(f"Попытка выключения автоподнятия для аккаунта {api_key}") # Проверяем существование аккаунта account = get_account_by_api_key(api_key) if not account: logger.warning(f"Аккаунт с API ключом {api_key} не найден") bot.send_message(chat_id, "Аккаунт с таким API-ключом не найден.") return # Обновляем настройки аккаунта if update_account_settings(api_key, auto_ping=0): logger.info(f"Автоподнятие успешно выключено для аккаунта {api_key}") bot.send_message(chat_id, "Автоподнятие успешно выключено.") else: logger.error(f"Не удалось выключить автоподнятие для аккаунта {api_key}") bot.send_message(chat_id, "Не удалось выключить автоподнятие.") def handle_bind_account(message): """Обрабатывает привязку аккаунта к чату.""" global bot chat_id = message.chat.id user_id = message.from_user.id api_key = message.text logger.info(f"Попытка привязки аккаунта {api_key} к чату {chat_id}") # Проверяем существование аккаунта account = get_account_by_api_key(api_key) if not account: logger.warning(f"Аккаунт с API ключом {api_key} не найден") bot.send_message(chat_id, "Аккаунт с таким API-ключом не найден.") return # Привязываем аккаунт к чату if add_account_to_chat(chat_id, api_key, user_id): logger.info(f"Аккаунт {api_key} успешно привязан к чату {chat_id}") bot.send_message(chat_id, "Аккаунт успешно привязан к чату.") else: logger.error(f"Не удалось привязать аккаунт {api_key} к чату {chat_id}") bot.send_message(chat_id, "Не удалось привязать аккаунт к чату.") def handle_unbind_account(message): """Отвязывает аккаунт от чата.""" chat_id = message.chat.id api_key = message.text if remove_account_from_chat(chat_id, api_key): bot.send_message(chat_id, "Аккаунт успешно отвязан от чата.") else: bot.send_message(chat_id, "Не удалось отвязать аккаунт от чата.") def handle_list_chat_accounts(message): """Выводит список аккаунтов, привязанных к чату.""" chat_id = message.chat.id accounts = get_chat_accounts(chat_id) if accounts: message_text = "Аккаунты, привязанные к этому чату:\n" for api_key in accounts: message_text += f"- {api_key}\n" bot.send_message(chat_id, message_text) else: bot.send_message(chat_id, "К этому чату не привязаны аккаунты.") def handle_transfer_confirmation(message, account_balances): """Обрабатывает подтверждение перевода средств.""" chat_id = message.chat.id user_id = message.from_user.id text = message.text if text == "Подтвердить": # Получаем главный аккаунт пользователя main_account = get_main_account(user_id) if not main_account: bot.send_message(chat_id, "Сначала установите главный аккаунт.") return main_api_key = main_account[1] # api_key is at index 1 for api_key, balance in account_balances: if api_key != main_api_key: # Пропускаем главный аккаунт account = get_account_by_api_key(api_key) if account: payment_password = account[2] transfer_result = transfer_money(api_key, payment_password, balance, main_api_key) if transfer_result and transfer_result.get('success'): bot.send_message(chat_id, f"Средства ({balance} {DEFAULT_CURRENCY}) успешно переведены с аккаунта {api_key}.") else: bot.send_message(chat_id, f"Не удалось перевести средства с аккаунта {api_key}.") else: Зависимости для работы скрипта pyTelegramBotAPI>=4.14.0 requests>=2.31.0 используем Python 3.10
cedro, с учетом того как маркет долго инвент обновляет если делать все руками - это еще и экономия времени в сотню раз