From e08b09bf7df56968d633c3e06e7fd74f7202820c Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Mon, 16 Jun 2025 16:24:35 +0800 Subject: [PATCH 01/10] Update CSFloat-Auto-Trade.py --- CSFloat-Auto-Trade.py | 68 +++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/CSFloat-Auto-Trade.py b/CSFloat-Auto-Trade.py index 3dc1c2d..8f01cab 100644 --- a/CSFloat-Auto-Trade.py +++ b/CSFloat-Auto-Trade.py @@ -1,7 +1,9 @@ import asyncio import json import aiohttp +import sys, time,os from pathlib import Path +from aiohttp_socks.connector import ProxyConnector from aiosteampy import SteamClient, AppContext from aiosteampy.utils import get_jsonable_cookies from aiosteampy.helpers import restore_from_cookies @@ -17,13 +19,20 @@ API_ACCEPT_TRADE = "https://csfloat.com/api/v1/trades/{trade_id}/accept" # Define the accept trade endpoint # Path to a file to save cookies, will be created at end of a script run if do not exist -COOKIE_FILE = Path("cookies.json") -USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0" +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) +COOKIE_FILE = Path(rf"{SCRIPT_DIR}/cookies.json") +# print(str(COOKIE_FILE)) +# print(COOKIE_FILE) +if COOKIE_FILE.is_file(): + print("cookie file true") +# time.sleep(10) +# sys.exit() +USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" # Path to store processed trade IDs -PROCESSED_TRADES_FILE = Path("processed_trades.json") +PROCESSED_TRADES_FILE = Path(rf"{SCRIPT_DIR}/processed_trades.json") -def load_steam_config(config_path='steam.json'): +def load_steam_config(config_path=rf"{SCRIPT_DIR}/steam.json"): with open(config_path, 'r') as file: return json.load(file) @@ -102,7 +111,7 @@ async def send_steam_trade(client: SteamClient, trade_id, buyer_steam_id=None, t # Проверка структуры предметов в инвентаре if not my_inv: - print("Ваш инвентарь пуст или не удалось его загрузить.") + print("Your inventory is empty or could not be loaded.") return False # Попытка найти предмет по asset_id @@ -113,7 +122,8 @@ async def send_steam_trade(client: SteamClient, trade_id, buyer_steam_id=None, t item_to_give = next((item for item in my_inv if item.asset_id == asset_id), None) if not item_to_give: - print(f"Предмет с asset_id {asset_id} не найден в инвентаре.") + print(f"Item with asset_id {asset_id} not found in inventory.") + # print(f"Предмет с asset_id {asset_id} не найден в инвентаре.") return False # Вызов make_trade_offer с использованием Steam ID или Trade URL @@ -187,7 +197,8 @@ async def check_actionable_trades(session, csfloat_api_key, client: SteamGuardMi if user_info and user_info.get('actionable_trades', 0) > 0: print("Actionable trades found, fetching trade details...") trades_info = await get_trades(session, csfloat_api_key) - + # print("asfasf.")#debug + # sys.exit()#debug if isinstance(trades_info, dict): trades_list = trades_info.get('trades', []) @@ -267,7 +278,15 @@ async def check_actionable_trades(session, csfloat_api_key, client: SteamGuardMi print(f"Unexpected trades data format: {type(trades_info)}") else: print(f"No actionable trades at the moment. Waiting for {check_interval_minutes} minutes before next check.") - +def any2bool(v): + return str(v).lower() in ("yes", "true", "t", "1") +def readConfigValue(configJson,jsonKey): + try: + jsonValue= configJson[jsonKey] + except Exception as err: + print(f"Couldn't load value from config file: {jsonKey}") + else: + return jsonValue async def main(): config = load_steam_config() # Загрузка конфигурации @@ -278,14 +297,17 @@ async def main(): steam_password = config['steam_password'] shared_secret = config['shared_secret'] identity_secret = config['identity_secret'] - + cilent_proxy = readConfigValue(config,'cilent_proxy') + steam_use_proxy = any2bool(readConfigValue(config,'steam_use_proxy')) # Acceptable true value: "yes", "true", "t", "y", "1" + if cilent_proxy: + print(f"proxy true: {cilent_proxy}") # Определение продолжительности ожидания (в минутах) CHECK_INTERVAL_MINUTES = 5 # Вы можете легко изменить это значение # Инициализация SteamClient с необходимыми аргументами class MySteamClient(SteamClient, SteamWebApiMixin, SteamGuardMixin): pass - + # print(steam_use_proxy) client = MySteamClient( steam_id=steam_id, # Steam ID64 как целое число username=steam_login, @@ -295,19 +317,35 @@ class MySteamClient(SteamClient, SteamWebApiMixin, SteamGuardMixin): api_key=steam_api_key, # Передача API ключа user_agent=USER_AGENT, ) - + if cilent_proxy and steam_use_proxy==True: + MySteamClient.proxy=cilent_proxy + print("steam proxy true") + # print(client.proxy) + else: + print(f"steam proxy false") + # sys.exit() # Восстановление cookies, если они существуют + if COOKIE_FILE.is_file(): - with COOKIE_FILE.open("r") as f: - cookies = json.load(f) - await restore_from_cookies(cookies, client) + try: + with COOKIE_FILE.open("r") as f: + cookies = json.load(f) + await restore_from_cookies(cookies, client) + except Exception as err: + print(f"{err}") + await client.login() else: await client.login() # Загрузка обработанных трейдов processed_trades = load_processed_trades() + + sessionConnector = ProxyConnector.from_url(cilent_proxy, ttl_dns_cache=300) if cilent_proxy else aiohttp.TCPConnector( + resolver=aiohttp.resolver.AsyncResolver(), + limit_per_host=50 + ) - async with aiohttp.ClientSession() as session: + async with aiohttp.ClientSession(connector=sessionConnector) as session: try: while True: await check_actionable_trades( From 8a22bdb32407e3b3ffb65a199f66d14ed6e974b9 Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Mon, 16 Jun 2025 17:15:46 +0800 Subject: [PATCH 02/10] Update README.md --- README.md | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e95b052..eaeecf6 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,58 @@ +- [русский](README_ru.md) -## Шаг 1: Клонирование репозитория +## Step 1: Clone the repository -Сначала склонируйте репозиторий с GitHub на ваш локальный компьютер. +First, clone the repository from GitHub to your local computer. -1. **Откройте терминал (Командную строку или PowerShell на Windows).** +1. **Open a terminal (Command Prompt or PowerShell on Windows).** -2. **Выполните команду:** +2. **Run the command:** `git clone https://github.com/gradinazz/CSFloat-Auto-Trade.git` -3. **Перейдите в директорию проекта:** +3. **Go to the project directory:** `cd CSFloat-Auto-Trade` -## Шаг 2: Установка зависимостей +## Step 2: Install Dependencies -Установите необходимые пакеты, перечисленные в файле `requirements.txt`. +Install the required packages listed in `requirements.txt`. -1. **Убедитесь, что находитесь в директории проекта и активировано виртуальное окружение.** +1. **Make sure you are in the project directory and the Python virtual environment is activated.** -2. **Выполните команду:** +2. **Run the command:** `pip install -r requirements.txt` -## Шаг 3: Конфигурация скрипта +## Step 3: Script Configuration -Перед запуском скрипта необходимо настроить конфигурационный файл `steam.json`. +Before running the script, you need to configure the configuration file `steam.json`. - - **Отредактируйте файл `steam.json` в корне проекта.** + - **Edit the `steam.json` file in the root of the project.** - - **Добавьте в него следующие параметры:** + - **Add the following parameters to it:** - - `csfloat_api_key`: Ваш API-ключ от CSFloat. - - `steam_api_key`: Ваш Steam API-ключ. - - `steam_id64`: Ваш Steam ID64 (например, `76561198034388123`). - - `steam_login`: Ваш логин от Steam. - - `steam_password`: Ваш пароль от Steam. - - `shared_secret` и `identity_secret`: Секреты, необходимые для подтверждения торговых предложений. Их можно получить из maFile. + - `csfloat_api_key`: Your CSFloat api key. + - `steam_api_key`: Your Steam API-ключ. + - `steam_id64`: Your Steam ID64 (example, `76561198034388123`). + - `steam_login`: Your Steam username. + - `steam_password`: Your Steam password. + - `shared_secret` and `identity_secret`: Secrets needed to confirm trade offers. Can be obtained from maFile. + - `cilent_proxy`: Optional, set the proxy. + - `steam_use_proxy`: Optional, apply proxy for steam cilent if true. - **Важно:** Никогда не делитесь этими ключами и секретами. Храните их в безопасном месте. + **Important:** Never share these keys and secrets. Keep them in a safe place. -## Шаг 4: Запуск скрипта +## Step 4: Run the script -Теперь вы готовы запустить скрипт. +Now you are ready to run the script. -1. **Выполните команду:** +1. **Run the command:** `python CSFloat-Auto-Trade.py` -2. **Скрипт начнёт выполнение и будет проверять наличие новых торговых предложений каждые 5 минут (по умолчанию).** +2. **The script will start executing and will check for new trade offers every 5 minutes (by default).** From 43c7ea1776a37c35b08abe59951846f97ef0c46a Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Mon, 16 Jun 2025 17:21:31 +0800 Subject: [PATCH 03/10] Add files via upload --- README_ru.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 README_ru.md diff --git a/README_ru.md b/README_ru.md new file mode 100644 index 0000000..7fb9225 --- /dev/null +++ b/README_ru.md @@ -0,0 +1,57 @@ + +## Шаг 1: Клонирование репозитория + +Сначала склонируйте репозиторий с GitHub на ваш локальный компьютер. + +1. **Откройте терминал (Командную строку или PowerShell на Windows).** + +2. **Выполните команду:** + + `git clone https://github.com/gradinazz/CSFloat-Auto-Trade.git` + +3. **Перейдите в директорию проекта:** + + `cd CSFloat-Auto-Trade` + + +## Шаг 2: Установка зависимостей + +Установите необходимые пакеты, перечисленные в файле `requirements.txt`. + +1. **Убедитесь, что находитесь в директории проекта и активировано виртуальное окружение.** + +2. **Выполните команду:** + + `pip install -r requirements.txt` + + +## Шаг 3: Конфигурация скрипта + +Перед запуском скрипта необходимо настроить конфигурационный файл `steam.json`. + + - **Отредактируйте файл `steam.json` в корне проекта.** + + - **Добавьте в него следующие параметры:** + + - `csfloat_api_key`: Ваш API-ключ от CSFloat. + - `steam_api_key`: Ваш Steam API-ключ. + - `steam_id64`: Ваш Steam ID64 (например, `76561198034388123`). + - `steam_login`: Ваш логин от Steam. + - `steam_password`: Ваш пароль от Steam. + - `shared_secret` и `identity_secret`: Секреты, необходимые для подтверждения торговых предложений. Их можно получить из maFile. + - `cilent_proxy`: Необязательно: Установите прокси. + - `steam_use_proxy`: Необязательно: Применить прокси для Steam cilent, если true. + + **Важно:** Никогда не делитесь этими ключами и секретами. Храните их в безопасном месте. + + +## Шаг 4: Запуск скрипта + +Теперь вы готовы запустить скрипт. + +1. **Выполните команду:** + + `python CSFloat-Auto-Trade.py` + +2. **Скрипт начнёт выполнение и будет проверять наличие новых торговых предложений каждые 5 минут (по умолчанию).** + From d1906b459429e65661987754a155034a783be134 Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Thu, 19 Jun 2025 05:13:44 +0800 Subject: [PATCH 04/10] Add files via upload --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index eaeecf6..d1d49f2 100644 --- a/README.md +++ b/README.md @@ -34,14 +34,18 @@ Before running the script, you need to configure the configuration file `steam.j - **Add the following parameters to it:** - - `csfloat_api_key`: Your CSFloat api key. - - `steam_api_key`: Your Steam API-ключ. - - `steam_id64`: Your Steam ID64 (example, `76561198034388123`). + - `csfloat_api_key`: Your CSFloat API key. + - `steam_api_key`: Your Steam API key. + - `steam_id64`: Your Steam ID64(example: `76561198034388123`). - `steam_login`: Your Steam username. - `steam_password`: Your Steam password. - `shared_secret` and `identity_secret`: Secrets needed to confirm trade offers. Can be obtained from maFile. - - `cilent_proxy`: Optional, set the proxy. - - `steam_use_proxy`: Optional, apply proxy for steam cilent if true. + - `cilent_proxy`: Optional: Set the proxy(example: `http://127.0.0.1:20122`). + - `steam_use_proxy`: Optional: Apply proxy for steam cilent if setted to "true". + - `check_interval_seconds`: Optional: Set the interval in seconds bewteen checks. + - `check_interval_seconds_random`: Optional: Enable randomizing the interval bewteen checks if setted to "true". + - `check_interval_seconds_random_min`: Optional: Set the minimum randomized interval in seconds bewteen checks. + - `check_interval_seconds_random_max`: Optional: Set the maximum randomized interval in seconds bewteen checks. **Important:** Never share these keys and secrets. Keep them in a safe place. From ff7652d7ef20676378dd7e473cfbab609791863e Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Thu, 19 Jun 2025 05:14:39 +0800 Subject: [PATCH 05/10] Add files via upload --- CSFloat-Auto-Trade.py | 489 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 397 insertions(+), 92 deletions(-) diff --git a/CSFloat-Auto-Trade.py b/CSFloat-Auto-Trade.py index 8f01cab..0adddc1 100644 --- a/CSFloat-Auto-Trade.py +++ b/CSFloat-Auto-Trade.py @@ -1,17 +1,31 @@ import asyncio import json import aiohttp -import sys, time,os +import os,random from pathlib import Path from aiohttp_socks.connector import ProxyConnector from aiosteampy import SteamClient, AppContext -from aiosteampy.utils import get_jsonable_cookies +from aiosteampy.utils import get_jsonable_cookies,JSONABLE_COOKIE_JAR +from aiosteampy.client import SteamClientBase +from aiosteampy.models import TradeOffer from aiosteampy.helpers import restore_from_cookies from aiosteampy.mixins.guard import SteamGuardMixin # Импортируем SteamGuard для подтверждения трейдов from aiosteampy.mixins.web_api import SteamWebApiMixin # Импортируем WebApiMixin для работы с Web API +from aiosteampy.constants import ( + App, + AppContext, + STEAM_URL, + Currency, + Language, + TradeOfferStatus, + MarketListingStatus, + EResult, + ConfirmationType, +) +# from collections import OrderedDict # Продолжительность ожидания между проверками (в минутах) -CHECK_INTERVAL_MINUTES = 5 +# CHECK_INTERVAL_MINUTES = 5 # Constants for API endpoints API_USER_INFO = "https://csfloat.com/api/v1/me" @@ -32,9 +46,70 @@ # Path to store processed trade IDs PROCESSED_TRADES_FILE = Path(rf"{SCRIPT_DIR}/processed_trades.json") +# Инициализация SteamClient с необходимыми аргументами +class MySteamClient(SteamClient, SteamWebApiMixin, SteamGuardMixin): + pass + def load_steam_config(config_path=rf"{SCRIPT_DIR}/steam.json"): with open(config_path, 'r') as file: return json.load(file) + +async def restore_from_cookies_retry(cookies: JSONABLE_COOKIE_JAR, steam_client: "SteamClientBase"): + try_count=0 + while True: + try: + await restore_from_cookies(cookies, steam_client) + print(f"Loaded Steam account: {steam_client.username}") + return + except aiohttp.ClientResponseError as http_err: + print(f"HTTP error occurred while restoring the Steam session from cookies: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while restoring the Steam session from cookies: {connect_err}") + except Exception as err: + print(f"Other error occurred while restoring the Steam session from cookies: {err}") + try_count+=1 + if try_count >5: + print("Failed too many times.") + return None + await asyncio.sleep(50) + +async def steam_client_login_retry(steam_client: "SteamClientBase"): + try_count=0 + while True: + try: + await steam_client.login() + print(f"Loaded Steam account: {steam_client.username}") + return + except aiohttp.ClientResponseError as http_err: + print(f"HTTP error occurred while logging in to Steam: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while logging in to Steam: {connect_err}") + except Exception as err: + print(f"Other error occurred while logging in to Steam: {err}") + try_count+=1 + if try_count >5: + print("Failed too many times.") + return None + await asyncio.sleep(50) + +async def confirm_trade_offer_retry(steam_client: "SteamClientBase", obj: int | TradeOffer): + try_count=0 + while True: + try: + print(f"Confirming trade offer {obj}.") + await steam_client.confirm_trade_offer(obj) + return + except aiohttp.ClientResponseError as http_err: + print(f"HTTP error occurred while confirming the trade offer: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while confirming the trade offer: {connect_err}") + except Exception as err: + print(f"Other error occurred while confirming the trade offer: {err}") + try_count+=1 + if try_count >5: + print("Failed too many times.") + return None + await asyncio.sleep(50) def load_processed_trades(): if PROCESSED_TRADES_FILE.is_file(): @@ -57,23 +132,33 @@ async def get_user_info(session, csfloat_api_key): response.raise_for_status() return await response.json() except aiohttp.ClientResponseError as http_err: - print(f"HTTP error occurred while fetching user info: {http_err}") + print(f"HTTP error occurred while fetching CSFloat user info: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while fetching CSFloat user info: {connect_err}") except Exception as err: - print(f"Other error occurred while fetching user info: {err}") + print(f"Other error occurred while fetching CSFloat user info: {err}") return None async def get_trades(session, csfloat_api_key): headers = {'Authorization': csfloat_api_key} - try: - async with session.get(API_TRADES, headers=headers) as response: - response.raise_for_status() - trades_data = await response.json() - return trades_data - except aiohttp.ClientResponseError as http_err: - print(f"HTTP error occurred while fetching trades: {http_err}") - except Exception as err: - print(f"Other error occurred while fetching trades: {err}") - return None + try_count=0 + while True: + try: + async with session.get(API_TRADES, headers=headers) as response: + response.raise_for_status() + trades_data = await response.json() + # print(trades_data)#debug + return trades_data + except aiohttp.ClientResponseError as http_err: + print(f"HTTP error occurred while fetching trades: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while fetching trades: {connect_err}") + except Exception as err: + print(f"Other error occurred while fetching trades: {err}") + try_count+=1 + if try_count >5: + return None + await asyncio.sleep(50) async def accept_trade(session, csfloat_api_key, trade_id, trade_token): url = API_ACCEPT_TRADE.format(trade_id=trade_id) @@ -96,61 +181,95 @@ async def accept_trade(session, csfloat_api_key, trade_id, trade_token): return True except aiohttp.ClientResponseError as http_err: print(f"HTTP error occurred while accepting trade {trade_id}: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while accepting trade: {connect_err}") except Exception as err: print(f"Other error occurred while accepting trade {trade_id}: {err}") return False -async def send_steam_trade(client: SteamClient, trade_id, buyer_steam_id=None, trade_url=None, asset_id=None, trade_token=None): +async def csfloat_send_steam_trade(client: SteamClient, trade_id, buyer_steam_id=None, trade_url=None, asset_id=None, trade_token=None): try: # Определение контекста игры, например, CS2 game_context = AppContext.CS2 # Убедитесь, что это правильный контекст для вашего предмета # Получение вашего инвентаря - my_inv, _, _ = await client.get_inventory(game_context) + my_inv, _, _ = await client.get_inventory(game_context,count=2000) # Проверка структуры предметов в инвентаре if not my_inv: print("Your inventory is empty or could not be loaded.") return False + + #wip compare to history offers # Попытка найти предмет по asset_id + asset_id = list(asset_id) + if not asset_id: #if all items to trade on csfloat are already included in created trade offers. + print("Nothing to give for trade offer.") + return False + asset_id_len=len(asset_id) + # print(f"asset_id {asset_id}") + print(f"asset_id_len {asset_id_len}") + items_to_give=[] try: - asset_id_int = int(asset_id) - item_to_give = next((item for item in my_inv if item.asset_id == asset_id_int), None) + for tai in asset_id: + items_to_give.append(next((item for item in my_inv if item.asset_id == tai))) + # items_to_give = list((item for item in my_inv if item.asset_id == asset_id)) + items_to_give_len=len(items_to_give) + # print(f"items_to_give {items_to_give}") + print(f"items_to_give_len {items_to_give_len}") + + if asset_id_len!=items_to_give_len: + print("Can't find all items to give.") + return False + except ValueError: - item_to_give = next((item for item in my_inv if item.asset_id == asset_id), None) + # items_to_give = next((item for item in my_inv if item.asset_id == asset_id), None) + pass - if not item_to_give: - print(f"Item with asset_id {asset_id} not found in inventory.") + if not items_to_give: #wip find missing items + if asset_id_len==1: + print(f"Item with asset_id {asset_id} not found in the inventory.") + else: + print(f"Item with asset_id {asset_id[0]} and {asset_id_len-1} other items not found in the inventory.") # print(f"Предмет с asset_id {asset_id} не найден в инвентаре.") return False - + if items_to_give_len>1: + trades_num_other=items_to_give_len-1 + offer_message=f"CSFloat Market Trade Offer #{trade_id} and {trades_num_other} other items Thanks for using CSFloat!" + else: + offer_message=f"CSFloat Market Trade Offer #{trade_id}. Thanks for using CSFloat!" + print(f"trade_id {trade_id} buyer_steam_id {buyer_steam_id} trade_url {trade_url} asset_id {asset_id} trade_token {trade_token} offer_message {offer_message}") + # return #debug # Вызов make_trade_offer с использованием Steam ID или Trade URL if trade_url: # Отправка через трейд-ссылку offer_id = await client.make_trade_offer( trade_url, # Трейд-ссылка как первый позиционный аргумент - to_give=[item_to_give], + to_give=items_to_give, to_receive=[], - message="" + message=offer_message, + confirm=False #debug ) elif buyer_steam_id: # Отправка через Steam ID партнёра if trade_token: offer_id = await client.make_trade_offer( buyer_steam_id, # Steam ID партнёра как первый позиционный аргумент - to_give=[item_to_give], + to_give=items_to_give, to_receive=[], - message="", - token=trade_token # Передача trade_token, если требуется + message=offer_message, + token=trade_token, # Передача trade_token, если требуется + confirm=False #debug ) else: offer_id = await client.make_trade_offer( buyer_steam_id, # Steam ID партнёра как первый позиционный аргумент - to_give=[item_to_give], + to_give=items_to_give, to_receive=[], - message="" + message=offer_message, + confirm=False #debug ) else: print("Необходимо указать либо buyer_steam_id, либо trade_url.") @@ -165,12 +284,15 @@ async def send_steam_trade(client: SteamClient, trade_id, buyer_steam_id=None, t except aiohttp.ClientResponseError as http_err: print(f"HTTP error occurred while sending trade offer: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while sending trade offer: {connect_err}") except Exception as e: print(f"An error occurred while sending trade offer: {e}") return False # Функция подтверждения трейдов, если требуется async def confirm_trade(client: SteamGuardMixin): + return#debug try: confirmations = await client.get_confirmations() @@ -191,107 +313,283 @@ async def confirm_trade(client: SteamGuardMixin): except Exception as e: print(f"An error occurred while confirming trades: {e}") -async def check_actionable_trades(session, csfloat_api_key, client: SteamGuardMixin, shared_secret, identity_secret, processed_trades, check_interval_minutes): - user_info = await get_user_info(session, csfloat_api_key) +async def get_actionable_trades_sell(session, csfloat_api_key,my_steam_id): + trades_info = await get_trades(session, csfloat_api_key) + if isinstance(trades_info, dict): + trades_list = trades_info.get('trades', []) + trades_list_sell = list(filter(lambda c: int(c['seller_id']) ==my_steam_id and not any2bool(c['wait_for_cancel_ping']), trades_list)) + return trades_list_sell + else: + print(f"Unexpected trades data format: {type(trades_info)}") + return None +async def check_actionable_trades(session, csfloat_api_key, client: MySteamClient, shared_secret, identity_secret, processed_trades, check_interval_seconds,my_steam_id): + user_info = await get_user_info(session, csfloat_api_key) + # print(user_info)#debug + if user_info and user_info.get('actionable_trades', 0) > 0: print("Actionable trades found, fetching trade details...") - trades_info = await get_trades(session, csfloat_api_key) - # print("asfasf.")#debug + # print(trades_info)#debug # sys.exit()#debug - if isinstance(trades_info, dict): - trades_list = trades_info.get('trades', []) + trades_list_sell=await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id) + if trades_list_sell: + # return#debug + # print(trades_list_sell)#debug + buyer_id_n_market_hash_name=[] + index_excluded=[] + offer_maker=[] + trades_list_sell_to_accept=list(filter(lambda c: not c.get('accepted_at'), trades_list_sell)) + # print(trades_list_sell_to_accept) #debug + if trades_list_sell_to_accept: + trades_list_sell_to_accept_processing=trades_list_sell_to_accept + trades_accept_loop_count=0 + while True: + # print("asfdsgsd.") + if trades_accept_loop_count>8: + print(f"trades_accept looped more than {trades_accept_loop_count} times. Stop for this check.") + return + if trades_accept_loop_count%3==0: + print("Updating the trade list.") #wip fetch new items + trades_list_sell_to_accept=list(filter(lambda c: not c.get('accepted_at'), await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id))) + # print(trades_list_sell_to_accept)#debug + if not trades_list_sell_to_accept: + print("All accetable trade accepted.") + break + + if isinstance(trades_list_sell_to_accept, list): + # print("afsfsdsdf.") + for trade in trades_list_sell_to_accept: + # print("asfsdggs.") + if isinstance(trade, dict): + trade_id = trade.get('id') + seller_id = int(trade.get('seller_id')) # ID отправителя + buyer_id = int(trade.get('buyer_id')) # ID получателя + asset_id = trade.get('contract', {}).get('item', {}).get('asset_id') + trade_token = trade.get('trade_token') # Получаем trade_token + trade_url = trade.get('trade_url') # Получаем trade_url + trade_state = trade.get('state') # Получаем состояние трейда + # print("sgdgdfasd.") + if trade_id and seller_id and buyer_id and asset_id: + print(f"Trade {trade_id} is a sold trade.") + # print(f"Trade {trade_id} is a sold trade.") + # continue#debug + + print(f"Accepting trade {trade_id}...") + accept_result = await accept_trade(session, csfloat_api_key, trade_id=str(trade_id), trade_token=trade_token) + + if accept_result: + print(f"Accepted trade {trade_id}...") + trades_list_sell_to_accept_processing=list(filter(lambda c: c["id"] != trade_id, trades_list_sell_to_accept_processing)) + # print(f"{trades_list_sell_to_accept_processing}")#debug - if isinstance(trades_list, list): - for trade in trades_list: + else: + print(f"Failed to accept trade {trade_id}") + # print("asasfsf.") + await asyncio.sleep(0.23) + # await asyncio.sleep(230) + print("sdgsdgsgd.") + if not trades_list_sell_to_accept_processing: + print("All accetable trade accepted.") + break + else: + trades_list_sell_to_accept=trades_list_sell_to_accept_processing + trades_accept_loop_count+=1 + print("asfsdggs.") + else: + print(f"Unexpected trades list format: {type(trades_list_sell)}") + + + # print("assgdfdf.") + # await asyncio.sleep(50000) + # print("asfgdfd.") + trades_list_sell_accepted=list(filter(lambda c: c.get('accepted_at'), await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id))) + if trades_list_sell_accepted: + for i in range(len(trades_list_sell_accepted)): + if i not in index_excluded: + asset_id_list_temp=[] + for ii in range(len(trades_list_sell_accepted)): + if trades_list_sell_accepted[ii]['buyer_id']==trades_list_sell_accepted[i]['buyer_id'] and trades_list_sell_accepted[ii]["contract"]["item"]["market_hash_name"]==trades_list_sell_accepted[i]["contract"]["item"]["market_hash_name"]: + asset_id_list_temp.append(int(trades_list_sell_accepted[ii]["contract"]["item"]["asset_id"])) + index_excluded.append(ii) + offer_maker.append({"trade_id":int(trades_list_sell_accepted[i]["id"]),"buyer_id":int(trades_list_sell_accepted[i]["buyer_id"]),"seller_id":int(trades_list_sell_accepted[i]["seller_id"]),"asset_id":asset_id_list_temp,"trade_token":trades_list_sell_accepted[i]["trade_token"],"trade_url":trades_list_sell_accepted[i]["trade_url"],"accepted_at":trades_list_sell_accepted[i].get('accepted_at'),"trade_state":trades_list_sell_accepted[i]["state"]}) + print(index_excluded) + print(offer_maker) + else: + return None + retryCount=0 + while True: + try: + sentto, _, next_cursorvar = await client.get_trade_offers(active_only=False,received=False) + except aiohttp.ClientResponseError as http_err: + print(f"HTTP error occurred while fetching Steam trade offers sent: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while fetching Steam trade offers sent: {connect_err}") + except Exception as err: + print(f"Other error occurred while fetching Steam trade offers sent: {err}") + else: + break + retryCount+=1 + if retryCount >5: + print("Failed too many times.") + return None + await asyncio.sleep(50) + for omi in range(len(offer_maker)): + # for omi in offer_maker: + asset_id_sent=[] + for toi in range(len(sentto)): + if sentto[toi].partner_id >76561197960265728: + sentto[toi].partner_id-=76561197960265728 + if offer_maker[omi]["buyer_id"] >76561197960265728: + offer_maker[omi]["buyer_id"]-=76561197960265728 + if sentto[toi].status in (TradeOfferStatus.ACCEPTED,TradeOfferStatus.ACTIVE,TradeOfferStatus.CONFIRMATION_NEED) and sentto[toi].partner_id==offer_maker[omi]["buyer_id"]: + for itg in sentto[toi].items_to_give: + asset_id_sent.append(itg.asset_id) + if sentto[toi].status == TradeOfferStatus.CONFIRMATION_NEED: + asset_id_sent_check=asset_id_sent + # asset_id_sent_check.append(1522523)#debug + for itgom in offer_maker[omi]["asset_id"]: + asset_id_sent_check=list(filter(lambda c: c!=itgom,asset_id_sent_check)) + if not asset_id_sent_check: + print("Trade offer to confirm matched.") + await confirm_trade_offer_retry(client,sentto[toi].trade_offer_id) + else: + print("Trade offer to confirm not matched.") + + print(asset_id_sent) + if asset_id_sent: + for i in asset_id_sent: + offer_maker[omi]["asset_id"]=list(filter(lambda c: c!=i,offer_maker[omi]["asset_id"])) + # if not offer_maker[omi]["asset_id"]: + print(offer_maker[omi]["asset_id"]) + print(offer_maker) + # for item in trades_list_sell_accepted: + # extItem={"buyer_id":item['buyer_id'],"market_hash_name":item["contract"]["item"]["market_hash_name"],} + # buyer_id_n_market_hash_name.append(extItem) + # buyer_id_n_market_hash_name=[dict(t) for t in {tuple(d.items()) for d in buyer_id_n_market_hash_name}] + # # buyer_id_n_market_hash_name=list(OrderedDict.fromkeys(buyer_id_n_market_hash_name)) + # # buyer_id_n_market_hash_name=list(dict.fromkeys(buyer_id_n_market_hash_name)) + # print(buyer_id_n_market_hash_name) + # for item in buyer_id_n_market_hash_name: + # findItem=next((filter(lambda c: c['buyer_id'] ==item['buyer_id'] and c["contract"]["item"]["market_hash_name"]==item["market_hash_name"], trades_list_sell_accepted))) + # item.update({"trade_id": findItem["id"], "seller_id": findItem["seller_id"], "asset_id": findItem["contract"]["item"]["asset_id"], "trade_token": findItem["trade_token"], "trade_url": findItem["trade_url"], "accepted_at": findItem["accepted_at"], "trade_state": findItem["trade_state"]}) #wip multiple asset_id + # offer_maker.append(item) + # print(offer_maker) + # return #debug wip complete retry if confirm failed + """ + if next(filter(lambda c: c.status==TradeOfferStatus.CONFIRMATION_NEED ,sentto)): + retryCount=0 + while True: + if retryCount>4: + print("Failed too many times.") + sys.exit() + try: + confirmations=await client.get_confirmations(update_listings=False) # wip attr + trades_to_confirm=await client.get_confirmations(update_listings=False) + # print(fr"aaa11a.") + if trades_to_confirm: + # print(fr"aaa111.") + trades_to_confirm_correct = list(filter(lambda c: c.type == ConfirmationType.TRADE, trades_to_confirm)) # c.headline: 'Selling for ¥ 1.11'. c.summary: EconItem.description.market_hash_name + if trades_to_confirm_correct: + # print(fr"aaa112.") + await client.allow_multiple_confirmations(trades_to_confirm_correct) + else: + print("No matched confirmation found.") + break + else: + print("No matched confirmation found.") + break + except Exception as e: + print(fr"{type(e)} {e}") + # writeToFile(os.path.join(LOGS_FOLDER, "1.log"),fr"{type(e)} {e}","a") + await asyncio.sleep(5) + else: + break + retryCount+=1 + + """ + if isinstance(offer_maker, list): + for trade in offer_maker: if isinstance(trade, dict): - trade_id = trade.get('id') + trade_id = trade.get('trade_id') + """ # Проверка, был ли уже обработан этот trade_id if str(trade_id) in processed_trades: print(f"Trade {trade_id} has already been processed. Skipping.") continue # Пропустить уже обработанные трейды + """ - seller_id = trade.get('seller_id') # ID отправителя - buyer_id = trade.get('buyer_id') # ID получателя - asset_id = trade.get('contract', {}).get('item', {}).get('asset_id') + seller_id = int(trade.get('seller_id')) # ID отправителя + buyer_id = int(trade.get('buyer_id')) # ID получателя + asset_id = trade.get('asset_id') trade_token = trade.get('trade_token') # Получаем trade_token trade_url = trade.get('trade_url') # Получаем trade_url accepted_at = trade.get('accepted_at') # Получаем время принятия, если есть - trade_state = trade.get('state') # Получаем состояние трейда - + trade_state = trade.get('trade_state') # Получаем состояние трейда + # print(trade)#debug + # continue#debug wip fix the bug that can't accept multiple trades. + + # print(f"seller_id {type(seller_id)} my_steam_id {type(my_steam_id)}") + if seller_id !=my_steam_id: + print(f"Trade {trade_id} is not a sold trade, skipping.") + continue + """ if trade_state == "verified": - # Если трейд уже подтвержден, добавляем его в обработанные и пропускаем + # If the trade is already verified, add it to processed and skip it processed_trades.add(str(trade_id)) continue + """ if trade_id and seller_id and buyer_id and asset_id: + print(f"Trade {trade_id} is a sold trade, proceeding.") + # print(f"Trade {trade_id} is a sold trade.") + # continue#debug wip retry if confirm failed + if accepted_at: - # Предложение уже принято, отправляем торговое предложение - print(f"Trade {trade_id} уже принято. Переходим к отправке торгового предложения.") - offer_id = await send_steam_trade( + # The offer has already been accepted. Sending a trade offer + print(f"Trade {trade_id} has already been accepted. Proceed to sending a trade offer.") + offer_id = await csfloat_send_steam_trade( #wip if items disappered client, - trade_id=str(trade_id), # Передаём trade_id как строку + trade_id=int(trade_id), # Передаём trade_id как строку buyer_steam_id=int(buyer_id), # Передаём buyer_id как целое число - asset_id=int(asset_id), + asset_id=asset_id, trade_token=trade_token, trade_url=trade_url ) + # return#debug if offer_id: # Автоматически подтверждаем трейды - await confirm_trade(client) + # await confirm_trade(client) + await confirm_trade_offer_retry(client,offer_id) else: print(f"Failed to send trade for {trade_id}") - else: - # Предложение ещё не принято, принимаем его - print(f"Accepting trade {trade_id}...") - accept_result = await accept_trade(session, csfloat_api_key, trade_id=str(trade_id), trade_token=trade_token) - - if accept_result: - print(f"Sending item to buyer for trade {trade_id}...") - offer_id = await send_steam_trade( - client, - trade_id=str(trade_id), # Передаём trade_id как строку - buyer_steam_id=int(buyer_id), # Передаём buyer_id как целое число - asset_id=int(asset_id), - trade_token=trade_token, - trade_url=trade_url - ) - - if offer_id: - # Автоматически подтверждаем трейды - await confirm_trade(client) - else: - print(f"Failed to send trade for {trade_id}") - else: - print(f"Failed to accept trade {trade_id}") # Добавляем trade_id в processed_trades независимо от результата - processed_trades.add(str(trade_id)) + # processed_trades.add(str(trade_id)) else: - print(f"Unexpected trades list format: {type(trades_list)}") + print(f"Unexpected trade maker list format: {type(offer_maker)}") else: - print(f"Unexpected trades data format: {type(trades_info)}") + print("No actionable sold trades at the moment.") else: - print(f"No actionable trades at the moment. Waiting for {check_interval_minutes} minutes before next check.") + print(f"No actionable trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") def any2bool(v): return str(v).lower() in ("yes", "true", "t", "1") def readConfigValue(configJson,jsonKey): try: jsonValue= configJson[jsonKey] except Exception as err: - print(f"Couldn't load value from config file: {jsonKey}") + print(f"Couldn't load the item from the config file: {jsonKey}") else: return jsonValue async def main(): config = load_steam_config() # Загрузка конфигурации csfloat_api_key = config['csfloat_api_key'] - steam_api_key = config['steam_api_key'] + steam_api_key = config.get('steam_api_key') steam_id = int(config['steam_id64']) # Убедитесь, что это целое число steam_login = config['steam_login'] steam_password = config['steam_password'] @@ -302,11 +600,13 @@ async def main(): if cilent_proxy: print(f"proxy true: {cilent_proxy}") # Определение продолжительности ожидания (в минутах) - CHECK_INTERVAL_MINUTES = 5 # Вы можете легко изменить это значение - - # Инициализация SteamClient с необходимыми аргументами - class MySteamClient(SteamClient, SteamWebApiMixin, SteamGuardMixin): - pass + check_interval_seconds_random = any2bool(config.get('check_interval_seconds_random')) + if check_interval_seconds_random: + check_interval_seconds_random_min=config.get('check_interval_seconds_random_min') + check_interval_seconds_random_max=config.get('check_interval_seconds_random_max') + check_interval_seconds=config.get('check_interval_seconds') + if not check_interval_seconds: + check_interval_seconds = 700 # Вы можете легко изменить это значение # print(steam_use_proxy) client = MySteamClient( steam_id=steam_id, # Steam ID64 как целое число @@ -317,25 +617,26 @@ class MySteamClient(SteamClient, SteamWebApiMixin, SteamGuardMixin): api_key=steam_api_key, # Передача API ключа user_agent=USER_AGENT, ) - if cilent_proxy and steam_use_proxy==True: + if cilent_proxy and steam_use_proxy: MySteamClient.proxy=cilent_proxy print("steam proxy true") # print(client.proxy) else: - print(f"steam proxy false") + print("steam proxy false") # sys.exit() # Восстановление cookies, если они существуют + if COOKIE_FILE.is_file(): try: with COOKIE_FILE.open("r") as f: cookies = json.load(f) - await restore_from_cookies(cookies, client) + await restore_from_cookies_retry(cookies, client) except Exception as err: print(f"{err}") - await client.login() + await steam_client_login_retry(client) #wip fix 502 errors else: - await client.login() + await steam_client_login_retry(client) # Загрузка обработанных трейдов processed_trades = load_processed_trades() @@ -348,6 +649,9 @@ class MySteamClient(SteamClient, SteamWebApiMixin, SteamGuardMixin): async with aiohttp.ClientSession(connector=sessionConnector) as session: try: while True: + if check_interval_seconds_random: + check_interval_seconds=round(random.uniform(check_interval_seconds_random_min, check_interval_seconds_random_max),4) + print(f"check_interval_seconds: {check_interval_seconds}") await check_actionable_trades( session, csfloat_api_key, @@ -355,10 +659,11 @@ class MySteamClient(SteamClient, SteamWebApiMixin, SteamGuardMixin): shared_secret, identity_secret, processed_trades, # Передача набора обработанных трейдов - CHECK_INTERVAL_MINUTES # Передача продолжительности ожидания + check_interval_seconds, # Передача продолжительности ожидания + my_steam_id=steam_id ) save_processed_trades(processed_trades) # Сохранение после каждой проверки - await asyncio.sleep(CHECK_INTERVAL_MINUTES * 60) # Ожидание заданное количество минут + await asyncio.sleep(check_interval_seconds) # Ожидание заданное количество минут finally: # Сохранение cookies with COOKIE_FILE.open("w") as f: From 2e267ce05133911e5bf445fdbcb666d7cbd3b611 Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Fri, 20 Jun 2025 03:18:27 +0800 Subject: [PATCH 06/10] Add files via upload --- CSFloat-Auto-Trade.py | 269 +++++++++++++++++++++--------------------- README.md | 4 +- README_ru.md | 8 +- 3 files changed, 143 insertions(+), 138 deletions(-) diff --git a/CSFloat-Auto-Trade.py b/CSFloat-Auto-Trade.py index 0adddc1..abe4b9e 100644 --- a/CSFloat-Auto-Trade.py +++ b/CSFloat-Auto-Trade.py @@ -2,6 +2,7 @@ import json import aiohttp import os,random +# from decimal import * from pathlib import Path from aiohttp_socks.connector import ProxyConnector from aiosteampy import SteamClient, AppContext @@ -35,12 +36,8 @@ # Path to a file to save cookies, will be created at end of a script run if do not exist SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) COOKIE_FILE = Path(rf"{SCRIPT_DIR}/cookies.json") -# print(str(COOKIE_FILE)) -# print(COOKIE_FILE) -if COOKIE_FILE.is_file(): - print("cookie file true") -# time.sleep(10) -# sys.exit() +# if COOKIE_FILE.is_file(): + USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" # Path to store processed trade IDs @@ -59,6 +56,7 @@ async def restore_from_cookies_retry(cookies: JSONABLE_COOKIE_JAR, steam_client: while True: try: await restore_from_cookies(cookies, steam_client) + print("Restored Steam session from the cookie file.") print(f"Loaded Steam account: {steam_client.username}") return except aiohttp.ClientResponseError as http_err: @@ -71,7 +69,7 @@ async def restore_from_cookies_retry(cookies: JSONABLE_COOKIE_JAR, steam_client: if try_count >5: print("Failed too many times.") return None - await asyncio.sleep(50) + await asyncio.sleep(5) async def steam_client_login_retry(steam_client: "SteamClientBase"): try_count=0 @@ -90,7 +88,7 @@ async def steam_client_login_retry(steam_client: "SteamClientBase"): if try_count >5: print("Failed too many times.") return None - await asyncio.sleep(50) + await asyncio.sleep(5) async def confirm_trade_offer_retry(steam_client: "SteamClientBase", obj: int | TradeOffer): try_count=0 @@ -109,7 +107,7 @@ async def confirm_trade_offer_retry(steam_client: "SteamClientBase", obj: int | if try_count >5: print("Failed too many times.") return None - await asyncio.sleep(50) + await asyncio.sleep(5) def load_processed_trades(): if PROCESSED_TRADES_FILE.is_file(): @@ -158,7 +156,7 @@ async def get_trades(session, csfloat_api_key): try_count+=1 if try_count >5: return None - await asyncio.sleep(50) + await asyncio.sleep(5) async def accept_trade(session, csfloat_api_key, trade_id, trade_token): url = API_ACCEPT_TRADE.format(trade_id=trade_id) @@ -188,111 +186,117 @@ async def accept_trade(session, csfloat_api_key, trade_id, trade_token): return False async def csfloat_send_steam_trade(client: SteamClient, trade_id, buyer_steam_id=None, trade_url=None, asset_id=None, trade_token=None): - try: - - # Определение контекста игры, например, CS2 - game_context = AppContext.CS2 # Убедитесь, что это правильный контекст для вашего предмета - - # Получение вашего инвентаря - my_inv, _, _ = await client.get_inventory(game_context,count=2000) - - # Проверка структуры предметов в инвентаре - if not my_inv: - print("Your inventory is empty or could not be loaded.") - return False - - #wip compare to history offers - - # Попытка найти предмет по asset_id - asset_id = list(asset_id) - if not asset_id: #if all items to trade on csfloat are already included in created trade offers. - print("Nothing to give for trade offer.") - return False - asset_id_len=len(asset_id) - # print(f"asset_id {asset_id}") - print(f"asset_id_len {asset_id_len}") - items_to_give=[] + # Определение контекста игры, например, CS2 + game_context = AppContext.CS2 # Убедитесь, что это правильный контекст для вашего предмета + + # Попытка найти предмет по asset_id + asset_id = list(asset_id) + if not asset_id: #if all items to trade on csfloat are already included in created trade offers. + print("Nothing to give for trade offer.") + return False + + retryCount=0 + while True: try: - for tai in asset_id: - items_to_give.append(next((item for item in my_inv if item.asset_id == tai))) - # items_to_give = list((item for item in my_inv if item.asset_id == asset_id)) - items_to_give_len=len(items_to_give) - # print(f"items_to_give {items_to_give}") - print(f"items_to_give_len {items_to_give_len}") - - if asset_id_len!=items_to_give_len: - print("Can't find all items to give.") - return False + # Получение вашего инвентаря + my_inv, _, _ = await client.get_inventory(game_context,count=2000) - except ValueError: - # items_to_give = next((item for item in my_inv if item.asset_id == asset_id), None) - pass + # Проверка структуры предметов в инвентаре + if not my_inv: + print("Your inventory is empty or could not be loaded.") + return False + + #wip compare to history offers - if not items_to_give: #wip find missing items - if asset_id_len==1: - print(f"Item with asset_id {asset_id} not found in the inventory.") + asset_id_len=len(asset_id) + # print(f"asset_id {asset_id}") + print(f"asset_id_len {asset_id_len}") + items_to_give=[] + try: + for tai in asset_id: + items_to_give.append(next((item for item in my_inv if item.asset_id == tai))) + # items_to_give = list((item for item in my_inv if item.asset_id == asset_id)) + items_to_give_len=len(items_to_give) + # print(f"items_to_give {items_to_give}") + print(f"items_to_give_len {items_to_give_len}") + + if asset_id_len!=items_to_give_len: + print("Can't find all items to give.") + return False + + except ValueError: + # items_to_give = next((item for item in my_inv if item.asset_id == asset_id), None) + pass + + if not items_to_give: #wip find missing items + if asset_id_len==1: + print(f"Item with asset_id {asset_id} not found in the inventory.") + else: + print(f"Item with asset_id {asset_id[0]} and {asset_id_len-1} other items not found in the inventory.") + # print(f"Предмет с asset_id {asset_id} не найден в инвентаре.") + return False + if items_to_give_len>1: + trades_num_other=items_to_give_len-1 + offer_message=f"CSFloat Market Trade Offer #{trade_id} and {trades_num_other} other items Thanks for using CSFloat!" else: - print(f"Item with asset_id {asset_id[0]} and {asset_id_len-1} other items not found in the inventory.") - # print(f"Предмет с asset_id {asset_id} не найден в инвентаре.") - return False - if items_to_give_len>1: - trades_num_other=items_to_give_len-1 - offer_message=f"CSFloat Market Trade Offer #{trade_id} and {trades_num_other} other items Thanks for using CSFloat!" - else: - offer_message=f"CSFloat Market Trade Offer #{trade_id}. Thanks for using CSFloat!" - print(f"trade_id {trade_id} buyer_steam_id {buyer_steam_id} trade_url {trade_url} asset_id {asset_id} trade_token {trade_token} offer_message {offer_message}") - # return #debug - # Вызов make_trade_offer с использованием Steam ID или Trade URL - if trade_url: - # Отправка через трейд-ссылку - offer_id = await client.make_trade_offer( - trade_url, # Трейд-ссылка как первый позиционный аргумент - to_give=items_to_give, - to_receive=[], - message=offer_message, - confirm=False #debug - ) - elif buyer_steam_id: - # Отправка через Steam ID партнёра - if trade_token: + offer_message=f"CSFloat Market Trade Offer #{trade_id}. Thanks for using CSFloat!" + print(f"trade_id {trade_id} buyer_steam_id {buyer_steam_id} trade_url {trade_url} asset_id {asset_id} trade_token {trade_token} offer_message {offer_message}") + # return #debug + # Вызов make_trade_offer с использованием Steam ID или Trade URL + if trade_url: + # Отправка через трейд-ссылку offer_id = await client.make_trade_offer( - buyer_steam_id, # Steam ID партнёра как первый позиционный аргумент + trade_url, # Трейд-ссылка как первый позиционный аргумент to_give=items_to_give, to_receive=[], message=offer_message, - token=trade_token, # Передача trade_token, если требуется confirm=False #debug ) + elif buyer_steam_id: + # Отправка через Steam ID партнёра + if trade_token: + offer_id = await client.make_trade_offer( + buyer_steam_id, # Steam ID партнёра как первый позиционный аргумент + to_give=items_to_give, + to_receive=[], + message=offer_message, + token=trade_token, # Передача trade_token, если требуется + confirm=False #debug + ) + else: + offer_id = await client.make_trade_offer( + buyer_steam_id, # Steam ID партнёра как первый позиционный аргумент + to_give=items_to_give, + to_receive=[], + message=offer_message, + confirm=False #debug + ) else: - offer_id = await client.make_trade_offer( - buyer_steam_id, # Steam ID партнёра как первый позиционный аргумент - to_give=items_to_give, - to_receive=[], - message=offer_message, - confirm=False #debug - ) - else: - print("Необходимо указать либо buyer_steam_id, либо trade_url.") - return False + print("It is necessary to specify either buyer_steam_id or trade_url.") + return False - if offer_id: - print(f"Торговое предложение {trade_id} отправлено!") - return offer_id # Возвращаем offer_id для дальнейшей обработки - else: - print("Не удалось отправить торговое предложение.") - return False + if offer_id: + print(f"Trade offer {trade_id} sent!") + return offer_id # Возвращаем offer_id для дальнейшей обработки + else: + print("It was not possible to send a trade offer.") + return False - except aiohttp.ClientResponseError as http_err: - print(f"HTTP error occurred while sending trade offer: {http_err}") - except ConnectionError as connect_err: - print(f"connection error occurred while sending trade offer: {connect_err}") - except Exception as e: - print(f"An error occurred while sending trade offer: {e}") - return False + except aiohttp.ClientResponseError as http_err: + print(f"HTTP error occurred while sending trade offer: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while sending trade offer: {connect_err}") + except Exception as e: + print(f"An error occurred while sending trade offer: {e}") + retryCount+=1 + if retryCount >5: + print("Failed too many times.") + return None + await asyncio.sleep(5) # Функция подтверждения трейдов, если требуется async def confirm_trade(client: SteamGuardMixin): - return#debug + # breakpoint()#debug try: confirmations = await client.get_confirmations() @@ -333,9 +337,9 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien # sys.exit()#debug trades_list_sell=await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id) if trades_list_sell: - # return#debug + # breakpoint()#debug # print(trades_list_sell)#debug - buyer_id_n_market_hash_name=[] + # buyer_id_n_market_hash_name=[] index_excluded=[] offer_maker=[] trades_list_sell_to_accept=list(filter(lambda c: not c.get('accepted_at'), trades_list_sell)) @@ -344,7 +348,6 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien trades_list_sell_to_accept_processing=trades_list_sell_to_accept trades_accept_loop_count=0 while True: - # print("asfdsgsd.") if trades_accept_loop_count>8: print(f"trades_accept looped more than {trades_accept_loop_count} times. Stop for this check.") return @@ -357,9 +360,7 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien break if isinstance(trades_list_sell_to_accept, list): - # print("afsfsdsdf.") for trade in trades_list_sell_to_accept: - # print("asfsdggs.") if isinstance(trade, dict): trade_id = trade.get('id') seller_id = int(trade.get('seller_id')) # ID отправителя @@ -368,10 +369,8 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien trade_token = trade.get('trade_token') # Получаем trade_token trade_url = trade.get('trade_url') # Получаем trade_url trade_state = trade.get('state') # Получаем состояние трейда - # print("sgdgdfasd.") if trade_id and seller_id and buyer_id and asset_id: print(f"Trade {trade_id} is a sold trade.") - # print(f"Trade {trade_id} is a sold trade.") # continue#debug print(f"Accepting trade {trade_id}...") @@ -384,24 +383,19 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien else: print(f"Failed to accept trade {trade_id}") - # print("asasfsf.") - await asyncio.sleep(0.23) - # await asyncio.sleep(230) - print("sdgsdgsgd.") + await asyncio.sleep(0.23) #0.23 if not trades_list_sell_to_accept_processing: print("All accetable trade accepted.") break else: trades_list_sell_to_accept=trades_list_sell_to_accept_processing trades_accept_loop_count+=1 - print("asfsdggs.") + print(f"Can't accept all trades. Retrying: {trades_accept_loop_count}.") else: print(f"Unexpected trades list format: {type(trades_list_sell)}") - + + await asyncio.sleep(25) - # print("assgdfdf.") - # await asyncio.sleep(50000) - # print("asfgdfd.") trades_list_sell_accepted=list(filter(lambda c: c.get('accepted_at'), await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id))) if trades_list_sell_accepted: for i in range(len(trades_list_sell_accepted)): @@ -412,27 +406,26 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien asset_id_list_temp.append(int(trades_list_sell_accepted[ii]["contract"]["item"]["asset_id"])) index_excluded.append(ii) offer_maker.append({"trade_id":int(trades_list_sell_accepted[i]["id"]),"buyer_id":int(trades_list_sell_accepted[i]["buyer_id"]),"seller_id":int(trades_list_sell_accepted[i]["seller_id"]),"asset_id":asset_id_list_temp,"trade_token":trades_list_sell_accepted[i]["trade_token"],"trade_url":trades_list_sell_accepted[i]["trade_url"],"accepted_at":trades_list_sell_accepted[i].get('accepted_at'),"trade_state":trades_list_sell_accepted[i]["state"]}) - print(index_excluded) - print(offer_maker) + # print(index_excluded) + # print(offer_maker) else: return None retryCount=0 while True: try: sentto, _, next_cursorvar = await client.get_trade_offers(active_only=False,received=False) + break except aiohttp.ClientResponseError as http_err: print(f"HTTP error occurred while fetching Steam trade offers sent: {http_err}") except ConnectionError as connect_err: print(f"connection error occurred while fetching Steam trade offers sent: {connect_err}") except Exception as err: print(f"Other error occurred while fetching Steam trade offers sent: {err}") - else: - break retryCount+=1 if retryCount >5: print("Failed too many times.") return None - await asyncio.sleep(50) + await asyncio.sleep(5) for omi in range(len(offer_maker)): # for omi in offer_maker: asset_id_sent=[] @@ -459,8 +452,8 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien if asset_id_sent: for i in asset_id_sent: offer_maker[omi]["asset_id"]=list(filter(lambda c: c!=i,offer_maker[omi]["asset_id"])) - # if not offer_maker[omi]["asset_id"]: - print(offer_maker[omi]["asset_id"]) + # if not offer_maker[omi]["asset_id"]: # Empty asset_id detection already implemented in function "csfloat_send_steam_trade" + # print(offer_maker[omi]["asset_id"])#debug print(offer_maker) # for item in trades_list_sell_accepted: # extItem={"buyer_id":item['buyer_id'],"market_hash_name":item["contract"]["item"]["market_hash_name"],} @@ -573,7 +566,8 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien else: print(f"Unexpected trade maker list format: {type(offer_maker)}") else: - print("No actionable sold trades at the moment.") + print(f"No actionable sold trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") + print(f"No actionable trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") else: print(f"No actionable trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") def any2bool(v): @@ -595,18 +589,23 @@ async def main(): steam_password = config['steam_password'] shared_secret = config['shared_secret'] identity_secret = config['identity_secret'] - cilent_proxy = readConfigValue(config,'cilent_proxy') + client_proxy = readConfigValue(config,'client_proxy') steam_use_proxy = any2bool(readConfigValue(config,'steam_use_proxy')) # Acceptable true value: "yes", "true", "t", "y", "1" - if cilent_proxy: - print(f"proxy true: {cilent_proxy}") + if client_proxy: + print(f"proxy true: {client_proxy}") # Определение продолжительности ожидания (в минутах) check_interval_seconds_random = any2bool(config.get('check_interval_seconds_random')) if check_interval_seconds_random: - check_interval_seconds_random_min=config.get('check_interval_seconds_random_min') + check_interval_seconds_random_min=config.get('check_interval_seconds_random_min') # converting to 'decimal.Decimal' causes the problem. check_interval_seconds_random_max=config.get('check_interval_seconds_random_max') + if check_interval_seconds_random_min>check_interval_seconds_random_max: + check_interval_seconds_random=False + print(f"Error: \"check_interval_seconds_random_min\" is greater than \"check_interval_seconds_random_max\". Restoring default check interval value.") + # check_interval_seconds=config.get('check_interval_seconds') + # check_interval_seconds=Decimal(config.get('check_interval_seconds')) check_interval_seconds=config.get('check_interval_seconds') if not check_interval_seconds: - check_interval_seconds = 700 # Вы можете легко изменить это значение + check_interval_seconds = 600 # Вы можете легко изменить это значение # print(steam_use_proxy) client = MySteamClient( steam_id=steam_id, # Steam ID64 как целое число @@ -617,13 +616,12 @@ async def main(): api_key=steam_api_key, # Передача API ключа user_agent=USER_AGENT, ) - if cilent_proxy and steam_use_proxy: - MySteamClient.proxy=cilent_proxy + if client_proxy and steam_use_proxy: + MySteamClient.proxy=client_proxy print("steam proxy true") # print(client.proxy) else: print("steam proxy false") - # sys.exit() # Восстановление cookies, если они существуют @@ -634,14 +632,14 @@ async def main(): await restore_from_cookies_retry(cookies, client) except Exception as err: print(f"{err}") - await steam_client_login_retry(client) #wip fix 502 errors + await steam_client_login_retry(client) else: await steam_client_login_retry(client) # Загрузка обработанных трейдов processed_trades = load_processed_trades() - sessionConnector = ProxyConnector.from_url(cilent_proxy, ttl_dns_cache=300) if cilent_proxy else aiohttp.TCPConnector( + sessionConnector = ProxyConnector.from_url(client_proxy, ttl_dns_cache=300) if client_proxy else aiohttp.TCPConnector( resolver=aiohttp.resolver.AsyncResolver(), limit_per_host=50 ) @@ -650,8 +648,11 @@ async def main(): try: while True: if check_interval_seconds_random: + # print(f"check_interval_seconds: {type(check_interval_seconds_random_min)}") + # print(f"check_interval_seconds: {type(check_interval_seconds_random_max)}") + # breakpoint() check_interval_seconds=round(random.uniform(check_interval_seconds_random_min, check_interval_seconds_random_max),4) - print(f"check_interval_seconds: {check_interval_seconds}") + # print(f"check_interval_seconds: {check_interval_seconds} {type(check_interval_seconds)}") await check_actionable_trades( session, csfloat_api_key, diff --git a/README.md b/README.md index d1d49f2..91d6f09 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Before running the script, you need to configure the configuration file `steam.j - `steam_login`: Your Steam username. - `steam_password`: Your Steam password. - `shared_secret` and `identity_secret`: Secrets needed to confirm trade offers. Can be obtained from maFile. - - `cilent_proxy`: Optional: Set the proxy(example: `http://127.0.0.1:20122`). + - `client_proxy`: Optional: Set the proxy(example: `http://127.0.0.1:7890`). - `steam_use_proxy`: Optional: Apply proxy for steam cilent if setted to "true". - `check_interval_seconds`: Optional: Set the interval in seconds bewteen checks. - `check_interval_seconds_random`: Optional: Enable randomizing the interval bewteen checks if setted to "true". @@ -58,5 +58,5 @@ Now you are ready to run the script. `python CSFloat-Auto-Trade.py` -2. **The script will start executing and will check for new trade offers every 5 minutes (by default).** +2. **The script will start executing and will check for new trade offers every 10 minutes (by default).** diff --git a/README_ru.md b/README_ru.md index 7fb9225..e47da67 100644 --- a/README_ru.md +++ b/README_ru.md @@ -39,8 +39,12 @@ - `steam_login`: Ваш логин от Steam. - `steam_password`: Ваш пароль от Steam. - `shared_secret` и `identity_secret`: Секреты, необходимые для подтверждения торговых предложений. Их можно получить из maFile. - - `cilent_proxy`: Необязательно: Установите прокси. + - `client_proxy`: Необязательно: Установите прокси (например, `http://127.0.0.1:7890`). - `steam_use_proxy`: Необязательно: Применить прокси для Steam cilent, если true. + - `check_interval_seconds`: Optional: Set the interval in seconds bewteen checks. + - `check_interval_seconds_random`: Optional: Enable randomizing the interval bewteen checks if setted to "true". + - `check_interval_seconds_random_min`: Optional: Set the minimum randomized interval in seconds bewteen checks. + - `check_interval_seconds_random_max`: Optional: Set the maximum randomized interval in seconds bewteen checks. **Важно:** Никогда не делитесь этими ключами и секретами. Храните их в безопасном месте. @@ -53,5 +57,5 @@ `python CSFloat-Auto-Trade.py` -2. **Скрипт начнёт выполнение и будет проверять наличие новых торговых предложений каждые 5 минут (по умолчанию).** +2. **Скрипт начнёт выполнение и будет проверять наличие новых торговых предложений каждые 10 минут (по умолчанию).** From e93d638c9ba922803bbfd1564a61c63190ebf0f3 Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Fri, 20 Jun 2025 04:57:38 +0800 Subject: [PATCH 07/10] Add files via upload --- CSFloat-Auto-Trade.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/CSFloat-Auto-Trade.py b/CSFloat-Auto-Trade.py index abe4b9e..4d037da 100644 --- a/CSFloat-Auto-Trade.py +++ b/CSFloat-Auto-Trade.py @@ -332,10 +332,11 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien # print(user_info)#debug if user_info and user_info.get('actionable_trades', 0) > 0: - print("Actionable trades found, fetching trade details...") + print("Unfinished trades found, fetching trade details...") # print(trades_info)#debug # sys.exit()#debug trades_list_sell=await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id) + # print(trades_list_sell)#debug if trades_list_sell: # breakpoint()#debug # print(trades_list_sell)#debug @@ -348,6 +349,7 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien trades_list_sell_to_accept_processing=trades_list_sell_to_accept trades_accept_loop_count=0 while True: + # breakpoint() if trades_accept_loop_count>8: print(f"trades_accept looped more than {trades_accept_loop_count} times. Stop for this check.") return @@ -370,7 +372,7 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien trade_url = trade.get('trade_url') # Получаем trade_url trade_state = trade.get('state') # Получаем состояние трейда if trade_id and seller_id and buyer_id and asset_id: - print(f"Trade {trade_id} is a sold trade.") + print(f"Trade {trade_id} is a sell trade.") # continue#debug print(f"Accepting trade {trade_id}...") @@ -395,8 +397,8 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien print(f"Unexpected trades list format: {type(trades_list_sell)}") await asyncio.sleep(25) - - trades_list_sell_accepted=list(filter(lambda c: c.get('accepted_at'), await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id))) + # breakpoint() + trades_list_sell_accepted=list(filter(lambda c: c.get('accepted_at') and not c.get('verify_sale_at'), await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id))) if trades_list_sell_accepted: for i in range(len(trades_list_sell_accepted)): if i not in index_excluded: @@ -409,7 +411,10 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien # print(index_excluded) # print(offer_maker) else: + # breakpoint() + print(f"No actionable sell trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") return None + # breakpoint() retryCount=0 while True: try: @@ -423,7 +428,7 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien print(f"Other error occurred while fetching Steam trade offers sent: {err}") retryCount+=1 if retryCount >5: - print("Failed too many times.") + print(f"Failed too many times. Waiting for {check_interval_seconds} seconds before next check.") return None await asyncio.sleep(5) for omi in range(len(offer_maker)): @@ -524,7 +529,7 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien # print(f"seller_id {type(seller_id)} my_steam_id {type(my_steam_id)}") if seller_id !=my_steam_id: - print(f"Trade {trade_id} is not a sold trade, skipping.") + print(f"Trade {trade_id} is not a sell trade, skipping.") continue """ @@ -536,8 +541,8 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien """ if trade_id and seller_id and buyer_id and asset_id: - print(f"Trade {trade_id} is a sold trade, proceeding.") - # print(f"Trade {trade_id} is a sold trade.") + print(f"Trade {trade_id} is a sell trade, proceeding.") + # print(f"Trade {trade_id} is a sell trade.") # continue#debug wip retry if confirm failed if accepted_at: @@ -566,10 +571,10 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien else: print(f"Unexpected trade maker list format: {type(offer_maker)}") else: - print(f"No actionable sold trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") - print(f"No actionable trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") + print(f"No actionable sell trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") + print(f"No actionable sell trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") else: - print(f"No actionable trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") + print(f"No actionable sell trades at the moment. Waiting for {check_interval_seconds} seconds before next check.") def any2bool(v): return str(v).lower() in ("yes", "true", "t", "1") def readConfigValue(configJson,jsonKey): @@ -598,10 +603,12 @@ async def main(): if check_interval_seconds_random: check_interval_seconds_random_min=config.get('check_interval_seconds_random_min') # converting to 'decimal.Decimal' causes the problem. check_interval_seconds_random_max=config.get('check_interval_seconds_random_max') - if check_interval_seconds_random_min>check_interval_seconds_random_max: + if not check_interval_seconds_random_min or not check_interval_seconds_random_max: + check_interval_seconds_random=False + print("Error: Value invalid of \"check_interval_seconds_random_min\" or \"check_interval_seconds_random_max\". Restoring default check interval value.") + elif check_interval_seconds_random_min>check_interval_seconds_random_max: check_interval_seconds_random=False - print(f"Error: \"check_interval_seconds_random_min\" is greater than \"check_interval_seconds_random_max\". Restoring default check interval value.") - # check_interval_seconds=config.get('check_interval_seconds') + print("Error: \"check_interval_seconds_random_min\" is greater than \"check_interval_seconds_random_max\". Restoring default check interval value.") # check_interval_seconds=Decimal(config.get('check_interval_seconds')) check_interval_seconds=config.get('check_interval_seconds') if not check_interval_seconds: @@ -653,6 +660,9 @@ async def main(): # breakpoint() check_interval_seconds=round(random.uniform(check_interval_seconds_random_min, check_interval_seconds_random_max),4) # print(f"check_interval_seconds: {check_interval_seconds} {type(check_interval_seconds)}") + if check_interval_seconds<300: + check_interval_seconds=300 + print("Minimum check interval is 300 seconds. Setting 'check_interval_seconds' to 300.") await check_actionable_trades( session, csfloat_api_key, From 1ddd0af8e3795f6a081010101d23cf4f9a1bbe76 Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Fri, 20 Jun 2025 05:17:29 +0800 Subject: [PATCH 08/10] Add files via upload --- CSFloat-Auto-Trade.py | 9 ++++++--- README.md | 1 + README_ru.md | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CSFloat-Auto-Trade.py b/CSFloat-Auto-Trade.py index 4d037da..45efe58 100644 --- a/CSFloat-Auto-Trade.py +++ b/CSFloat-Auto-Trade.py @@ -38,8 +38,6 @@ COOKIE_FILE = Path(rf"{SCRIPT_DIR}/cookies.json") # if COOKIE_FILE.is_file(): -USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" - # Path to store processed trade IDs PROCESSED_TRADES_FILE = Path(rf"{SCRIPT_DIR}/processed_trades.json") @@ -614,6 +612,11 @@ async def main(): if not check_interval_seconds: check_interval_seconds = 600 # Вы можете легко изменить это значение # print(steam_use_proxy) + user_agent=config.get('user_agent') + if not user_agent: + user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" + print(f"User agent: {user_agent}") + # breakpoint() client = MySteamClient( steam_id=steam_id, # Steam ID64 как целое число username=steam_login, @@ -621,7 +624,7 @@ async def main(): shared_secret=shared_secret, identity_secret=identity_secret, api_key=steam_api_key, # Передача API ключа - user_agent=USER_AGENT, + user_agent=user_agent, ) if client_proxy and steam_use_proxy: MySteamClient.proxy=client_proxy diff --git a/README.md b/README.md index 91d6f09..09ea2b4 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Before running the script, you need to configure the configuration file `steam.j - `steam_password`: Your Steam password. - `shared_secret` and `identity_secret`: Secrets needed to confirm trade offers. Can be obtained from maFile. - `client_proxy`: Optional: Set the proxy(example: `http://127.0.0.1:7890`). + - `user_agent`: Optional: Set the user agent. The default value is "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0". - `steam_use_proxy`: Optional: Apply proxy for steam cilent if setted to "true". - `check_interval_seconds`: Optional: Set the interval in seconds bewteen checks. - `check_interval_seconds_random`: Optional: Enable randomizing the interval bewteen checks if setted to "true". diff --git a/README_ru.md b/README_ru.md index e47da67..b753a14 100644 --- a/README_ru.md +++ b/README_ru.md @@ -40,6 +40,7 @@ - `steam_password`: Ваш пароль от Steam. - `shared_secret` и `identity_secret`: Секреты, необходимые для подтверждения торговых предложений. Их можно получить из maFile. - `client_proxy`: Необязательно: Установите прокси (например, `http://127.0.0.1:7890`). + - `user_agent`: Optional: Set the user agent. The default value is "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0". - `steam_use_proxy`: Необязательно: Применить прокси для Steam cilent, если true. - `check_interval_seconds`: Optional: Set the interval in seconds bewteen checks. - `check_interval_seconds_random`: Optional: Enable randomizing the interval bewteen checks if setted to "true". From 6f93be4814e37e31f4cadba6ee4716b52c993475 Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:57:55 +0800 Subject: [PATCH 09/10] Update CSFloat-Auto-Trade.py --- CSFloat-Auto-Trade.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CSFloat-Auto-Trade.py b/CSFloat-Auto-Trade.py index 45efe58..1bcc1c1 100644 --- a/CSFloat-Auto-Trade.py +++ b/CSFloat-Auto-Trade.py @@ -383,7 +383,7 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien else: print(f"Failed to accept trade {trade_id}") - await asyncio.sleep(0.23) #0.23 + await asyncio.sleep(0.19) #0.23 if not trades_list_sell_to_accept_processing: print("All accetable trade accepted.") break @@ -394,7 +394,7 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien else: print(f"Unexpected trades list format: {type(trades_list_sell)}") - await asyncio.sleep(25) + await asyncio.sleep(1) # breakpoint() trades_list_sell_accepted=list(filter(lambda c: c.get('accepted_at') and not c.get('verify_sale_at'), await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id))) if trades_list_sell_accepted: From 13b19e7dd82cc678ff07781f307ff06a0014b731 Mon Sep 17 00:00:00 2001 From: redlfox <53183547+redlfox@users.noreply.github.com> Date: Fri, 25 Jul 2025 20:03:51 +0800 Subject: [PATCH 10/10] Update CSFloat-Auto-Trade.py --- CSFloat-Auto-Trade.py | 159 +++++++++++++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 42 deletions(-) diff --git a/CSFloat-Auto-Trade.py b/CSFloat-Auto-Trade.py index 1bcc1c1..53f6936 100644 --- a/CSFloat-Auto-Trade.py +++ b/CSFloat-Auto-Trade.py @@ -30,8 +30,9 @@ # Constants for API endpoints API_USER_INFO = "https://csfloat.com/api/v1/me" -API_TRADES = "https://csfloat.com/api/v1/me/trades?state=queued,pending&limit=500" +API_TRADES = "https://csfloat.com/api/v1/me/trades?state=queued,pending&limit=3000" API_ACCEPT_TRADE = "https://csfloat.com/api/v1/trades/{trade_id}/accept" # Define the accept trade endpoint +API_ACCEPT_TRADES_BULK = "https://csfloat.com/api/v1/trades/bulk/accept" # Define the bulk accept trades endpoint # Path to a file to save cookies, will be created at end of a script run if do not exist SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -49,8 +50,31 @@ def load_steam_config(config_path=rf"{SCRIPT_DIR}/steam.json"): with open(config_path, 'r') as file: return json.load(file) +async def network_request_retry_template(methodToRun,actoinMessageErr,retryCountMax:int,retryWaitTime:float|int): + actoinMessageErr=str(actoinMessageErr) + retryCount=0 + while True: + try: + methodToRun() + return + except aiohttp.ClientResponseError as http_err: + print(f"HTTP error occurred while {actoinMessageErr}: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while {actoinMessageErr}: {connect_err}") + except Exception as err: + print(f"Other error occurred while {actoinMessageErr}: {err}") + retryCount+=1 + if retryCount >retryCountMax: + print("Failed too many times.") + return None + await asyncio.sleep(retryWaitTime) +async def restore_from_cookies_prompt(cookies: JSONABLE_COOKIE_JAR, steam_client: "SteamClientBase"): + await restore_from_cookies(cookies, steam_client) + print("Restored Steam session from the cookie file.") + print(f"Loaded Steam account: {steam_client.username}") + return async def restore_from_cookies_retry(cookies: JSONABLE_COOKIE_JAR, steam_client: "SteamClientBase"): - try_count=0 + retryCount=0 while True: try: await restore_from_cookies(cookies, steam_client) @@ -63,14 +87,14 @@ async def restore_from_cookies_retry(cookies: JSONABLE_COOKIE_JAR, steam_client: print(f"connection error occurred while restoring the Steam session from cookies: {connect_err}") except Exception as err: print(f"Other error occurred while restoring the Steam session from cookies: {err}") - try_count+=1 - if try_count >5: + retryCount+=1 + if retryCount >5: print("Failed too many times.") return None await asyncio.sleep(5) async def steam_client_login_retry(steam_client: "SteamClientBase"): - try_count=0 + retryCount=0 while True: try: await steam_client.login() @@ -82,14 +106,14 @@ async def steam_client_login_retry(steam_client: "SteamClientBase"): print(f"connection error occurred while logging in to Steam: {connect_err}") except Exception as err: print(f"Other error occurred while logging in to Steam: {err}") - try_count+=1 - if try_count >5: + retryCount+=1 + if retryCount >5: print("Failed too many times.") return None await asyncio.sleep(5) async def confirm_trade_offer_retry(steam_client: "SteamClientBase", obj: int | TradeOffer): - try_count=0 + retryCount=0 while True: try: print(f"Confirming trade offer {obj}.") @@ -101,8 +125,8 @@ async def confirm_trade_offer_retry(steam_client: "SteamClientBase", obj: int | print(f"connection error occurred while confirming the trade offer: {connect_err}") except Exception as err: print(f"Other error occurred while confirming the trade offer: {err}") - try_count+=1 - if try_count >5: + retryCount+=1 + if retryCount >5: print("Failed too many times.") return None await asyncio.sleep(5) @@ -137,7 +161,7 @@ async def get_user_info(session, csfloat_api_key): async def get_trades(session, csfloat_api_key): headers = {'Authorization': csfloat_api_key} - try_count=0 + retryCount=0 while True: try: async with session.get(API_TRADES, headers=headers) as response: @@ -151,8 +175,8 @@ async def get_trades(session, csfloat_api_key): print(f"connection error occurred while fetching trades: {connect_err}") except Exception as err: print(f"Other error occurred while fetching trades: {err}") - try_count+=1 - if try_count >5: + retryCount+=1 + if retryCount >5: return None await asyncio.sleep(5) @@ -174,15 +198,42 @@ async def accept_trade(session, csfloat_api_key, trade_id, trade_token): return False result = await response.json() - return True + return result except aiohttp.ClientResponseError as http_err: print(f"HTTP error occurred while accepting trade {trade_id}: {http_err}") except ConnectionError as connect_err: - print(f"connection error occurred while accepting trade: {connect_err}") + print(f"connection error occurred while accepting trade {trade_id}: {connect_err}") except Exception as err: print(f"Other error occurred while accepting trade {trade_id}: {err}") return False +async def accept_trades_bulk(session, csfloat_api_key, trade_ids: list[str]): + url = API_ACCEPT_TRADES_BULK + headers = { + 'Authorization': csfloat_api_key, + 'Content-Type': 'application/json' + } + payload = { + "trade_ids": trade_ids + } + try: + async with session.post(url, headers=headers, json=payload) as response: + if response.status != 200: + # Логирование подробностей ошибки + error_detail = await response.text() + print(f"Failed to accept trades. Status: {response.status}, Detail: {error_detail}") + return False + result = await response.json() + + return result + except aiohttp.ClientResponseError as http_err: + print(f"HTTP error occurred while accepting trades: {http_err}") + except ConnectionError as connect_err: + print(f"connection error occurred while accepting trades: {connect_err}") + except Exception as err: + print(f"Other error occurred while accepting trades: {err}") + return False + async def csfloat_send_steam_trade(client: SteamClient, trade_id, buyer_steam_id=None, trade_url=None, asset_id=None, trade_token=None): # Определение контекста игры, например, CS2 game_context = AppContext.CS2 # Убедитесь, что это правильный контекст для вашего предмета @@ -328,6 +379,7 @@ async def get_actionable_trades_sell(session, csfloat_api_key,my_steam_id): async def check_actionable_trades(session, csfloat_api_key, client: MySteamClient, shared_secret, identity_secret, processed_trades, check_interval_seconds,my_steam_id): user_info = await get_user_info(session, csfloat_api_key) # print(user_info)#debug + # await get_trades(session, csfloat_api_key)#debug if user_info and user_info.get('actionable_trades', 0) > 0: print("Unfinished trades found, fetching trade details...") @@ -360,30 +412,42 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien break if isinstance(trades_list_sell_to_accept, list): + trade_ids_to_accept=[] for trade in trades_list_sell_to_accept: if isinstance(trade, dict): trade_id = trade.get('id') - seller_id = int(trade.get('seller_id')) # ID отправителя - buyer_id = int(trade.get('buyer_id')) # ID получателя - asset_id = trade.get('contract', {}).get('item', {}).get('asset_id') - trade_token = trade.get('trade_token') # Получаем trade_token - trade_url = trade.get('trade_url') # Получаем trade_url - trade_state = trade.get('state') # Получаем состояние трейда - if trade_id and seller_id and buyer_id and asset_id: - print(f"Trade {trade_id} is a sell trade.") - # continue#debug - - print(f"Accepting trade {trade_id}...") - accept_result = await accept_trade(session, csfloat_api_key, trade_id=str(trade_id), trade_token=trade_token) - - if accept_result: - print(f"Accepted trade {trade_id}...") - trades_list_sell_to_accept_processing=list(filter(lambda c: c["id"] != trade_id, trades_list_sell_to_accept_processing)) - # print(f"{trades_list_sell_to_accept_processing}")#debug - - else: - print(f"Failed to accept trade {trade_id}") - await asyncio.sleep(0.19) #0.23 + trade_ids_to_accept.append(str(trade_id)) + # trade_id = trade.get('id') + # seller_id = int(trade.get('seller_id')) # ID отправителя + # buyer_id = int(trade.get('buyer_id')) # ID получателя + # asset_id = trade.get('contract', {}).get('item', {}).get('asset_id') + # trade_token = trade.get('trade_token') # Получаем trade_token + # trade_url = trade.get('trade_url') # Получаем trade_url + # trade_state = trade.get('state') # Получаем состояние трейда + # if trade_id and seller_id and buyer_id and asset_id: + # print(f"Trade {trade_id} is a sell trade.") + # # continue#debug + + # print(f"Accepting trade {trade_id}...") + # accept_result = await accept_trade(session, csfloat_api_key, trade_id=str(trade_id), trade_token=trade_token) + + # if accept_result: + # print(f"Accepted trade {trade_id}...") + # trades_list_sell_to_accept_processing=list(filter(lambda c: c["id"] != trade_id, trades_list_sell_to_accept_processing)) + # # print(f"{trades_list_sell_to_accept_processing}")#debug + + # else: + # print(f"Failed to accept trade {trade_id}") + # await asyncio.sleep(0.19) #0.23 + await asyncio.sleep(round(random.uniform(6, 11),4)) + accept_result = await accept_trades_bulk(session, csfloat_api_key, trade_ids=trade_ids_to_accept) + if accept_result: # wip cancel trades if can't send trade offers + print(f"Accepted trades.") + for ati in trade_ids_to_accept: + trades_list_sell_to_accept_processing=list(filter(lambda c: c["id"] != str(ati), trades_list_sell_to_accept_processing)) + # print(f"{trades_list_sell_to_accept_processing}")#debug + else: + print(f"Failed to accept trade {trade_id}") if not trades_list_sell_to_accept_processing: print("All accetable trade accepted.") break @@ -393,8 +457,8 @@ async def check_actionable_trades(session, csfloat_api_key, client: MySteamClien print(f"Can't accept all trades. Retrying: {trades_accept_loop_count}.") else: print(f"Unexpected trades list format: {type(trades_list_sell)}") - - await asyncio.sleep(1) + await asyncio.sleep(1) + await asyncio.sleep(round(random.uniform(6, 11),4)) # breakpoint() trades_list_sell_accepted=list(filter(lambda c: c.get('accepted_at') and not c.get('verify_sale_at'), await get_actionable_trades_sell(session, csfloat_api_key,my_steam_id))) if trades_list_sell_accepted: @@ -617,18 +681,30 @@ async def main(): user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0" print(f"User agent: {user_agent}") # breakpoint() - client = MySteamClient( + client = SteamClient( steam_id=steam_id, # Steam ID64 как целое число username=steam_login, password=steam_password, shared_secret=shared_secret, identity_secret=identity_secret, api_key=steam_api_key, # Передача API ключа - user_agent=user_agent, + user_agent=user_agent ) if client_proxy and steam_use_proxy: - MySteamClient.proxy=client_proxy + # client.api_key=steam_api_key + # client.proxy=client_proxy + client = SteamClient( + steam_id=steam_id, # Steam ID64 как целое число + username=steam_login, + password=steam_password, + shared_secret=shared_secret, + identity_secret=identity_secret, + api_key=steam_api_key, # Передача API ключа + user_agent=user_agent, + proxy=client_proxy + ) print("steam proxy true") + # print(client.user_agent) # print(client.proxy) else: print("steam proxy false") @@ -653,7 +729,6 @@ async def main(): resolver=aiohttp.resolver.AsyncResolver(), limit_per_host=50 ) - async with aiohttp.ClientSession(connector=sessionConnector) as session: try: while True: