Skip to content
This repository has been archived by the owner on Feb 1, 2019. It is now read-only.

Commit

Permalink
modules woo (#25)
Browse files Browse the repository at this point in the history
added module support
  • Loading branch information
mninc authored Mar 10, 2018
1 parent 081fc37 commit 5933ecb
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 151 deletions.
54 changes: 29 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# steam-trade

### An asynchronous, event based python steam trade lib
## Description

Expand All @@ -9,54 +10,57 @@ It's **asynchronous**, so that means it can do multiple tasks at the same time!
It's **event based**, so that means you won't have code, doing loops, polling for trades, we do all that for you. All you have to write is a listener `@manager.on('new_trade')` and your function to proccess the event.

## Installation
You'll need to install this through pip, Python's package manager. If you don't have pip installed, then you aren't using the lastest version of python needed to run this program.
```bash
pip install -U steam-trade
```
You'll need to install this through pip, Python's package manager. If you don't have pip installed, then reinstall python with the install pip option checked (It's possible other ways, but this is seriously the easiest).
If you're installing python via a linux command line and pip isn't available, try running `sudo apt install python3-pip`.

Do `pip install -U steam-trade`, or if pip isn't added to path do `python -m pip install -U steam-trade`, substituting python with whatever you use to run python3.6 normally (this differs if you have another version of python installed)

Then, you will access it under a different name when importing it:
```py
from pytrade import *
import pytrade
```
## Usage
First, you will need to create an *AsyncClient* object, and a *TradeManager* object (see why the AsyncClient object is required in **FAQ**)
```py
steam_login = login.AsyncClient("Zwork101", "abc123", "super-secret-secret")
trade_manager = client.TradeManager("12345678", "steam api key", identity_secret="also-super-secret")
```
Now, run "setup" code. Code, like reading a database, or getting prices from a site. This code will only be run once. For example, I might to something like:
```py
key_price = 0
with open('key_price.txt') as file:
key_price = float(file.read())
steam_login = pytrade.login.AsyncClient("Zwork101", "abc123", shared_secret="super-secret-secret")
trade_manager = pytrade.manager_trade.TradeManager("12345678", "steam api key", identity_secret="also-super-secret")
global_manager = pytrade.GlobalManager([trade_manager])
```

Now, run any setup code you want.

After that, create coroutines to proccess events. Use `async` before `def` to expalin to python that function is a coroutine. Then, write the code to proccess these events.
```py
@manager.on('logged_on')
@trade_manager.on('logged_on')
async def login():
print("Trade Manager is logged in")

@manager.on('trade_accepted')
@trade_manager.on('trade_accepted')
async def trade_accept(trade_offer):
print('----NEW TRADE ACCEPTED-----------')
print(f'Trade Offer Id: {trade_offer.tradeofferid}')
print(f'From User: {trade_offer.steamid_other.toString()}')
print('---------------------------------')
```
Then, you need to run the program forever. Currently, there is no "clean" way to exit.
```py
```
Then, you need to run the program forever. Currently, there is no "clean" way to exit.
```py
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.ensure_future(manager.login(steam_login)))
trade_manager.run_forever()
loop.run_until_complete(asyncio.ensure_future(trade_manager.login(steam_login)))
global_manager.run_forever()
```
## FAQ
**Q**: Why have a class, just for a steam login?
**Q**: Why have a class just for a steam login? Why is there a global manager and a trade manager? Why does the global manager take the trade manager in a list?

**A**: Later on, I plan on making more of these steam libraries, and they will all take AsyncClient as input
**A**: Futureproofing. The global manager should be able to take many more modules, not just a trade manager. This makes it easy to add something like a steam chat manager in the future.

**Q**: What if I want to use the program, and not run it forever?

**A**: You will have to use asyncio.ensure_future(function you want to use) for each coroutine, unless you call it in another coroutine.
**A**: You will have to use `asyncio.ensure_future(function you want to use)` for each coroutine, unless you call it in another coroutine. Each manager has a `poll` method, you could run that when you like.

**Q**: How can I contribute?
**Q**: How can I help?

**A**: There are lots of ways! Just by uploading an example, or data to sample from is helpful!
**A**: There are lots of ways! Upload an example, rewrite some code (make sure to check it works first!), send a donation or just star the project - it is all appreciated!

**Q**: Who the hell made this *amazing* library?!?

**A**: Check out the [contibutors tab](https://github.com/Zwork101/steam-trade/graphs/contributors)!
8 changes: 3 additions & 5 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode']
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Expand Down Expand Up @@ -157,7 +157,5 @@
]




# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/': None}
21 changes: 11 additions & 10 deletions examples/basic.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import asyncio
from pytrade import login, client
import pytrade
from pytrade import login, manager_trade

steam_cli = login.AsyncClient('name', 'pass', shared_secret='secret')
manager = client.TradeManager('steam 64 id', key='apikey', identity_secret='your other secret')
steam_client = login.AsyncClient('name', 'pass', shared_secret='secret')
trade_manager = manager_trade.TradeManager('steam 64 id', key='apikey', identity_secret='your other secret')
global_manager = pytrade.GlobalManager([trade_manager])


# This will be called, when it completes the client.login
@manager.on('logged_on')
# Client has logged in
@trade_manager.on('logged_on')
async def login():
print('Logged in!')


# On a new trade, this will be called. an EconTradeOffer.TradeOffer object will be passed in
@manager.on('new_trade')
# A new trade has been received. Gives an EconTradeOffer.TradeOffer object
@trade_manager.on('new_trade')
async def new_offer(trade_offer):
print(f"Got Offer: {trade_offer.tradeofferid}")
if not trade_offer.items_to_give: # Not losing any items
Expand All @@ -29,7 +31,6 @@ async def new_offer(trade_offer):
print(f"Failed to decline trade: {response[1]}")


# This is the basic setup for the program, and it will run forever. Currently, there is no "nice" way to end it.
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.ensure_future(manager.login(steam_cli)))
manager.run_forever()
loop.run_until_complete(asyncio.ensure_future(trade_manager.login(steam_client)))
global_manager.run_forever()
19 changes: 10 additions & 9 deletions examples/process.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import asyncio
from pytrade import login, client
import pytrade
import json

# Open a premade prices file.
Expand All @@ -8,18 +8,19 @@
with open("prices.json", "r") as f:
prices = json.load(f)

steam_cli = login.AsyncClient('name', 'pass', shared_secret='secret')
manager = client.TradeManager('steam 64 id', key='apikey', identity_secret='your other secret')
steam_client = pytrade.login.AsyncClient('name', 'pass', shared_secret='secret')
trade_manager = pytrade.manager_trade.TradeManager('steam 64 id', key='apikey', identity_secret='your other secret')
global_manager = pytrade.GlobalManager([trade_manager])


# This will be called, when it completes the client.login
@manager.on('logged_on')
# Client has logged in
@trade_manager.on('logged_on')
async def login():
print('Logged in!')


# On a new trade, this will be called. an EconTradeOffer.TradeOffer object will be passed in
@manager.on('new_trade')
# A new trade has been received. Gives an EconTradeOffer.TradeOffer object
@trade_manager.on('new_trade')
async def new_offer(trade_offer):
print(f"Got Offer: {trade_offer.tradeofferid}")
losing_metal = 0
Expand Down Expand Up @@ -66,5 +67,5 @@ async def new_offer(trade_offer):

# This is the basic setup for the program, and it will run forever. Currently, there is no "nice" way to end it.
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.ensure_future(manager.login(steam_cli)))
manager.run_forever()
loop.run_until_complete(asyncio.ensure_future(trade_manager.login(steam_client)))
global_manager.run_forever()
59 changes: 37 additions & 22 deletions examples/receiver.py
Original file line number Diff line number Diff line change
@@ -1,89 +1,104 @@
# NOT UPDATED

import asyncio
from pytrade import login, client
import pytrade

steam_cli = login.AsyncClient('name', 'pass', shared_secret='secret')
manager = client.TradeManager('steam 64 id', key='apikey', identity_secret='your other secret')
steam_client = pytrade.login.AsyncClient('name', 'pass', shared_secret='secret')
trade_manager = pytrade.manager_trade.TradeManager('steam 64 id', key='apikey', identity_secret='your other secret')
global_manager = pytrade.GlobalManager([trade_manager])


# This will be called, when it completes the client.login
@manager.on('logged_on')
@trade_manager.on('logged_on')
async def login():
print('Logged in!')


# On a new trade, this will be called. an EconTradeOffer.TradeOffer object will be passed in
@manager.on('new_trade')
@trade_manager.on('new_trade')
async def new_offer(trade_offer):
print(f"Got Offer: {trade_offer.tradeofferid}")


# A new confirmation (including ones that are going to be accepted automatically)
@manager.on('new_conf')
@trade_manager.on('new_conf')
async def new_conf(conf):
print(f"Got confirmation: {conf.id}")


# This is called at the end of polling
@manager.on('end_poll')
# This is called at the end of global polling
@trade_manager.on('global_end_poll')
async def poll_end():
print("Global poll ended.")


# This is called at the start of global polling
@trade_manager.on('global_start_poll')
async def poll_start():
print("Global poll started.")


# This is called at the end of trade polling
@trade_manager.on('trade_end_poll')
async def poll_end():
print("Poll ended.")
print("Trade poll ended.")


# This is called at the start of polling
@manager.on('start_poll')
# This is called at the start of trade polling
@trade_manager.on('trade_start_poll')
async def poll_start():
print("Poll started.")
print("Trade poll started.")


# This is called when there is an error in some of your code
@manager.on('error')
@trade_manager.on('error')
async def error(message):
print(f"Our code errored: {message}")


# This is called when there is an error whilst polling.
# This should be caught and polling will continue as normal
@manager.on('poll_error')
@trade_manager.on('trade_poll_error')
async def poll_error(message):
print(f"Poll error: {message}")


# This is called when a trade is accepted
@manager.on('trade_accepted')
@trade_manager.on('trade_accepted')
async def accepted_offer(trade_offer):
print(f"Accepted Offer: {trade_offer.tradeofferid}")


# This is called when a trade is declined
@manager.on('trade_declined')
@trade_manager.on('trade_declined')
async def declined_offer(trade_offer):
print(f"Declined Offer: {trade_offer.tradeofferid}")


# This is called when a trade is cancelled
@manager.on('trade_canceled')
@trade_manager.on('trade_canceled')
async def canceled_offer(trade_offer):
print(f"Canceled Offer: {trade_offer.tradeofferid}")


# This is called when a trade has expired
@manager.on('trade_expired')
@trade_manager.on('trade_expired')
async def expired_offer(trade_offer):
print(f"Expired Offer: {trade_offer.tradeofferid}")


# This is called when a trade has been countered
@manager.on('trade_countered')
@trade_manager.on('trade_countered')
async def countered_offer(trade_offer):
print(f"Countered Offer: {trade_offer.tradeofferid}")


# This is called when a trade state has changed to something unexpected
@manager.on('trade_state_changed')
@trade_manager.on('trade_state_changed')
async def changed_offer(trade_offer):
print(f"Countered Offer: {trade_offer.tradeofferid}")

# This is the basic setup for the program, and it will run forever. Currently, there is no "nice" way to end it.
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.ensure_future(manager.login(steam_cli)))
manager.run_forever()
loop.run_until_complete(asyncio.ensure_future(trade_manager.login(steam_client)))
global_manager.run_forever()
19 changes: 4 additions & 15 deletions pytrade/EconItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ class Item:

def __init__(self, data, missing=False):
"""
Args:
data:
missing:
:param data:
:param missing:
"""
self.appid = data.get('appid')
self.classid = data.get('classid')
Expand All @@ -28,8 +27,8 @@ def __init__(self, data, missing=False):
self.descriptions = data.get('descriptions', [])
self.market_hash_name = data.get('market_hash_name')
self.market_name = data.get('market_name')
self.tradable = bool(data.get('tradable')) if data.get('tradable') != None else None
self.marketable = bool(data.get('marketable')) if data.get('marketable') != None else None
self.tradable = bool(data.get('tradable')) if data.get('tradable') is not None else None
self.marketable = bool(data.get('marketable')) if data.get('marketable') is not None else None
self.market_tradable_restriction = data.get('market_tradable_restriction')
self.name_color = data.get('name_color')
self.background_color = data.get('background_color')
Expand All @@ -39,22 +38,12 @@ def __init__(self, data, missing=False):

@property
def small_image(self):
"""
Returns:
"""
if not self.icon_url:
return None
return "https://steamcommunity-a.akamaihd.net/economy/image/" + self.icon_url

@property
def large_image(self):
"""
Returns:
"""
if not self.icon_url_large:
return None
return "https://steamcommunity-a.akamaihd.net/economy/image/" + self.icon_url_large
Loading

0 comments on commit 5933ecb

Please sign in to comment.