Как написать стим бота на питоне

Предисловие.

В этом уроке вы научитесь работать с библиотекой 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 не работает?

Из-за изменения api стима, через steampy невозможно залогиниться, и как следствие, написать бота. Пока автор не обновил библиотеку, используйте форк steampy_rework. Он, почти, полная копия steampy, за исключением некоторых комманд:

Инициализируем steam_client так:

steam_client = SteamClient(steam_guard="guard.json")

А логинимся так:

 steam_client.login(steam_login, steam_password)

Также, в этом форке удобней сохранять ссессию. Не забудьте поставить звезду автору библиотеки, ему это будет очень приятно.

Подтверждаем обмен.

Напишем основу стим бота.

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=тип_игры)

В данном примере мы установим заявку на покупку 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 бота, который я упоминал здесь. Применив знания с данной статьи отсюда и отсюда, вы сможете написать похожего бота.

Итоговый результат.

Steam Trade Offers Client for Python

PayPal Donate Button

Donate bitcoin: 3KrB6B5YRQuSEEZ5EVMAQeGa3SLCFZ76T7

steampy is a library for Python, inspired by node-steam-tradeoffers, node-steam and other libraries for Node.js.
It was designed as a simple lightweight library, combining features of many steam libraries from Node.js into a single python module.
steampy is capable of logging into steam, fetching trade offers and handling them in simple manner, using steam user credentials
and SteamGuard file(no need to extract and pass sessionID and webCookie).
steampy is developed with Python 3 using type hints and many other features its supported for Windows, Linux and MacOs.

Table of Content

  • Installation

  • Usage

  • Examples

  • SteamClient methods

  • Market methods

  • Guard module functions

  • SteamChat methods

  • Test

  • License

Installation

Usage

Obtaining API Key

Obtaining SteamGuard from mobile device

Obtaining SteamGuard using Android emulation

from steampy.client import SteamClient

steam_client = SteamClient('MY_API_KEY')
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')

If you have steamid, shared_secret and identity_secret you can place it in file Steamguard.txt instead of fetching SteamGuard file from device.

{
    "steamid": "YOUR_STEAM_ID_64",
    "shared_secret": "YOUR_SHARED_SECRET",
    "identity_secret": "YOUR_IDENTITY_SECRET"
}

Examples

You’ll need to obtain your API key and SteamGuard file in order to run the examples,
and then fill login and password in storehose.py file.
The storehouse.py file contains an example of handling incoming trade offers.

If you want to generate authentication codes and use steampy as steam desktop authenticator
then fill required secrets in desktop_authenticator.py file.
The desktop_authenticator.py file contains examples of generating such one time codes/

python desktop_authenticator.py

SteamClient methods

Unless specified in documentation, the method does not require login to work(it uses API Key from constructor instead)

login(username: str, password: str, steam_guard: str) -> requests.Response

Log into the steam account. Allows to accept trade offers and some other methods.

from steampy.client import SteamClient

steam_client = SteamClient('MY_API_KEY')
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')

You can also use with statement to automatically login and logout.

with SteamClient(api_key, login, password, steam_guard_file) as client:
    client.some_method1(...)
    client.some_method2(...)
    ...

logout() -> None

Using SteamClient.login method is required before usage
Logout from steam.

from steampy.client import SteamClient

steam_client = SteamClient('MY_API_KEY')
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
steam_client.logout()

You can also use with statement to automatically login and logout.

with SteamClient(api_key, login, password, steam_guard_file) as client:
    client.some_method1(...)
    client.some_method2(...)
    ...

is_session_alive() -> None

Using SteamClient.login method is required before usage
Check if session is alive. This method fetches main page and check
if user name is there. Thanks for vasia123 for this solution.

from steampy.client import SteamClient

steam_client = SteamClient('MY_API_KEY')
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
is_session_alive = steam_client.is_session_alive()

api_call(request_method: str, interface: str, api_method: str, version: str, params: dict = None) -> requests.Response

Directly call api method from the steam api services.

Official steam api site

Unofficial but more elegant

from steampy.client import SteamClient

steam_client = SteamClient('MY_API_KEY')
params = {'key': 'MY_API_KEY'}
summaries =  steam_client.api_call('GET', 'IEconService', 'GetTradeOffersSummary', 'v1', params).json()

get_trade_offers_summary() -> dict

get_trade_offers(merge: bool = True) -> dict

Fetching trade offers from steam using an API call.
Method is fetching offers with descriptions that satisfy conditions:

* Are sent by us or others
* Are active (means they have `trade_offer_state` set to 2 (Active))
* Are not historical
* No time limitation

If merge is set True then offer items are merged from items data and items description into dict where items id is key
and descriptions merged with data are value.

get_trade_offer(trade_offer_id: str, merge: bool = True) -> dict

get_trade_receipt(trade_id: str) -> list

Using SteamClient.login method is required before usage
Getting the receipt for a trade with all item information after the items has been traded.
Do NOT store any item ids before you got the receipt since the ids may change.
«trade_id» can be found in trade offers: offer['response']['offer']['tradeid']. Do not use ´tradeofferid´.

make_offer(items_from_me: List[Asset], items_from_them: List[Asset], partner_steam_id: str, message:str =») -> dict

Using SteamClient.login method is required before usage
Asset is class defined in client.py, you can obtain asset_id from SteamClient.get_my_inventory method.
This method also uses identity secret from SteamGuard file to confirm the trade offer.
No need to manually confirm it on mobile app or email.
This method works when partner is your friend or steam.
In returned dict there will be trade offer id by the key tradeofferid.

from steampy.client import SteamClient, Asset
from steampy.utils import GameOptions

steam_client = SteamClient('MY_API_KEY')
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
partner_id = 'PARTNER_ID'
game = GameOptions.CS
my_items = steam_client.get_my_inventory(game)
partner_items = steam_client.get_partner_inventory(partner_id, game)
my_first_item = next(iter(my_items.values()))
partner_first_item = next(iter(partner_items.values()))
my_asset = Asset(my_first_item['id'], game)
partner_asset = Asset(partner_first_item['id'], game)
steam_client.make_offer([my_asset], [partner_asset], partner_id, 'Test offer')

make_offer_with_url(items_from_me: List[Asset], items_from_them: List[Asset], trade_offer_url: str, message: str = », case_sensitive: bool = True) -> dict

Using SteamClient.login method is required before usage
This method is similar to SteamClient.make_offer, but it takes trade url instead of friend account id.
It works even when partner isn’t your steam friend
In returned dict there will be trade offer id by the key tradeofferid.
If case_sensitive is False, then url params with be parsed with case insensitive params keys.

get_escrow_duration(trade_offer_url: str) -> int

Using SteamClient.login method is required before usage

Check the escrow duration for trade between you and partner(given partner trade offer url)

accept_trade_offer(trade_offer_id: str) -> dict

Using SteamClient.login method is required before usage
This method also uses identity secret from SteamGuard file to confirm the trade offer.
No need to manually confirm it on mobile app or email.

decline_trade_offer(trade_offer_id: str) -> dict

Decline trade offer that other user sent to us.

cancel_trade_offer(trade_offer_id: str) -> dict

Cancel trade offer that we sent to other user.

get_my_inventory(game: GameOptions, merge: bool = True, count: int = 5000) -> dict

Using SteamClient.login method is required before usage

If merge is set True then inventory items are merged from items data and items description into dict where items id is key
and descriptions merged with data are value.

Count parameter is default max number of items, that can be fetched.

Inventory entries looks like this:

{'7146788981': {'actions': [{'link': 'steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20S%owner_steamid%A%assetid%D316070896107169653',
                             'name': 'Inspect in Game...'}],
                'amount': '1',
                'appid': '730',
                'background_color': '',
                'classid': '1304827205',
                'commodity': 0,
                'contextid': '2',
                'descriptions': [{'type': 'html',
                                  'value': 'Exterior: Field-Tested'},
                                 {'type': 'html', 'value': ' '},
                                 {'type': 'html',
                                  'value': 'Powerful and reliable, the AK-47 '
                                           'is one of the most popular assault '
                                           'rifles in the world. It is most '
                                           'deadly in short, controlled bursts '
                                           'of fire. It has been painted using '
                                           'a carbon fiber hydrographic and a '
                                           'dry-transfer decal of a red '
                                           'pinstripe.n'
                                           'n'
                                           '<i>Never be afraid to push it to '
                                           'the limit</i>'},
                                 {'type': 'html', 'value': ' '},
                                 {'app_data': {'def_index': '65535',
                                               'is_itemset_name': 1},
                                  'color': '9da1a9',
                                  'type': 'html',
                                  'value': 'The Phoenix Collection'},
                                 {'type': 'html', 'value': ' '},
                                 {'app_data': {'def_index': '65535'},
                                  'type': 'html',
                                  'value': '<br><div id="sticker_info" '
                                           'name="sticker_info" title="Sticker '
                                           'Details" style="border: 2px solid '
                                           'rgb(102, 102, 102); border-radius: '
                                           '6px; width=100; margin:4px; '
                                           'padding:8px;"><center><img '
                                           'width=64 height=48 '
                                           'src="https://steamcdn-a.akamaihd.net/apps/730/icons/econ/stickers/eslkatowice2015/pentasports.a6b0ddffefb5507453456c0d2c35b6a57821c171.png"><img '
                                           'width=64 height=48 '
                                           'src="https://steamcdn-a.akamaihd.net/apps/730/icons/econ/stickers/eslkatowice2015/pentasports.a6b0ddffefb5507453456c0d2c35b6a57821c171.png"><img '
                                           'width=64 height=48 '
                                           'src="https://steamcdn-a.akamaihd.net/apps/730/icons/econ/stickers/eslkatowice2015/pentasports.a6b0ddffefb5507453456c0d2c35b6a57821c171.png"><img '
                                           'width=64 height=48 '
                                           'src="https://steamcdn-a.akamaihd.net/apps/730/icons/econ/stickers/cologne2015/mousesports.3e75da497d9f75fa56f463c22db25f29992561ce.png"><br>Sticker: '
                                           'PENTA Sports  | Katowice 2015, '
                                           'PENTA Sports  | Katowice 2015, '
                                           'PENTA Sports  | Katowice 2015, '
                                           'mousesports | Cologne '
                                           '2015</center></div>'}],
                'icon_drag_url': '',
                'icon_url': '-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV09-5lpKKqPrxN7LEmyVQ7MEpiLuSrYmnjQO3-UdsZGHyd4_Bd1RvNQ7T_FDrw-_ng5Pu75iY1zI97bhLsvQz',
                'icon_url_large': '-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV09-5lpKKqPrxN7LEm1Rd6dd2j6eQ9N2t2wK3-ENsZ23wcIKRdQE2NwyD_FK_kLq9gJDu7p_KyyRr7nNw-z-DyIFJbNUz',
                'id': '7146788981',
                'instanceid': '480085569',
                'market_actions': [{'link': 'steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D316070896107169653',
                                    'name': 'Inspect in Game...'}],
                'market_hash_name': 'AK-47 | Redline (Field-Tested)',
                'market_name': 'AK-47 | Redline (Field-Tested)',
                'market_tradable_restriction': '7',
                'marketable': 1,
                'name': 'AK-47 | Redline',
                'name_color': 'D2D2D2',
                'owner_descriptions': '',
                'tags': [{'category': 'Type',
                          'category_name': 'Type',
                          'internal_name': 'CSGO_Type_Rifle',
                          'name': 'Rifle'},
                         {'category': 'Weapon',
                          'category_name': 'Weapon',
                          'internal_name': 'weapon_ak47',
                          'name': 'AK-47'},
                         {'category': 'ItemSet',
                          'category_name': 'Collection',
                          'internal_name': 'set_community_2',
                          'name': 'The Phoenix Collection'},
                         {'category': 'Quality',
                          'category_name': 'Category',
                          'internal_name': 'normal',
                          'name': 'Normal'},
                         {'category': 'Rarity',
                          'category_name': 'Quality',
                          'color': 'd32ce6',
                          'internal_name': 'Rarity_Legendary_Weapon',
                          'name': 'Classified'},
                         {'category': 'Exterior',
                          'category_name': 'Exterior',
                          'internal_name': 'WearCategory2',
                          'name': 'Field-Tested'},
                         {'category': 'Tournament',
                          'category_name': 'Tournament',
                          'internal_name': 'Tournament6',
                          'name': '2015 ESL One Katowice'},
                         {'category': 'Tournament',
                          'category_name': 'Tournament',
                          'internal_name': 'Tournament7',
                          'name': '2015 ESL One Cologne'},
                         {'category': 'TournamentTeam',
                          'category_name': 'Team',
                          'internal_name': 'Team39',
                          'name': 'PENTA Sports'},
                         {'category': 'TournamentTeam',
                          'category_name': 'Team',
                          'internal_name': 'Team29',
                          'name': 'mousesports'}],
                'tradable': 1,
                'type': 'Classified Rifle'}}

get_partner_inventory(partner_steam_id: str, game: GameOptions, merge: bool = True, count: int = 5000) -> dict

Using SteamClient.login method is required before usage

Inventory items can be merged like in SteamClient.get_my_inventory method

Count parameter is default max number of items, that can be fetched.

get_wallet_balance(convert_to_float: bool = True) -> Union[str, float]

Check account balance of steam acccount. It uses parse_price method from utils
to covnert money string to Decimal if convert_to_decimal is set to True.

Example:

 with SteamClient(api_key, login, password, steam_guard_file) as client:
            wallet_balance = client.get_wallet_balance()
            self.assertTrue(type(wallet_balance), decimal.Decimal)

market methods

fetch_price(item_hash_name: str, game: GameOptions, currency: str = Currency.USD) -> dict

Some games are predefined in GameOptions class, such as GameOptions.DOTA2, GameOptions.CS and GameOptions.TF2, but GameOptions` object can be constructed with custom parameters.

Currencies are defined in Currency class, currently

Default currency is USD

May rise TooManyRequests exception if used more than 20 times in 60 seconds.

steam_client = SteamClient(self.credentials.api_key)
item = 'M4A1-S | Cyrex (Factory New)'
steam_client.market.fetch_price(item, game=GameOptions.CS)
{'volume': '208', 'lowest_price': '$11.30 USD', 'median_price': '$11.33 USD', 'success': True}

fetch_price_history(item_hash_name: str, game: GameOptions) -> dict

Using SteamClient.login method is required before usage

Returns list of price history of and item.

with SteamClient(self.credentials.api_key, self.credentials.login,
                 self.credentials.password, self.steam_guard_file) as client:
    item = 'M4A1-S | Cyrex (Factory New)'
    response = client.market.fetch_price_history(item, GameOptions.CS)
    response['prices'][0]
    ['Jul 02 2014 01: +0', 417.777, '40']

Each entry in response['prices'] is a list, with first entry being date, second entry price, and third entry a volume.

get_my_market_listings() -> dict

Using SteamClient.login method is required before usage

Returns market listings posted by user

steam_client = SteamClient(self.credentials.api_key)
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
listings = steam_client.market.get_my_market_listings()

create_sell_order(assetid: str, game: GameOptions, money_to_receive: str) -> dict

Using SteamClient.login method is required before usage

Create sell order of the asset on the steam market.

steam_client = SteamClient(self.credentials.api_key)
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
asset_id_to_sell = 'some_asset_id'
game = GameOptions.DOTA2
sell_response = steam_client.market.create_sell_order(asset_id_to_sell, game, "10000")

⚠️ money_to_receive has to be in cents, so «100.00» should be passed has «10000»

create_buy_order(market_name: str, price_single_item: str, quantity: int, game: GameOptions, currency: Currency = Currency.USD) -> dict

Using SteamClient.login method is required before usage

Create buy order of the assets on the steam market.

steam_client = SteamClient(self.credentials.api_key)
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
response = steam_client.market.create_buy_order("AK-47 | Redline (Field-Tested)", "1034", 2, GameOptions.CS, Currency.EURO)
buy_order_id = response["buy_orderid"]

⚠️ price_single_item has to be in cents, so «10.34» should be passed has «1034»

buy_item(market_name: str, market_id: str, price: int, fee: int, game: GameOptions, currency: Currency = Currency.USD) -> dict

Using SteamClient.login method is required before usage

Buy a certain item from market listing.

steam_client = SteamClient(self.credentials.api_key)
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
response = steam_client.market.buy_item('AK-47 | Redline (Field-Tested)', '1942659007774983251', 81, 10,
                                        GameOptions.CS, Currency.RUB)
wallet_balance = response["wallet_info"]["wallet_balance"]

cancel_sell_order(sell_listing_id: str) -> None

Using SteamClient.login method is required before usage

Cancel previously requested sell order on steam market.

steam_client = SteamClient(self.credentials.api_key)
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
sell_order_id = "some_sell_order_id"
response = steam_client.market.cancel_sell_order(sell_order_id)

cancel_buy_order(buy_order_id) -> dict

Using SteamClient.login method is required before usage

Cancel previously requested buy order on steam market.

steam_client = SteamClient(self.credentials.api_key)
steam_client.login('MY_USERNAME', 'MY_PASSWORD', 'PATH_TO_STEAMGUARD_FILE')
buy_order_id = "some_buy_order_id"
response = steam_client.market.cancel_buy_order(buy_order_id)

Currencies

Currency class Description
Currency.USD United States Dollar
Currency.GBP United Kingdom Pound
Currency.EURO European Union Euro
Currency.CHF Swiss Francs
Currency.RUB Russian Rouble
Currency.PLN Polish Złoty
Currency.BRL Brazilian Reals
Currency.JPY Japanese Yen
Currency.NOK Norwegian Krone
Currency.IDR Indonesian Rupiah
Currency.MYR Malaysian Ringgit
Currency.PHP Philippine Peso
Currency.SGD Singapore Dollar
Currency.THB Thai Baht
Currency.VND Vietnamese Dong
Currency.KRW South Korean Won
Currency.TRY Turkish Lira
Currency.UAH Ukrainian Hryvnia
Currency.MXN Mexican Peso
Currency.CAD Canadian Dollars
Currency.AUD Australian Dollars
Currency.NZD New Zealand Dollar
Currency.CNY Chinese Renminbi (yuan)
Currency.INR Indian Rupee
Currency.CLP Chilean Peso
Currency.PEN Peruvian Sol
Currency.COP Colombian Peso
Currency.ZAR South African Rand
Currency.HKD Hong Kong Dollar
Currency.TWD New Taiwan Dollar
Currency.SAR Saudi Riyal
Currency.AED United Arab Emirates Dirham
Currency.SEK Swedish Krona
Currency.ARS Argentine Peso
Currency.ILS Israeli New Shekel
Currency.BYN Belarusian Ruble
Currency.KZT Kazakhstani Tenge
Currency.KWD Kuwaiti Dinar
Currency.QAR Qatari Riyal
Currency.CRC Costa Rican Colón
Currency.UYU Uruguayan Peso
Currency.BGN Bulgarian Lev
Currency.HRK Croatian Kuna
Currency.CZK Czech Koruna
Currency.DKK Danish Krone
Currency.HUF Hungarian Forint
Currency.RON Romanian Leu

guard module functions

load_steam_guard(steam_guard: str) -> dict

If steam_guard is file name then load and parse it, else just parse steam_guard as json string.

generate_one_time_code(shared_secret: str, timestamp: int = None) -> str

Generate one time code for logging into Steam using shared_secret from SteamGuard file.
If none timestamp provided, timestamp will be set to current time.

generate_confirmation_key(identity_secret: str, tag: str, timestamp: int = int(time.time())) -> bytes

Generate mobile device confirmation key for accepting trade offer.
Default timestamp is current time.

SteamChat methods

send_message(steamid_64: str, text: str) -> requests.Response

Send the string contained in text to the desired steamid_64.

client.chat.send_message("[steamid]", "This is a message.")

fetch_messages() -> dict

Returns a dictionary with all new sent and received messages:

{
    'sent': [
        {'partner': "[steamid]", 'message': "This is a message."}
    ],
    'received': []
}

client.chat.fetch_messages()

Test

All public methods are documented and tested.
guard module has unit tests, client uses an acceptance test.
For the acceptance test you have to put credentials.pwd and Steamguard file into test directory

Example credentials.pwd file:

account1 password1 api_key1
account2 password2 api_key2

In some tests you also have to obtain transaction_id.
You can do it by SteamClient.get_trade_offers or by logging manually into steam account in browser and get it from url

In some tests you also have to obtain partner steam id.
You can do it by by logging manually into steam account in browser and get it from url

License

MIT License

Copyright (c) 2016 Michał Bukowski

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the «Software»), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

steam.py is a modern, easy to use, and async ready API wrapper for the Steam API and its CMs. Heavily inspired by
discord.py and borrowing functionality from
ValvePython/steam.

Key Features#

  • Modern Pythonic API using async/await syntax

  • Command extension to aid with bot creation

  • Easy to use with an object-oriented design

  • Fully typed hinted for faster development

Getting help#

  • These are good pages to start with if it’s your first time see Quickstart & F.A.Q

  • Ask us in our discord server.

  • If you’re looking for something specific, try the index or searching.

  • Report bugs in the issue tracker.

API references#

Pages detailing the API.

  • steam API Reference
  • steam.ext.commands API Reference

Extensions#

steam.py has extension modules to help with common tasks.

  • steam.ext.commands — Bot commands framework

i am currently working on a project that involves TF2,python,and steam trading. I would like to know how i can send a steam trade offer from python. I do not need source code or anything, just point me in the right direction. I have searched for ~20 mins on google and cant find anything quite like what i want, they all want to log in to check steam trade offers or the community market prices.

asked Jul 13, 2015 at 3:57

Michael Becker's user avatar

I looked hard and couldn’t find a Python library unfortunately, but I did find this Node.js library that does what you want and looks robust at first glance:

Steam trading for Node.js
Allows you to automate Steam trading in Node.js.
https://github.com/seishun/node-steam-trade

You might consider writing your app in Javascript, because the library is there. Alternatively, call your Python functions from Node.js.

answered Jul 13, 2015 at 4:11

Maximillian Laumeister's user avatar

1

Jun 21, 2021

1 min read

steam.py

A modern, easy to use, and async ready package to interact with the Steam API. Heavily inspired by discord.py and borrowing functionality from ValvePython/steam.

Key Features

  • Modern Pythonic API using async/await syntax
  • Command extension to aid with bot creation
  • Easy to use with an object-oriented design
  • Fully typed hinted for faster development

Installation

Python 3.7 or higher is required

To install the library just run either of the following commands:

# Linux/macOS
python3 -m pip install -U steamio
# Windows
py -m pip install -U steamio

Or for the development version.

# Linux/macOS
python3 -m pip install -U "steamio @ git+https://github.com/Gobot1234/[email protected]"
# Windows
py -m pip install -U "steamio @ git+https://github.com/Gobot1234/[email protected]"

Quick Example

import steam


class MyClient(steam.Client):
    async def on_ready(self) -> None:
        print("Logged in as", self.user)

    async def on_trade_receive(self, trade: steam.TradeOffer) -> None:
        await trade.partner.send("Thank you for your trade")
        print(f"Received trade: #{trade.id}")
        print("Trade partner is:", trade.partner)
        print("We would send:", len(trade.items_to_send), "items")
        print("We would receive:", len(trade.items_to_receive), "items")

        if trade.is_gift():
            print("Accepting the trade as it is a gift")
            await trade.accept()


client = MyClient()
client.run("username", "password")

Bot Example

from steam.ext import commands

bot = commands.Bot(command_prefix="!")


@bot.command
async def ping(ctx: commands.Context) -> None:
    await ctx.send("Pong!")


bot.run("username", "password")

GitHub

https://github.com/Gobot1234/steam.py

John

John was the first writer to have joined pythonawesome.com. He has since then inculcated very effective writing and reviewing culture at pythonawesome which rivals have found impossible to imitate.

A multipurpose Telegram Bot made with Pyrogram and asynchronous programming
Previous Post

A multipurpose Telegram Bot made with Pyrogram and asynchronous programming

A Python 3 package for Misty II development using Misty's REST API
Next Post

A Python 3 package for Misty II development using Misty’s REST API

Я решился сделать «небольшой» парсер нужной мне информации по лотам торговой площадки стим для оперирование с ней в дальнейшем. Поскольку, я просмотрел множество информации, как это можно сделать, я не нашел ничего потного или нашел, но без должного объяснения.
Допусти пример https://question-it.com/questions/4398755/steam-ma… тут формируется запрос к ТП с понятным объяснения для данной ситуации. Мне нужна более подробное разъяснение некая документация.
Я не рассматриваю вариант с официальным api, так как там нет подробностей именно с ТП (steamworks).

Python я выбрал, так как мне этот язык намного ближе к сердцу и я в нем больше разбираюсь ( в любом случаем можно будет переписать на него ).

Порядок действий:
1. Это сделать полный парсинг всех лотов по игре условно возьмем pubg ( id 578080 ).
2. По нужному алгоритму я выбираю предметы ( ну допустим в массив)
3. По выбранным предметам я собираю полную инфу, то есть цена авто покупки, просто покупки, продажи, в бушующем возможно индивидуальный id предмета, float и т д.
И естественно эти запросы должны формироваться автоматически по заданной модели и сохранять все это в бд ( это самая легкая часть )

Это все мне нужно для создания бота стим. Да, я больной человек, который развлекается таким образом.
Я видел, что есть уже подобные решения, но там на столько огромные проекты ( в несколько тысяч строк ), что я буду разбираться в них до второго предшествии и мне будет гораздо проще и интереснее разобраться в этом самому.

Я рассматривал вариант «против лома нет приема» в виде bs4, но это прям крайний вариант к которому я приду, в случае не удачи с api или его подобием.

Я прощу вас дать мне механизм, как это сделать или стать, гайды и другую инфу.

A Steam lib for trade automation

Project description

The author of this package has not provided a project description

Project details

Download files

Download the file for your platform. If you’re not sure which to choose, learn more about installing packages.

Source Distribution

Built Distribution

Close

Hashes for steampy-0.75.tar.gz

Hashes for steampy-0.75.tar.gz

Algorithm Hash digest
SHA256 df81d3feb4e0ee64ab14f407aff21eccb3572744e9ab5a044a704d10ab6326b2
MD5 6e9f359ce19e65e279f25020a50b139e
BLAKE2b-256 47a1c90f07d14ce4b70cb3807c375c751ac31be78f1eda8bae35bea97896ee1d

Close

Hashes for steampy-0.75-py3-none-any.whl

Hashes for steampy-0.75-py3-none-any.whl

Algorithm Hash digest
SHA256 da6004e05ce303f0e6229f78ec97ea635c96bb10dee3867e6ab1f0abae98dc9a
MD5 e8863512979e4a782f1bf79ad35a873f
BLAKE2b-256 595efea9e9da99da546fb86406c2e524c02f95df3c2783ac637d05a8475c358c

Понравилась статья? Поделить с друзьями:

Не пропустите и эти статьи:

  • Как написать стиль css
  • Как написать стиллер паролей на python
  • Как написать стиллер на питоне
  • Как написать стиллер на пайтоне
  • Как написать стиллер на lua

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии