From 93bee444941aa082487eae55b72e07618444c968 Mon Sep 17 00:00:00 2001 From: Rossen Georgiev Date: Sun, 1 May 2016 18:29:24 +0100 Subject: [PATCH] updated friends mixing * added docstring for SteamFriendlist * added 'ready' event * renamed 'get_persona_state_value' to 'get_ps' * SteamFriendlist logger's name is now based on the SteamClient instance name --- steam/client/mixins/friends.py | 68 ++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/steam/client/mixins/friends.py b/steam/client/mixins/friends.py index 2af3c6d..d05d65d 100644 --- a/steam/client/mixins/friends.py +++ b/steam/client/mixins/friends.py @@ -11,24 +11,57 @@ class Friends(object): super(Friends, self).__init__(*args, **kwargs) #: SteamFriendlist instance - self.friends = SteamFriendlist(self) + self.friends = SteamFriendlist(self, logger_name="%s.friends" % self.__class__.__name__) class SteamFriendlist(EventEmitter): - _LOG = logging.getLogger('SteamClient.friends') + """SteamFriendlist is an object that keeps state of user's friend list. + Think of it as a list of :class:`SteamUser`. + You can iterate over it, check if it contains a particular steam id, or get :class:`SteamUser` for a steamid. - def __init__(self, client): + .. note:: + persona state is not update immediatelly for new user entries + + + Event: ``ready`` - friendlist is ready to use + + Event: ``friend_invite`` - new or existing friend invite + + :param user: steam user instance + :type user: :class:`SteamUser` + + Event: ``friend_new`` - emitted upon accepting a new friend (or being accepted) + + :param user: steam user instance + :type user: :class:`SteamUser` + + + Event: ``friend_removed`` - no longer a friend (removed by either side) + + :param user: steam user instance + :type user: :class:`SteamUser` + + """ + ready = False #: indicates whether friend list is available + + def __init__(self, client, logger_name='SteamFriendList'): + self._LOG = logging.getLogger(logger_name) self._fr = {} self._steam = client self._steam.on(EMsg.ClientAddFriendResponse, self._handle_add_friend_result) self._steam.on(EMsg.ClientFriendsList, self._handle_friends_list) self._steam.on(EMsg.ClientPersonaState, self._handle_persona_state) + self._steam.on('disconnected', self._handle_disconnect) def emit(self, event, *args): if event is not None: self._LOG.debug("Emit event: %s" % repr(event)) EventEmitter.emit(self, event, *args) + def _handle_disconnect(self): + self.ready = False + self._fr.clear() + def _handle_add_friend_result(self, message): eresult = EResult(message.body.eresult) steam_id = SteamID(message.body.steam_id_added) @@ -72,6 +105,10 @@ class SteamFriendlist(EventEmitter): m.body.friends.extend(pstate_check) self._steam.send(m) + if not self.ready: + self.ready = True + self.emit('ready') + def _handle_persona_state(self, message): for friend in message.body.friends: steamid = friend.friendid @@ -81,6 +118,7 @@ class SteamFriendlist(EventEmitter): if steamid in self._fr: self._fr[steamid]._data['pstate'] = friend + self.emit('persona_state_updated', self._fr[steamid]) def __repr__(self): return "<%s %d users>" % ( @@ -143,6 +181,14 @@ class SteamUser(intBase): 'relationship': EFriendRelationship(rel) } + def __repr__(self): + return "<%s (%s) %s %s>" % ( + self.__class__.__name__, + int(self) if self.name is None else repr(self.name), + self.relationship.name, + self.state.name, + ) + @property def steamid(self): """SteamID instance @@ -159,7 +205,7 @@ class SteamUser(intBase): """ return self._data['relationship'] - def get_persona_state_value(self, field_name): + def get_ps(self, field_name): """Get a value for field in ``CMsgClientPersonaState.Friend`` :param field_name: see example list below @@ -188,7 +234,7 @@ class SteamUser(intBase): :rtype: :class:`str`, :class:`None` """ - return self.get_persona_state_value('player_name') + return self.get_ps('player_name') @property def state(self): @@ -196,7 +242,7 @@ class SteamUser(intBase): :rtype: :class:`steam.enums.common.EPersonaState` """ - state = self.get_persona_state_value('persona_state') + state = self.get_ps('persona_state') if state: return EPersonaState(state) return EPersonaState.Offline @@ -209,7 +255,7 @@ class SteamUser(intBase): :return: url to avatar :rtype: :class:`str` """ - ahash = self.get_persona_state_value('avatar_hash') + ahash = self.get_ps('avatar_hash') if ahash is None: return None @@ -222,11 +268,3 @@ class SteamUser(intBase): ahash = binascii.hexlify(persona_state_value.avatar_hash).decode('ascii') return url % (ahash[:2], ahash, sizes[size]) - - def __repr__(self): - return "<%s (%s) %s %s>" % ( - self.__class__.__name__, - int(self) if self.name is None else repr(self.name), - self.relationship.name, - self.state.name, - )