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.
 
 

148 lines
5.3 KiB

from weakref import WeakValueDictionary
from steam.client.user import SteamUser
from steam.enums import EPersonaState, EChatEntryType, EType
from steam.enums.emsg import EMsg
from steam.core.msg import MsgProto
from steam.util import proto_fill_from_dict
class User(object):
EVENT_CHAT_MESSAGE = 'chat_message'
"""On new private chat message
:param user: steam user
:type user: :class:`.SteamUser`
:param message: message text
:type message: str
"""
persona_state = EPersonaState.Online #: current persona state
user = None #: :class:`.SteamUser` instance once logged on
current_games_played = [] #: :class:`list` of app ids currently being played
def __init__(self, *args, **kwargs):
super(User, self).__init__(*args, **kwargs)
self._user_cache = WeakValueDictionary()
self.on(self.EVENT_DISCONNECTED, self.__handle_disconnect)
self.on(self.EVENT_LOGGED_ON, self.__handle_set_persona)
self.on(EMsg.ClientPersonaState, self.__handle_persona_state)
self.on(EMsg.ClientFriendMsgIncoming, self.__handle_message_incoming)
self.on("FriendMessagesClient.IncomingMessage#1", self.__handle_message_incoming2)
def __handle_message_incoming(self, msg):
# old chat
if msg.body.chat_entry_type == EChatEntryType.ChatMsg:
user = self.get_user(msg.body.steamid_from)
self.emit("chat_message", user, msg.body.message.decode('utf-8'))
def __handle_message_incoming2(self, msg):
# new chat
if msg.body.chat_entry_type == EChatEntryType.ChatMsg:
user = self.get_user(msg.body.steamid_friend)
self.emit("chat_message", user, msg.body.message)
def __handle_disconnect(self):
self.user = None
self.current_games_played = []
def __handle_set_persona(self):
self.user = self.get_user(self.steam_id, False)
if self.steam_id.type == EType.Individual and self.persona_state != EPersonaState.Offline:
self.change_status(persona_state=self.persona_state)
def __handle_persona_state(self, message):
for friend in message.body.friends:
steamid = friend.friendid
if steamid in self._user_cache:
suser = self._user_cache[steamid]
suser._pstate = friend
suser._pstate_ready.set()
def change_status(self, **kwargs):
"""
Set name, persona state, flags
.. note::
Changing persona state will also change :attr:`persona_state`
:param persona_state: persona state (Online/Offline/Away/etc)
:type persona_state: :class:`.EPersonaState`
:param player_name: profile name
:type player_name: :class:`str`
:param persona_state_flags: persona state flags
:type persona_state_flags: :class:`.EPersonaStateFlag`
"""
if not kwargs: return
self.persona_state = kwargs.get('persona_state', self.persona_state)
message = MsgProto(EMsg.ClientChangeStatus)
proto_fill_from_dict(message.body, kwargs)
self.send(message)
def request_persona_state(self, steam_ids, state_flags=863):
"""Request persona state data
:param steam_ids: list of steam ids
:type steam_ids: :class:`list`
:param state_flags: client state flags
:type state_flags: :class:`.EClientPersonaStateFlag`
"""
m = MsgProto(EMsg.ClientRequestFriendData)
m.body.persona_state_requested = state_flags
m.body.friends.extend(steam_ids)
self.send(m)
def get_user(self, steam_id, fetch_persona_state=True):
"""Get :class:`.SteamUser` instance for ``steam id``
:param steam_id: steam id
:type steam_id: :class:`int`, :class:`.SteamID`
:param fetch_persona_state: whether to request person state when necessary
:type fetch_persona_state: :class:`bool`
:return: SteamUser instance
:rtype: :class:`.SteamUser`
"""
steam_id = int(steam_id)
suser = self._user_cache.get(steam_id, None)
if suser is None:
suser = SteamUser(steam_id, self)
self._user_cache[steam_id] = suser
if fetch_persona_state:
self.request_persona_state([steam_id])
return suser
def games_played(self, app_ids):
"""
Set the apps being played by the user
:param app_ids: a list of application ids
:type app_ids: :class:`list`
These app ids will be recorded in :attr:`current_games_played`.
"""
if not isinstance(app_ids, list):
raise ValueError("Expected app_ids to be of type list")
self.current_games_played = app_ids = list(map(int, app_ids))
self.send(MsgProto(EMsg.ClientGamesPlayed),
{'games_played': [{'game_id': app_id} for app_id in app_ids]}
)
def set_ui_mode(self, uimode):
"""
Set UI mode. Show little icon next to name in friend list. (e.g phone, controller, other)
:param uimode: UI mode integer
:type uimode: :class:`EClientUIMode`
These app ids will be recorded in :attr:`current_games_played`.
"""
self.send(MsgProto(EMsg.ClientCurrentUIMode), {'uimode': EClientUIMode(uimode)})