Skip to content

Commit

Permalink
Finally: Big part of a docs 📖 (without mixins methods and utils)
Browse files Browse the repository at this point in the history
  • Loading branch information
somespecialone committed Sep 19, 2024
1 parent 1b31cff commit 2a9af23
Show file tree
Hide file tree
Showing 16 changed files with 766 additions and 428 deletions.
65 changes: 65 additions & 0 deletions docs/design.md
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 👋!
42 changes: 42 additions & 0 deletions docs/exceptions.md
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)
```
4 changes: 2 additions & 2 deletions docs/ext/converter.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Currencies converter
# Currencies converter 💱

A `dict-like` class to handle converting steam currencies.

Expand All @@ -18,7 +18,7 @@ poetry add aiosteampy[converter]
Before start converting rates need to be loaded.

```python
from aiosteampy.converter import CurrencyConverter
from aiosteampy.ext.converter import CurrencyConverter

converter = CurrencyConverter()
await converter.load()
Expand Down
4 changes: 2 additions & 2 deletions docs/ext/user_agents.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# User Agents Server
# User Agents Service 🕶️

`List-like` class of user agents responsible for loading and getting random user agents.

Expand All @@ -8,7 +8,7 @@
## Creating instance and loading agents

```python
from aiosteampy.user_agents import UserAgentsService
from aiosteampy.ext.user_agents import UserAgentsService

user_agents = UserAgentsService()
await user_agents.load()
Expand Down
115 changes: 89 additions & 26 deletions docs/get_started.md
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 😉
5 changes: 2 additions & 3 deletions docs/install.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Prerequisites

You need python 3.10 and above to use this library.
You need **python 3.10** and above to use this library.

{%
include-markdown "../README.md"
Expand All @@ -11,5 +11,4 @@ You need python 3.10 and above to use this library.
!!! tip "speedups"
[Aiohttp docs](https://docs.aiohttp.org/en/stable/#library-installation) recommends install speedups (`aiodns`, ...)

!!! info "`asyncsteampy`"
Old version still available on PyPI: [asyncsteampy](https://pypi.org/project/asyncsteampy/)
[//]: # (TODO notes about steam updates and old version that will stop working in that case)
Loading

0 comments on commit 2a9af23

Please sign in to comment.