Предисловие.
В этом уроке вы научитесь работать с библиотекой steampy, на которой можно создать steam бота.
Подготовка
Первым делом, получите steam_api ключ, он нам понадобится для получения информации о трейдах. Получить его можно на сайте steam: https://steamcommunity.com/dev/apikey

Далее, понадобятся shared_secret и identity_secret, дающие полный доступ к вашему аккаунту.
Получить его можно в SDA в папке maFiles, при условии что вы не шифровали этот файл. Или на телефоне под управлением android с рут правами, к которому привязан steam.
Создайте текстовый файл steam_guard.json, и поместите туда следующий текст.
{
"steamid": "YOUR_STEAM_ID_64",
"shared_secret": "YOUR_SHARED_SECRET",
"identity_secret": "YOUR_IDENTITY_SECRET"
}
Steamid берем тут. В поле сайта, введите ссылку на аккаунт.
И установите библиотеку steampy, введя данную комманду в консоли.
pip install steampy
Что делать если steampy не работает?
Никто не знает когда bukson (создатель steampy), решит обновить библиотеку. Поэтому качаем мой форк собранный из фиксов, которые я взял из вкладки Issues гитхаба steampy.
Если у вас бот прекрасно работает, то форк вам не нужен, если же нет — устанавливаем.
Как установить форк?
Если ранее steampy был установлен, то удаляем его:
pip uninstall steampy
И устанавливаем форк:
pip install "git+https://github.com/bolon667/steampy.git"
Подтверждаем обмен.
Напишем основу стим бота.
from steampy.client import SteamClient #импортируем библиотеку
steam_client = SteamClient('MY_API_KEY')
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'steam_guard.json') #авторизируемся в аккаунте
Данный код отвечает за авторизацию на аккаунте.
Далее, попросите друга или бота кинуть трейд, чтобы на аккаунте висел не принятый обмен.

И пройдите по данной ссылке.
https://api.steampowered.com/IEconService/GetTradeOffers/v1/?key=STEAM_API_KEY&get_received_offers=1
STEAM_API_KEY — замените на свой.
Данная ссылка, это api запрос, который выводит информацию о входящих трейдах в json формате, подробнее здесь.

Нас, во всем этом месиве, интересует только tradeofferid. Он понадобится для подтверждения обмена. Теперь, скопируйте следующие строки в свой скрипт.
trade_id = ваш_trade_id
steam_client.accept_trade_offer(trade_id)
trade_id — замените на собственный.
И запустите скрипт.

В итоге, обмен принят без нашего участия, что круто.
Кидаем обмен.
Кидать обмен можно только друзьям.
Создайте новый скрипт, и поместите туда следующий код:
from steampy.client import SteamClient, Asset
from steampy.utils import GameOptions, get_key_value_from_url, account_id_to_steam_id
def find_item_in_inventory(item_hash_name, items):
for item in items.values():
market_hash_name = item['market_hash_name']
if market_hash_name != item_hash_name:
continue
return {
'market_hash_name': market_hash_name,
'id': item['id']
}
def make_trade_1_item(give_item, get_item, trade_link):
game = GameOptions.TF2
my_items = steam_client.get_my_inventory(game)
my_item_give = find_item_in_inventory(give_item, my_items)
my_asset = [Asset(my_item_give['id'], game)]
partner_account_id = get_key_value_from_url(trade_link, 'partner', True)
partner_steam_id = account_id_to_steam_id(partner_account_id)
partner_items = steam_client.get_partner_inventory(partner_steam_id, game)
partner_item_give = find_item_in_inventory(get_item, partner_items)
partner_asset = [Asset(partner_item_give['id'], game)]
steam_client.make_offer_with_url(my_asset, partner_asset, trade_link)
steam_client = SteamClient('secret')
steam_client.login('secret', 'secret', "steam_guard.json")
trade_link = 'https://randomSteamTradeOfferLink1234_under_prog_ru'
make_trade_1_item('Refined Metal', 'Refined Metal', trade_link)
За отправку трейда отвечает функция make_trade_1_item, разберем её.
game = GameOptions.TF2
В качестве инвентаря выбрали инвентарь TF2
my_items = steam_client.get_my_inventory(game)
my_item_give = find_item_in_inventory(my_items, give_item)
Получаем информацию о предметах инвентаря. И отсеиваем ненужное, с помощью функции find_item_in_inventory. На выходе, получаем словарь такого формата:
{
'market_hash_name': напзвание_предмета,
'id': id_предмета
}
Далее, запаковываем предмет в Asset.
my_asset = [Asset(my_item_give['id'], game)]
Asset принимает 2 аргумента:
- id предмета
- код игры (для TF2, это 440)
Наши предметы готовы, осталось подготовить предметы партнера. Сперва, получим инвентарь партнера.
partner_account_id = get_key_value_from_url(trade_link, 'partner', True) #получаем id аккаунта из трейд ссылки
partner_steam_id = account_id_to_steam_id(partner_account_id) # id аккаунта преводим в steam_id
partner_items = steam_client.get_partner_inventory(partner_steam_id, game) #получаем инвентарь партнера
Отсеем все ненужное, и закинем в Asset.
partner_item_give = find_item_in_inventory(get_item, partner_items)
partner_asset = [Asset(partner_item_give['id'], game)]
Ассеты собраны, время посылать трейд.
steam_client.make_offer_with_url(my_asset, partner_asset, trade_link)

Пишем бота для торговой площадки Steam (SCM).
Чтобы получить цену предмета предмета с тп (торговой площадки).
from steampy.client import SteamClient
from steampy.models import GameOptions, Currency
itemName = "Winter 2021 Cosmetic Case"
resp = steam_client.market.fetch_price(itemName,game=GameOptions.TF2)
print(resp)
Необходимо воспользоваться методом fetch_price, который имеет следующий синтаксис
steam_client.market.fetch_price(имя_предмета, game=тип_игры)
Данный код не будет работать, если вы в объекте steam_client не залогинились.
Таким образом, код выше, ищет на тп цену Winter 2021 Cosmetic Case, и выводит её на экран (print).
Похожим образом, методом fetch_price_history, вы можете получить историю цен предмета.
steam_client.market.fetch_price_history(имя_предмета, game=тип_игры)
Покупаем предмет с торговой площадки Steam.
В данном примере мы установим заявку на покупку Winter 2021 Cosmetic Case, за 0.06 р.
Перепишите данный код:
from steampy.client import SteamClient
from steampy.models import GameOptions, Currency
itemName = "Winter 2021 Cosmetic Case"
response = steam_client.market.create_buy_order(itemName, "6", 1, GameOptions.TF2, Currency.RUB)
buy_order_id = response["buy_orderid"]
У метода create_buy_order, следующий синтаксис:
steam_client.market.create_buy_order(имя_предмета, цена_предмета*100, количество_заявок_на_покупку, тип_игры, тип_валюты)
- имя_предмета — имя предмета для покупки
- цена_предмета*100 — цена предмета помноженная на 100 (в примере цена = 6, валюта рубль, значит ордер создастся на цену 0.06 р)
- количество_заявок_на_покупку — количество предметов на покупку
Таким образом, вы можете автоматизировать покупку предметов на тп.
Продаем предмет на тп.
Перепишите данный код:
from steampy.models import GameOptions, Currency
from steampy.client import SteamClient, Asset
from steampy.utils import GameOptions, get_key_value_from_url, account_id_to_steam_id
def find_item_in_inventory(item_hash_name, items):
for item in items.values():
market_hash_name = item['market_hash_name']
if market_hash_name != item_hash_name:
continue
return {
'market_hash_name': market_hash_name,
'id': item['id']
}
steam_client = None
def initSteam():
global steam_client
print("Signing in steam account")
steam_client = SteamClient(ваш_апи_ключ_стим)
steam_client.login(ваш_логин_стим, ваш_пароль_стим, "steam_secret.json") #авторизируемся в аккаунте
itemName = "Winter 2021 Cosmetic Case"
my_items = steam_client.get_my_inventory(GameOptions.TF2) #Получаем свой инвентарь
my_item_sell = find_item_in_inventory(itemName, my_items) #Из него извлекаем нужный предмет на имени
sell_response = steam_client.market.create_sell_order(my_item_sell["id"], GameOptions.TF2, "4") #Выставляем на продажу за 4 копейки
print(sell_response)
initSteam()
За выставления лота на продажу отвечает метод steam_client.market.create_sell_order:
steam_client.market.create_sell_order(id_предмета, тип_игры, цена_продажи*100)
- id_предемета — id предмета в твоем инвентаре.
- тип_игры — переменная типа GameOptions
- цена_продажи*100 — цена, за которую продается предмет, без учета комиссии стим.
Чтобы получить id_предмета, сперва, я получил свой инвентарь (массив предметов), и, с помощью метода find_item_in_inventory, получил предмет с именем Winter 2021 Cosmetic Case
itemName = "Winter 2021 Cosmetic Case"
my_items = steam_client.get_my_inventory(GameOptions.TF2) #Получаем свой инвентарь
my_item_sell = find_item_in_inventory(itemName, my_items) #Из него извлекаем нужный предмет на имени
И передал id этого предмета в метод steam_client.market.create_sell_order
sell_response = steam_client.market.create_sell_order(my_item_sell["id"], GameOptions.TF2, "4") #Выставляем на продажу за 4 копейки
В итоге, Winter 2021 Cosmetic Case выставился на продажу за 0.06р (4 копейки + комиссия стима).

Сохранение сессии.
Каждый раз запуская бота, вы заново логинитесь в стиме. И все бы ничего, только вот, у стима есть ограничение на количество авторизаций. Решить проблему, можно с помощью сохранения сессии, и последующей её загрузки.
steam_client.login(api_keys.steam_login, api_keys.steam_password, "steam_secret.json")
Используя метод steam_client.login мы получаем сессию (набор куки, заголовков). По ключам которые находятся в куки, сайт стима понимает что мы авторизованны. Следовательно, сохранив сессию в файл, а позже загрузив, мы можем получить доступ к аккаунту, минуя авторизацию.
Для сохранения, будем использовать библиотеку pickle, позволяющую сохранять объекты языка Python, в файл. В своем примере, я сохранил весь обьект steam_client в файл.
import os
from steampy.models import GameOptions, Currency
from steampy.client import SteamClient, Asset
from steampy.utils import GameOptions, get_key_value_from_url, account_id_to_steam_id
import pickle
steam_client = None
def initSteam():
global steam_client
if(os.path.isfile("steamClient.pkl")):
print("Using previous session")
with open('steamClient.pkl', 'rb') as f:
steam_client = pickle.load(f)
else:
print("You not authorized, trying to login into Steam")
print("Signing in steam account")
steam_client = SteamClient(api_keys.steam_api_key)
steam_client.login(ваш_стим_логин, ваш_стим_пароль, "steam_secret.json") #авторизируемся в аккаунте
print("Saving session")
with open('steamClient.pkl', 'wb') as f:
pickle.dump(steam_client, f)
- Если файл steamClient.pkl существует, то подгружаем его pickle.load(f) в переменную steam_client.
- Если отсутствует, то логинимся в стиме steam_client.login, и объект steam_client сохраняем в файл steamClient.pkl.
Таким образом, бот авторизируется в стиме 1 раз, а дальше, будет подгружать сессию из файла.
Заключение.
Данная библиотека, мне очень помогла в написании tf2.tm бота, который я упоминал здесь. Применив знания с данной статьи отсюда и отсюда, вы сможете написать похожего бота.
Итоговый результат.
