Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add check in setup.py #416

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pythonpr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8]
python-version: ["3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Table of Content
Installation
============

Requires python 3.8 at least
Requires python 3.12 at least
```
pip install steampy
```
Expand Down
2 changes: 1 addition & 1 deletion examples/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@

# Dump all the info to inventory_(app_id)_(context_id).json file
print('Saving information...')
with Path(f'inventory_{app_id}_{context_id}.json').open('w') as file:
with Path(f'inventory_{app_id}_{context_id}.json').open('w', encoding='utf-8') as file:
json.dump(item_amounts, file)
print(f'Done! Saved to file: inventory_{app_id}_{context_id}.json')
8 changes: 6 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import sys

from setuptools import setup

if sys.version_info < (3, 12):
sys.exit("Python < 3.12 is not supported")

version = '1.1.2'

setup(
name='steampy',
packages=['steampy', 'test', 'examples' ],
packages=['steampy', 'test', 'examples'],
version=version,
description='A Steam lib for trade automation',
author='Michał Bukowski',
author_email='gigibukson@gmail.com',
license='MIT',
url='https://github.com/bukson/steampy',
download_url='https://github.com/bukson/steampy/tarball/' + version,
keywords=['steam', 'trade' ],
keywords=['steam', 'trade'],
classifiers=[],
install_requires=[
"requests",
Expand Down
7 changes: 3 additions & 4 deletions steampy/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,11 @@ def get_steam_id(self) -> int:
response = self._session.get(url)
if steam_id := re.search(r'g_steamID = "(\d+)";', response.text):
return int(steam_id.group(1))
else:
raise ValueError(f'Invalid steam_id: {steam_id}')
raise ValueError(f'Invalid steam_id: {steam_id}')

def login(self, username: str | None = None, password: str | None = None, steam_guard: str | None = None) -> None:
invalid_client_credentials_is_present = None in (self.username, self._password, self.steam_guard_string)
invalid_login_credentials_is_present = None in (username, password, steam_guard)
invalid_client_credentials_is_present = None in {self.username, self._password, self.steam_guard_string}
invalid_login_credentials_is_present = None in {username, password, steam_guard}

if invalid_client_credentials_is_present and invalid_login_credentials_is_present:
raise InvalidCredentials(
Expand Down
3 changes: 1 addition & 2 deletions steampy/confirmation.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ def _get_confirmations(self) -> list[Confirmation]:
nonce = conf['nonce']
confirmations.append(Confirmation(data_confid, nonce))
return confirmations
else:
raise ConfirmationExpected
raise ConfirmationExpected

def _fetch_confirmations_page(self) -> requests.Response:
tag = Tag.CONF.value
Expand Down
4 changes: 3 additions & 1 deletion steampy/guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ def load_steam_guard(steam_guard: str) -> dict[str, str]:
Arguments:
steam_guard (str): If this string is a path to a file, then its contents will be parsed as a json data.
Otherwise, the string will be parsed as a json data.

Returns:
Dict[str, str]: Parsed json data as a dictionary of strings (both key and value).

"""
if Path(steam_guard).is_file():
with Path(steam_guard).open() as f:
with Path(steam_guard).open(encoding='utf-8') as f:
return json.loads(f.read(), parse_int=str)
else:
return json.loads(steam_guard, parse_int=str)
Expand Down
15 changes: 7 additions & 8 deletions steampy/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ def _api_call(self, method: str, service: str, endpoint: str, version: str = 'v1
headers = {'Referer': f'{SteamUrl.COMMUNITY_URL}/', 'Origin': SteamUrl.COMMUNITY_URL}
if method.upper() == 'GET':
return self.session.get(url, params=params, headers=headers)
elif method.upper() == 'POST':
if method.upper() == 'POST':
return self.session.post(url, data=params, headers=headers)
else:
raise ValueError('Method must be either GET or POST')
raise ValueError('Method must be either GET or POST')

def login(self) -> Session:
login_response = self._send_login_request()
Expand All @@ -53,20 +52,20 @@ def _send_login_request(self) -> Response:
request_data = self._prepare_login_request_data(encrypted_password, rsa_timestamp)
return self._api_call('POST', 'IAuthenticationService', 'BeginAuthSessionViaCredentials', params=request_data)

def set_sessionid_cookies(self):
def set_sessionid_cookies(self) -> None:
community_domain = SteamUrl.COMMUNITY_URL[8:]
store_domain = SteamUrl.STORE_URL[8:]
community_cookie_dic = self.session.cookies.get_dict(domain = community_domain)
store_cookie_dic = self.session.cookies.get_dict(domain = store_domain)
community_cookie_dic = self.session.cookies.get_dict(domain=community_domain)
store_cookie_dic = self.session.cookies.get_dict(domain=store_domain)
for name in ('steamLoginSecure', 'sessionid', 'steamRefresh_steam', 'steamCountry'):
cookie = self.session.cookies.get_dict()[name]
if name in ["sessionid", "steamLoginSecure"]:
if name in {"sessionid", "steamLoginSecure"}:
community_cookie = create_cookie(name, community_cookie_dic[name], community_domain)
else:
community_cookie = create_cookie(name, cookie, community_domain)

self.session.cookies.set(**community_cookie)
self.session.cookies.set(**store_cookie)
self.session.cookies.set(**store_cookie)

def _fetch_rsa_params(self, current_number_of_repetitions: int = 0) -> dict:
self.session.post(SteamUrl.COMMUNITY_URL)
Expand Down
1 change: 1 addition & 0 deletions steampy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class PredefinedOptions(NamedTuple):
app_id: str
context_id: str


class GameOptions:
STEAM = PredefinedOptions('753', '6')
DOTA2 = PredefinedOptions('570', '2')
Expand Down
9 changes: 6 additions & 3 deletions steampy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ def login_required(func):
def func_wrapper(self, *args, **kwargs):
if not self.was_login_executed:
raise LoginRequired('Use login method first')
else:
return func(self, *args, **kwargs)
return func(self, *args, **kwargs)

return func_wrapper

Expand Down Expand Up @@ -67,8 +66,10 @@ def calculate_gross_price(price_net: Decimal, publisher_fee: Decimal, steam_fee:
fraud incidents and cover the cost of development of this and future Steam economy features. The fee is
currently `5%` (with a minimum fee of `$0.01`). This fee may be increased or decreased by Steam in the
future.

Returns:
Decimal: Gross price (including fees) - the amount that the buyer pays during a market transaction

"""
price_net *= 100
steam_fee_amount = int(math.floor(max(price_net * steam_fee, 1)))
Expand All @@ -88,8 +89,10 @@ def calculate_net_price(price_gross: Decimal, publisher_fee: Decimal, steam_fee:
fraud incidents and cover the cost of development of this and future Steam economy features. The fee is
currently `5%` (with a minimum fee of `$0.01`). This fee may be increased or decreased by Steam in the
future.

Returns:
Decimal: Net price (without fees) - the amount that the seller receives after a market transaction.

"""
price_gross *= 100
estimated_net_price = Decimal(int(price_gross / (steam_fee + publisher_fee + 1)))
Expand Down Expand Up @@ -244,7 +247,7 @@ def get_key_value_from_url(url: str, key: str, case_sensitive: bool = True) -> s

def load_credentials():
dirname = Path(__file__).resolve().parent
with Path(f'{dirname}/../secrets/credentials.pwd').open() as f:
with Path(f'{dirname}/../secrets/credentials.pwd').open(encoding='utf-8') as f:
return [Credentials(line.split()[0], line.split()[1], line.split()[2]) for line in f]


Expand Down
42 changes: 21 additions & 21 deletions test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,38 @@
@unittest.skip('Requires secrets/Steamguard.txt')
class TestSteamClient(TestCase):
@classmethod
def setUpClass(cls):
def setUpClass(cls) -> None:
cls.credentials = load_credentials()[0]
dirname = Path(__file__).resolve().parent
cls.steam_guard_file = f'{dirname}/../secrets/Steamguard.txt'

def test_get_steam_id(self):
def test_get_steam_id(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
assert client.get_steam_id() == int(self.steam_guard_file['Session']['SteamID'])

def test_login(self):
def test_login(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)

def test_is_session_alive(self):
def test_is_session_alive(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
assert client.is_session_alive()

def test_logout(self):
def test_logout(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
assert client.is_session_alive()
client.logout()

def test_client_with_statement(self):
def test_client_with_statement(self) -> None:
with SteamClient(
self.credentials.api_key, self.credentials.login, self.credentials.password, self.steam_guard_file,
) as client:
assert client.is_session_alive()

def test_send_offer_without_sessionid_cookie(self):
def test_send_offer_without_sessionid_cookie(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
client._session.cookies.set('sessionid', None, domain='steamcommunity.com')
Expand All @@ -55,70 +55,70 @@ def test_send_offer_without_sessionid_cookie(self):
trade_offer_url = ''
self.assertRaises(AttributeError, lambda: client.make_offer_with_url([my_asset], [], trade_offer_url, 'TEST'))

def test_sessionid_cookie(self):
def test_sessionid_cookie(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
community_cookies = client._session.cookies.get_dict('steamcommunity.com')
store_cookies = client._session.cookies.get_dict('store.steampowered.com')
assert 'sessionid' in community_cookies
assert 'sessionid' in store_cookies

def test_get_my_inventory(self):
def test_get_my_inventory(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
inventory = client.get_my_inventory(GameOptions.CS)
assert inventory is not None

def test_get_partner_inventory(self):
def test_get_partner_inventory(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
partner_id = ''
game = GameOptions.TF2
inventory = client.get_partner_inventory(partner_id, game)
assert inventory is not None

def test_get_trade_offers_summary(self):
def test_get_trade_offers_summary(self) -> None:
client = SteamClient(self.credentials.api_key)
summary = client.get_trade_offers_summary()
assert summary is not None

def test_get_trade_offers(self):
def test_get_trade_offers(self) -> None:
client = SteamClient(self.credentials.api_key)
offers = client.get_trade_offers()
assert offers is not None

def test_get_trade_offer(self):
def test_get_trade_offer(self) -> None:
client = SteamClient(self.credentials.api_key)
trade_offer_id = '1442685162'
offer = client.get_trade_offer(trade_offer_id)
assert offer is not None

def test_accept_trade_offer_without_login(self):
def test_accept_trade_offer_without_login(self) -> None:
client = SteamClient(self.credentials.api_key)
self.assertRaises(LoginRequired, client.accept_trade_offer, 'id')

def test_accept_trade_offer(self):
def test_accept_trade_offer(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
trade_offer_id = '1451378159'
response_dict = client.accept_trade_offer(trade_offer_id)
assert response_dict is not None

def test_decline_trade_offer(self):
def test_decline_trade_offer(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
trade_offer_id = '1449530707'
response_dict = client.decline_trade_offer(trade_offer_id)
assert response_dict['response'] == {}

def test_cancel_trade_offer(self):
def test_cancel_trade_offer(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
trade_offer_id = '1450637835'
response_dict = client.cancel_trade_offer(trade_offer_id)
assert response_dict['response'] == {}

def test_make_offer(self):
def test_make_offer(self) -> None:
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
partner_id = ''
Expand All @@ -133,7 +133,7 @@ def test_make_offer(self):
assert response is not None
assert 'tradeofferid' in response

def test_make_offer_url(self):
def test_make_offer_url(self) -> None:
partner_account_id = '32384925'
partner_token = '7vqRtBpC'
sample_trade_url = (
Expand All @@ -154,15 +154,15 @@ def test_make_offer_url(self):
assert response is not None
assert 'tradeofferid' in response

def test_get_escrow_duration(self):
def test_get_escrow_duration(self) -> None:
# A sample trade URL with escrow time of 15 days cause mobile auth not added
sample_trade_url = 'https://steamcommunity.com/tradeoffer/new/?partner=314218906&token=sgA4FdNm'
client = SteamClient(self.credentials.api_key)
client.login(self.credentials.login, self.credentials.password, self.steam_guard_file)
response = client.get_escrow_duration(sample_trade_url)
assert response == 15

def test_get_wallet_balance(self):
def test_get_wallet_balance(self) -> None:
with SteamClient(
self.credentials.api_key, self.credentials.login, self.credentials.password, self.steam_guard_file,
) as client:
Expand Down
10 changes: 5 additions & 5 deletions test/test_guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@

class TestGuard(TestCase):
@classmethod
def setUpClass(cls):
def setUpClass(cls) -> None:
cls.shared_secret = b64encode(b'1234567890abcdefghij')
cls.identity_secret = b64encode(b'abcdefghijklmnoprstu')

def test_one_time_code(self):
def test_one_time_code(self) -> None:
timestamp = 1469184207
code = guard.generate_one_time_code(self.shared_secret, timestamp)
assert code == 'P2QJN'

def test_confirmation_key(self):
def test_confirmation_key(self) -> None:
timestamp = 1470838334
confirmation_key = guard.generate_confirmation_key(self.identity_secret, Tag.CONF.value, timestamp)
assert confirmation_key == b'pWqjnkcwqni+t/n+5xXaEa0SGeA='

def test_generate_device_id(self):
def test_generate_device_id(self) -> None:
steam_id = '12341234123412345'
device_id = guard.generate_device_id(steam_id)
assert device_id == 'android:677cf5aa-3300-7807-d1e2-c408142742e2'

def test_load_steam_guard(self):
def test_load_steam_guard(self) -> None:
expected_keys = ('steamid', 'shared_secret', 'identity_secret')

guard_json_str = '{"steamid": 12345678, "shared_secret": "SHARED_SECRET", "identity_secret": "IDENTITY_SECRET"}'
Expand Down
Loading
Loading