client¶
Implementation of Steam client based on gevent
Warning
steam.client
no longer patches stdlib to make it gevent cooperative.
This provides flexibility if you want to use SteamClient
with async or other modules.
If you want to monkey patch anyway use steam.monkey.patch_minimal()
Note
Additional features are located in separate submodules. All functionality from builtins
is inherited by default.
Note
Optional features are available as mixins
. This allows the client to remain light yet flexible.
-
class
steam.client.
SteamClient
¶ Bases:
steam.core.cm.CMClient
,steam.client.builtins.BuiltinBase
-
EVENT_AUTH_CODE_REQUIRED
= 'auth_code_required'¶ When either email or 2FA code is needed for login
-
EVENT_CHANNEL_SECURED
= 'channel_secured'¶
-
EVENT_CHAT_MESSAGE
= 'chat_message'¶
-
EVENT_CONNECTED
= 'connected'¶
-
EVENT_DISCONNECTED
= 'disconnected'¶
-
EVENT_EMSG
= 0¶
-
EVENT_ERROR
= 'error'¶
-
EVENT_LOGGED_ON
= 'logged_on'¶ After successful login
-
EVENT_NEW_LOGIN_KEY
= 'new_login_key'¶ After a new login key is accepted
-
EVENT_RECONNECT
= 'reconnect'¶
-
PROTOCOL_TCP
= 0¶
-
PROTOCOL_UDP
= 1¶
-
anonymous_login
()¶ Login as anonymous user
Returns: logon result, see CMsgClientLogonResponse.eresult Return type: EResult
-
auto_discovery
= True¶
-
cell_id
= 0¶
-
change_status
(**kwargs)¶ Set name, persona state, flags
Note
Changing persona state will also change
persona_state
Parameters: - persona_state (
EPersonaState
) – persona state (Online/Offline/Away/etc) - player_name (
str
) – profile name - persona_state_flags (
EPersonaStateFlag
) – persona state flags
- persona_state (
-
channel_hmac
= None¶
-
channel_key
= None¶
-
channel_secured
= False¶
-
chat_mode
= 2¶ chat mode (0=old chat, 2=new chat)
-
cli_login
(username='', password='')¶ Generates CLI prompts to complete the login process
Parameters: Returns: logon result, see CMsgClientLogonResponse.eresult
Return type: Example console output after calling
cli_login()
In [5]: client.cli_login() Steam username: myusername Password: Steam is down. Keep retrying? [y/n]: y Invalid password for 'myusername'. Enter password: Enter email code: 123 Incorrect code. Enter email code: K6VKF Out[5]: <EResult.OK: 1>
-
cm_servers
= None¶
-
connect
(*args, **kwargs)¶ Attempt to establish connection, see
CMClient.connect()
-
connected
= False¶
-
count_listeners
(event)¶ Returns a count of how many listeners are registered registed for a specific event
Parameters: event – event identifier Returns: number of listeners Return type: int
-
credential_location
= None¶ location for sentry
-
current_games_played
= []¶
-
current_jobid
= 0¶
-
current_server_addr
= None¶
-
disconnect
(*args, **kwargs)¶ Close connection, see
CMClient.disconnect()
-
emit
(event, *args)¶ Emit event with some arguments
Parameters: - event (any type) – event identifier
- args – any or no arguments
-
games_played
(app_ids)¶ Set the apps being played by the user
Parameters: app_ids ( list
) – a list of application idsThese app ids will be recorded in
current_games_played
.
-
get_access_tokens
(app_ids=[], package_ids=[])¶ Get access tokens
Parameters: Returns: dict with
apps
andpackages
containing their access tokens, see example belowReturn type: dict
,None
{'apps': {123: 8888888886, ...}, 'packages': {456: 6666666666, ...} }
-
get_app_ticket
(app_id)¶ Get app ownership ticket
Parameters: app_id ( int
) – app idReturns: CMsgClientGetAppOwnershipTicketResponse Return type: proto message
-
get_cdn_auth_token
(depot_id, hostname)¶ Get CDN authentication token
Note
This token is no longer needed for access to CDN files
Parameters: Returns: Return type: proto message
-
get_changes_since
(change_number, app_changes=True, package_changes=False)¶ Get changes since a change number
Parameters: Returns: Return type: proto message instance, or
None
on timeout
-
get_depot_key
(app_id, depot_id)¶ Get depot decryption key
Parameters: Returns: Return type: proto message
-
get_encrypted_app_ticket
(app_id, userdata)¶ Gets the encrypted app ticket :param app_id: app id :type app_id:
int
:param userdata: userdata :type userdata:bytes
:return: EncryptedAppTicket <https://github.com/ValvePython/steam/blob/39627fe883feeed2206016bacd92cf0e4580ead6/protobufs/encrypted_app_ticket.proto>_ :rtype: proto message
-
get_leaderboard
(app_id, name)¶ New in version 0.8.2.
Find a leaderboard
Parameters: Returns: leaderboard instance
Return type: SteamLeaderboard
Raises: LookupError
on message timeout or error
-
get_player_count
(app_id, timeout=5)¶ Get numbers of players for app id
Parameters: app_id ( int
) – app idReturns: number of players Return type: int
,EResult
-
get_product_info
(apps=[], packages=[], meta_data_only=False, raw=False, auto_access_tokens=True, timeout=15)¶ Get product info for apps and packages
Parameters: - apps (
list
) – items in the list should be either justapp_id
, ordict
- packages (
list
) – items in the list should be either justpackage_id
, ordict
- meta_data_only (
bool
) – only meta data will be returned in the reponse (e.g. change number, missing_token, sha1) - raw (
bool
) – Data buffer for each app is returned as bytes in its’ original form. Apps buffer is text VDF, and package buffer is binary VDF - auto_access_token (
bool
) – automatically request and fill access tokens
Returns: dict with
apps
andpackages
containing their info, see example belowReturn type: dict
,None
{'apps': {570: {...}, ...}, 'packages': {123: {...}, ...} }
Access token is needed to access full information for certain apps, and also package info. Each app and package has its’ own access token. If a token is required then
_missing_token=True
in the response.App access tokens are obtained by calling
get_access_tokens()
, and are returned only when the account has a license for the specified app. Example code:result = client.get_product_info(apps=[123]) if result['apps'][123]['_missing_token']: tokens = client.get_access_token(apps=[123]) result = client.get_product_info(apps=[{'appid': 123, 'access_token': tokens['apps'][123] }])
Note
It is best to just request access token for all apps, before sending a product info request.
Package tokens are located in the account license list. See
licenses
result = client.get_product_info(packages=[{'packageid': 123, 'access_token': client.licenses[123].access_token, }])
- apps (
-
get_sentry
(username)¶ Returns contents of sentry file for the given username
Note
returns
None
ifcredential_location
is not set, or file is not found/inaccessibleParameters: username (str) – username Returns: sentry file contents, or None
Return type: bytes
,None
-
get_user
(steam_id, fetch_persona_state=True)¶ Get
SteamUser
instance forsteam id
Parameters: Returns: SteamUser instance
Return type:
-
get_web_session
(language='english')¶ Get a
requests.Session
that is ready for useNote
Auth cookies will only be send to
(help|store).steampowered.com
andsteamcommunity.com
domainsNote
The session is valid only while
SteamClient
instance is logged on.Parameters: language ( str
) – localization language for steam pagesReturns: authenticated Session ready for use Return type: requests.Session
,None
Get web authentication cookies via WebAPI’s
AuthenticateUser
Note
The cookies are valid only while
SteamClient
instance is logged on.Returns: dict with authentication cookies Return type: dict
,None
-
idle
()¶ Yeild in the current greenlet and let other greenlets run
-
licenses
= None¶
-
logged_on
= None¶ indicates logged on status. Listen to
logged_on
when change toTrue
-
login
(username, password='', login_key=None, auth_code=None, two_factor_code=None, login_id=None)¶ Login as a specific user
Parameters: Returns: logon result, see CMsgClientLogonResponse.eresult
Return type: Note
Failure to login will result in the server dropping the connection,
error
event is firedauth_code_required
event is fired when 2FA or Email code is needed. Here is example code of how to handle the situation.@steamclient.on(steamclient.EVENT_AUTH_CODE_REQUIRED) def auth_code_prompt(is_2fa, code_mismatch): if is_2fa: code = input("Enter 2FA Code: ") steamclient.login(username, password, two_factor_code=code) else: code = input("Enter Email Code: ") steamclient.login(username, password, auth_code=code)
Codes are required every time a user logins if sentry is not setup. See
set_credential_location()
-
login_key
= None¶ can be used for subsequent logins (no 2FA code will be required)
-
logout
()¶ Logout from steam. Doesn’t nothing if not logged on.
Note
The server will drop the connection immediatelly upon logout.
-
on
(event, callback=None, once=False)¶ Registers a callback for the specified event
Parameters: - event – event name
- callback – callback function
Can be as function decorator if only
event
param is specified.@instaceOfSomeClass.on("some event") def handle_event(): pass instaceOfSomeClass.on("some event", handle_event)
To listen for any event, use
None
as event identifier.
-
once
(event, callback=None)¶ Register a callback, but call it exactly one time
See
eventemitter.EventEmitter.on()
-
persona_state
= 1¶
-
reconnect
(maxdelay=30, retry=0)¶ Implements explonential backoff delay before attempting to connect. It is otherwise identical to calling
CMClient.connect()
. The delay is reset upon a successful login.Parameters: - maxdelay (
int
) – maximum delay in seconds before connect (0-120s) - retry (
int
) – seeCMClient.connect()
Returns: successful connection
Return type: - maxdelay (
-
register_product_key
(key)¶ Register/Redeem a CD-Key
Parameters: key ( str
) – CD-KeyReturns: format (eresult, result_details, receipt_info)
Return type: tuple
Example
receipt_info
:{'BasePrice': 0, 'CurrencyCode': 0, 'ErrorHeadline': '', 'ErrorLinkText': '', 'ErrorLinkURL': '', 'ErrorString': '', 'LineItemCount': 1, 'PaymentMethod': 1, 'PurchaseStatus': 1, 'ResultDetail': 0, 'Shipping': 0, 'Tax': 0, 'TotalDiscount': 0, 'TransactionID': UINT_64(111111111111111111), 'TransactionTime': 1473000000, 'lineitems': {'0': {'ItemDescription': 'Half-Life 3', 'TransactionID': UINT_64(11111111111111111), 'packageid': 1234}}, 'packageid': -1}
-
relogin
()¶ Login without needing credentials, essentially remember password. The
login_key
is acquired after successful login and it will be automatically acknowledged. Listen for thenew_login_key
event. After that the client can relogin using this method.Note
Only works when
relogin_available
isTrue
.if client.relogin_available: client.relogin() else: client.login(user, pass)
Returns: login result Return type: EResult
-
remove_all_listeners
(event=None)¶ Removes all registered callbacks, or all registered callbacks for a specific event
Parameters: event – event identifier
-
remove_listener
(event, callback)¶ Removes callback for the specified event
Parameters: - event – event identifier
- callback (function, method or
gevent.event.AsyncResult
) – callback reference
-
request_free_license
(app_ids)¶ Request license for free app(s)
Parameters: app_ids ( list
) – list of app idsReturns: format ( EResult
, result_details, receipt_info)Return type: tuple
-
request_persona_state
(steam_ids, state_flags=863)¶ Request persona state data
Parameters: - steam_ids (
list
) – list of steam ids - state_flags (
EClientPersonaStateFlag
) – client state flags
- steam_ids (
-
run_forever
()¶ Transfer control the gevent event loop
This is useful when the application is setup and ment to run for a long time
-
send
(message, body_params=None)¶ Send a message to CM
Parameters:
-
send_job
(message, body_params=None)¶ Send a message as a job
Note
Not all messages are jobs, you’ll have to find out which are which
Parameters: Returns: jobid
event identifierReturn type: To catch the response just listen for the
jobid
event.jobid = steamclient.send_job(my_message) resp = steamclient.wait_event(jobid, timeout=15) if resp: (message,) = resp
-
send_job_and_wait
(message, body_params=None, timeout=None, raises=False)¶ Send a message as a job and wait for the response.
Note
Not all messages are jobs, you’ll have to find out which are which
Parameters: Returns: response proto message
Return type: Raises:
-
send_message_and_wait
(message, response_emsg, body_params=None, timeout=None, raises=False)¶ Send a message to CM and wait for a defined answer.
Parameters: Returns: response proto message
Return type: Raises:
-
send_um
(method_name, params=None)¶ Send service method request
Parameters: Returns: job_id
identifierReturn type: Listen for
jobid
on this object to catch the response.
-
send_um_and_wait
(method_name, params=None, timeout=10, raises=False)¶ Send service method request and wait for response
Parameters: - method_name (
str
) – method name (e.g.Player.GetGameBadgeLevels#1
) - params (
dict
) – message parameters - timeout (
int
) – (optional) seconds to wait - raises (
bool
) – (optional) On timeout ifFalse
returnNone
, else raisegevent.Timeout
Returns: response message
Return type: proto message instance
Raises: - method_name (
-
session_id
= None¶
-
set_credential_location
(path)¶ Sets folder location for sentry files
Needs to be set explicitly for sentries to be created.
-
set_ui_mode
(uimode)¶ Set UI mode. Show little icon next to name in friend list. (e.g phone, controller, other)
Parameters: uimode ( EClientUIMode
) – UI mode integerThese app ids will be recorded in
current_games_played
.
-
sleep
(seconds)¶ Yeild and sleep N seconds. Allows other greenlets to run
-
steam_id
= SteamID(id=0, type='Invalid', universe='Invalid', instance=0)¶
-
store_sentry
(username, sentry_bytes)¶ Store sentry bytes under a username
Parameters: username (str) – username Returns: Whenver the operation succeed Return type: bool
-
user
= None¶
-
username
= None¶ username when logged on
-
verbose_debug
= False¶
-
wait_event
(event, timeout=None, raises=False)¶ Blocks until an event and returns the results
Parameters: Returns: returns event arguments in tuple
Return type: None
, ortuple
Raises: gevent.Timeout
Handling timeout
args = ee.wait_event('my event', timeout=5) if args is None: print "Timeout!"
-
wait_msg
(event, timeout=None, raises=None)¶ Wait for a message, similiar to
wait_event()
Parameters: - event (
EMsg
orstr
) – event id - timeout (
int
) – seconds to wait before timeout - raises (
bool
) – On timeout whenFalse
returnsNone
, else raisegevent.Timeout
Returns: returns a message or
None
Return type: None
, or proto messageRaises: - event (
-
-
steam.client.
random
() → x in the interval [0, 1).¶