-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Finally: Big part of a docs 📖 (without mixins methods and utils)
- Loading branch information
1 parent
1b31cff
commit 2a9af23
Showing
16 changed files
with
766 additions
and
428 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
## Prologue | ||
|
||
This project embodies `SteamCommunity` + a small part of the `Steam Web Api`. | ||
Designed to be flexible with modest complexity, while being typed and developer friendly as possible. | ||
|
||
> Created mostly for trading purposes, so, I hope, must and will cover most cases for `Steam` trading. | ||
As you can read in [previous](./get_started.md#first-words) chapter, there is two **clients**: public and non-public. | ||
Both represents interaction layer with `SteamCommunity`. | ||
Each **client** instance has separate `session`, therefore as **cookies**, and other properties | ||
(country, currency, ...). | ||
|
||
!!! tip | ||
Think of them as a private-mode window of a web browser. Each **client** instance is a new private mode window, | ||
completely independent and separate from others | ||
|
||
!!! info "Persistence" | ||
However, if it is impossible to store session properties from private window of a web browser and then restore | ||
from them intentionally, You can do this with `aiosteampy` **client**, both public and non. | ||
Take a closer look [here](./session.md) | ||
|
||
## Points | ||
|
||
All interaction with `SteamCommunity` goes through the **client**. Next means that models, | ||
like `EconItem`, `MarketListing`, `TradeOffer` does not have methods to interact with `SteamCommunity` | ||
and do not even know what the **client** is. | ||
|
||
!!! info "Web proxy" | ||
Each client can be connected to a web proxy and make all requests through it. | ||
[Proxies](./proxies.md) chapter will tell you more about it. | ||
|
||
To give more grain control over requests, whenever it is possible methods have **headers** and | ||
**payload/params** arguments to pass additional info/data to request. | ||
|
||
### Community parts | ||
|
||
**Client** consist of a methods related to different parts of `SteamCommunity`. | ||
As example, `MarketMixin` responsible for methods related to `SteamMarket`: buying listings, get listings, get orders | ||
and more, `TradeMixin`, otherwise, responsible for methods related to trade offers: create, counter, decline, ... | ||
|
||
So, if you want to augment client behaviour, subclass `SteamClientBase` or `SteamPublicClientBase` for your needs. | ||
This classes inherit all corresponding mixins. [Inheritance](./client.md#inheritance) | ||
|
||
### Exceptions | ||
|
||
There is two general types of exceptions: `python` (builtin exceptions, related to invalid arguments values, | ||
broken connection, so on) and `steam`, that raised when code faced error while trying to interact with `Steam`, | ||
as follows: `Steam` cannot return market listings, items not in inventory, malformed response, `Steam` | ||
return error result (`EResult`) deliberately for some reason (lol) or even give your **client** (mainly, by ip) a | ||
rate limit restriction ([more information](./scraping.md)). | ||
|
||
### Modules & entrypoints | ||
|
||
`Aiosteampy` contains `utils` and `helpers` moduls, each contain useful utilities to make work with **client** easier. | ||
[There is](./utils_helpers.md) | ||
|
||
Alongside with mentioned moduls project have a few `extensions`: | ||
|
||
- [user agents](./ext/user_agents.md) - service, which main aim is to help get random user agent for your **client/s** | ||
- [currency converter](./ext/converter.md) - service, aims to help you convert `Steam` currencies | ||
|
||
## Epilogue | ||
|
||
_That's it_. Further information introduce short overview of methods, how things work more detailed and even | ||
hard to say some patterns. Good luck 👋! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
What type of exceptions can be raised in method you can see at corresponding `docstring`. | ||
|
||
All `Steam` side errors does have `SteamError` class. | ||
|
||
So, to catch all errors of this type, all you need to do next is: | ||
|
||
```python | ||
from aiosteampy import SteamError | ||
|
||
try: | ||
await client.login() | ||
except SteamError as e: | ||
print("Catch Steam error", e) | ||
``` | ||
|
||
But, more detailed, there is an exception hierarchy - next errors subclass `SteamError`: | ||
|
||
- **EResultError** - raised when `Steam` response with error code (`success` field in json response). Look at | ||
[steamerrors.com](https://steamerrors.com) | ||
- **LoginError** - when there is an error in login process occurred | ||
- **SessionExpired** - means that your session is expired, and you need to do login again. | ||
Raise decision based solely on response from `Steam` and no internal logic, for ex. check `access_token` | ||
- **RateLimitExceeded** - you have been rate limited | ||
- **ResourceNotModified** - means that requested data has not been modified since timestamp | ||
from passed `If-Modified-Since` header value | ||
|
||
[More information](./scraping.md) regarded last two exceptions | ||
|
||
Respecting the hierarchy: | ||
|
||
```python | ||
from aiosteampy import SteamError, LoginError, EResultError | ||
|
||
try: | ||
await client.login() | ||
except LoginError as e: | ||
print("Catch specific login error", e) | ||
except EResultError as e: | ||
print("Catch e result error", e) | ||
except SteamError as e: | ||
print("Catch other Steam errors (there is nothing in login method, btw)", e) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,126 @@ | ||
### Client creation and login | ||
## First words | ||
|
||
`SteamClient` with minimal setup: | ||
First of all, main entity to hold all interaction with `SteamCommunity` is **client**. There is two type of **clients**: | ||
|
||
* `SteamPublicClient` - for methods that do not require authentication, such as getting market data, listings, | ||
getting non-private inventory of users, etc... | ||
* `SteamClient` - all from `SteamPublicClient` plus methods related to personal `Steam` account: login, inventory of | ||
self, trade offers creation, declining, countering, buying market listings, creating sell orders and more. | ||
This page contains examples based on this **client**. | ||
|
||
### Client creation, login and preparing | ||
|
||
`SteamClient` with minimal setup, must be instantiated in **async context** (within **event loop**, or, | ||
for simplicity, function defined with `async def`): | ||
|
||
```python | ||
from aiosteampy import SteamClient | ||
|
||
|
||
client = SteamClient( | ||
112233, # steam id(64) or account id(32) | ||
"username", | ||
"password", | ||
112233, # steam id(64) or account id(32) | ||
shared_secret="shared secret", | ||
identity_secret="identity secret", | ||
user_agent="my user agent :)" | ||
"shared secret", | ||
"identity secret", # almost optional | ||
user_agent="my user agent" # strongly recommended | ||
) | ||
|
||
await client.login() | ||
|
||
# load properties required for all methods to work | ||
# (currency, country, trade token) | ||
await client.prepare() | ||
``` | ||
|
||
??? info "Client args" | ||
Client will retrieve needed data from `steam` if you not pass it. Details [there](client.md#init--login). | ||
!!! info "Prepare client to work" | ||
Consider preparing client to make code below work by calling `client.prepare` method after `client.login` | ||
or pass required properties to constructor. [Read more](./client.md) | ||
|
||
???+ tip "User-Agent" | ||
!!! tip "User-Agent header" | ||
[Aiohttp](https://docs.aiohttp.org/en/stable/) uses its own `User-Agent` header by default. | ||
It is strongly recommended to replace it with your own. | ||
**It is strongly recommended to replace it with your own**. | ||
You can easily get one from [randua.somespecial.one](https://randua.somespecial.one) | ||
or use [User Agent Service](./ext/user_agents.md). | ||
|
||
### Do work | ||
|
||
Simple showcase. For more details, please, continue reading | ||
|
||
```python | ||
from aiosteampy import Game | ||
from aiosteampy import AppContext | ||
|
||
# get self inventory | ||
my_inventory, _, _ = await client.get_inventory(AppContext.CS2) | ||
|
||
inv = await client.get_inventory(Game.CSGO) # get self inventory | ||
first_item = my_inventory[0] | ||
|
||
listings, total_count = await client.get_item_listings(inv[0]) # fetch listings for this item | ||
# fetch listings for this item | ||
listings, _, _ = await client.get_item_listings(first_item.description) | ||
first_listing = listings[0] | ||
|
||
wallet_balance = await client.buy_market_listing(listings[0]) # buy first listing and get new wallet balance | ||
await client.buy_market_listing(first_listing) # buy first listing | ||
|
||
listing_id = await client.place_sell_listing(inv[0], price=15.6) # place sell order on market | ||
# let's increase price for about 10% | ||
price = int(first_listing.price * 1.1) | ||
|
||
await client.cancel_sell_listing(listing_id) # changed my mind and want to cancel my sell listing | ||
# place sell order on market | ||
listing_id = await client.place_sell_listing(first_item, price=price) | ||
|
||
# hmm, I've changed my mind and want to cancel my sell listing | ||
await client.cancel_sell_listing(listing_id) | ||
``` | ||
|
||
### Do another work | ||
|
||
```python | ||
from aiosteampy import Game, TradeOfferStatus | ||
from aiosteampy import AppContext, SteamClient | ||
|
||
client: SteamClient | ||
|
||
gifts = await client.get_inventory(Game.CSGO, predicate=lambda i: "Nova Mandrel" in i.class_.name) # get all Nova Mandrel items from inventory | ||
# get self inventory | ||
inv, _, _ = await client.get_inventory(AppContext.CS2) | ||
# get all Nova Mandrel items from inventory | ||
gifts = list(filter(lambda i: "Nova Mandrel" in i.description.name, inv)) | ||
|
||
partner_id = 123456789 # in friends list | ||
offer_id = await client.make_trade_offer(partner_id, gifts, message="Gift for my friend!") # make and confirm trade | ||
partner_id = 123456789 # partner, which in friends list, id | ||
|
||
gift_trade = await client.fetch_trade(offer_id) # just get trade from steam | ||
if gift_trade.status is TradeOfferStatus.ACCEPTED: | ||
print("yeeah") | ||
elif gift_trade.status is TradeOfferStatus.DECLINED: | ||
print("Ouugh noo...") | ||
# make and confirm trade, fetch and return trade offer | ||
trade = await client.make_trade_offer( | ||
partner_id, | ||
gifts, | ||
message="Gift for my friend!", | ||
fetch=True, | ||
) | ||
|
||
if trade.accepted: | ||
print("yeeahs") | ||
elif trade.declined: | ||
print("Bbut wmhhy?") | ||
elif trade.active: | ||
await client.cancel_trade_offer(trade) # haha, I revoke my gift | ||
``` | ||
|
||
### Catch errors | ||
|
||
```python | ||
from aiosteampy import App, RateLimitExceeded, EResultError | ||
|
||
try: | ||
listings, _, _ = await client.get_item_listings( | ||
"AWP | Chromatic Aberration (Field-Tested)", | ||
App.CS2, | ||
) | ||
except RateLimitExceeded: | ||
print("Whhosh, I need to rest a bit") | ||
except EResultError as e: | ||
print(f"Steam response with error ({e.result}, {e.data}), what a surprise!") | ||
``` | ||
|
||
[Dedicated exceptions chapter](./exceptions.md) | ||
|
||
## Second words | ||
|
||
Corresponding docs pages contain more detailed information on how to use this project, what capabilities does it have | ||
and how things work. | ||
|
||
Also, it is worth reading the [design page](./design.md). Check it out at least once, you won't want to miss out 😉 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.