pythonhacktoberfeststeamauthenticationauthenticatorsteam-authenticatorsteam-clientsteam-guard-codessteam-websteamworksvalvewebapi
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.1 KiB
144 lines
4.1 KiB
import logging
|
|
import gevent
|
|
from eventemitter import EventEmitter
|
|
from steam.enums.emsg import EMsg
|
|
from steam.enums import EResult
|
|
from steam.core.msg import MsgProto
|
|
from steam.core.cm import CMClient
|
|
from steam import SteamID
|
|
from steam.client.jobs import JobManager
|
|
|
|
logger = logging.getLogger("SteamClient")
|
|
|
|
|
|
class SteamClient(EventEmitter):
|
|
def __init__(self):
|
|
self.cm = CMClient()
|
|
self.job = JobManager(self)
|
|
|
|
# re-emit all events from CMClient
|
|
self.cm.on(None, self.emit)
|
|
|
|
# register listners
|
|
self.on(EMsg.ClientLogOnResponse, self._handle_logon)
|
|
self.on("disconnected", self._handle_disconnect)
|
|
|
|
self.logged_on = False
|
|
|
|
def __repr__(self):
|
|
return "<%s() %s>" % (self.__class__.__name__,
|
|
'online' if self.connected else 'offline',
|
|
)
|
|
|
|
def emit(self, event, *args):
|
|
if event is not None:
|
|
logger.debug("Emit event: %s" % repr(event))
|
|
super(SteamClient, self).emit(event, *args)
|
|
|
|
@property
|
|
def steam_id(self):
|
|
return self.cm.steam_id
|
|
@property
|
|
|
|
def connected(self):
|
|
return self.cm.connected
|
|
|
|
def connect(self):
|
|
self.cm.connect()
|
|
|
|
def disconnect(self):
|
|
self.cm.disconnect()
|
|
|
|
def _handle_disconnect(self):
|
|
self.logged_on = False
|
|
|
|
def _handle_logon(self, msg):
|
|
result = EResult(msg.body.eresult)
|
|
|
|
if result == EResult.OK:
|
|
self.logged_on = True
|
|
self.emit("logged_on")
|
|
return
|
|
|
|
# CM kills the connection on error anyway
|
|
self.disconnect()
|
|
|
|
if result in (EResult.AccountLogonDenied,
|
|
EResult.AccountLoginDeniedNeedTwoFactor,
|
|
EResult.TwoFactorCodeMismatch,
|
|
):
|
|
self.emit("auth_code_required", result)
|
|
else:
|
|
self.emit("error", result)
|
|
|
|
def send(self, message):
|
|
if not self.connected:
|
|
raise RuntimeError("Cannot send message while not connected")
|
|
|
|
self.cm.send_message(message)
|
|
|
|
def _pre_login(self):
|
|
if self.logged_on:
|
|
logger.debug("Trying to login while logged on???")
|
|
raise RuntimeError("Already logged on")
|
|
|
|
if not self.connected:
|
|
self.connect()
|
|
|
|
if not self.cm.channel_secured:
|
|
self.wait_event("channel_secured")
|
|
|
|
def anonymous_login(self):
|
|
logger.debug("Attempting Anonymous login")
|
|
|
|
self._pre_login()
|
|
|
|
message = MsgProto(EMsg.ClientLogon)
|
|
message.header.steamid = SteamID(type='AnonUser', universe='Public')
|
|
message.body.protocol_version = 65575
|
|
self.send(message)
|
|
|
|
def login(self, username, password, auth_code=None, two_factor_code=None, remember=False):
|
|
logger.debug("Attempting login")
|
|
|
|
self._pre_login()
|
|
|
|
message = MsgProto(EMsg.ClientLogon)
|
|
message.header.steamid = SteamID(type='Individual', universe='Public')
|
|
message.body.protocol_version = 65575
|
|
message.body.client_package_version = 1771
|
|
message.body.client_os_type = 13
|
|
message.body.client_language = "english"
|
|
|
|
message.body.account_name = username
|
|
message.body.password = password
|
|
|
|
if auth_code:
|
|
message.body.auth_code = auth_code
|
|
if two_factor_code:
|
|
message.body.two_factor_code = two_factor_code
|
|
|
|
self.send(message)
|
|
|
|
def logout(self):
|
|
if self.logged_on:
|
|
self.logged_on = False
|
|
self.send(MsgProto(EMsg.ClientLogOff))
|
|
self.wait_event('disconnected')
|
|
|
|
def run_forever(self):
|
|
while True:
|
|
gevent.sleep(300)
|
|
|
|
def games_played(self, app_ids):
|
|
if not isinstance(app_ids, list):
|
|
raise ValueError("Expected app_ids to be of type list")
|
|
|
|
app_ids = map(int, app_ids)
|
|
|
|
message = MsgProto(EMsg.ClientGamesPlayed)
|
|
GamePlayed = message.body.GamePlayed
|
|
|
|
message.body.games_played.extend(map(lambda x: GamePlayed(game_id=x), app_ids))
|
|
|
|
self.send(message)
|
|
|