2 SleekXMPP: The Sleek XMPP Library
3 Copyright (C) 2010 Nathanael C. Fritz
4 This file is part of SleekXMPP.
6 See the file LICENSE for copying permission.
9 from sleekxmpp
.stanza
import Presence
10 from sleekxmpp
.xmlstream
import JID
11 from sleekxmpp
.roster
import RosterNode
17 SleekXMPP's roster manager.
19 The roster is divided into "nodes", where each node is responsible
20 for a single JID. While the distinction is not strictly necessary
21 for client connections, it is a necessity for components that use
24 Rosters may be stored and persisted in an external datastore. An
25 interface object to the datastore that loads and saves roster items may
26 be provided. See the documentation for the RosterItem class for the
27 methods that the datastore interface object must provide.
30 xmpp -- The main SleekXMPP instance.
31 db -- Optional interface object to an external datastore.
32 auto_authorize -- Default auto_authorize value for new roster nodes.
34 auto_subscribe -- Default auto_subscribe value for new roster nodes.
38 add -- Create a new roster node for a JID.
39 send_presence -- Shortcut for sending a presence stanza.
42 def __init__(self
, xmpp
, db
=None):
47 xmpp -- The main SleekXMPP instance.
48 db -- Optional interface object to a datastore.
52 self
._auto
_authorize
= True
53 self
._auto
_subscribe
= True
57 for node
in self
.db
.entries(None, {}):
60 self
.xmpp
.add_filter('out', self
._save
_last
_status
)
62 def _save_last_status(self
, stanza
):
64 if isinstance(stanza
, Presence
):
65 sfrom
= stanza
['from'].full
66 sto
= stanza
['to'].full
69 sfrom
= self
.xmpp
.boundjid
71 if stanza
['type'] in stanza
.showtypes
or \
72 stanza
['type'] in ('available', 'unavailable'):
74 self
[sfrom
][sto
].last_status
= stanza
76 self
[sfrom
].last_status
= stanza
77 with self
[sfrom
]._last
_status
_lock
:
78 for jid
in self
[sfrom
]:
79 self
[sfrom
][jid
].last_status
= None
81 if not self
.xmpp
.sentpresence
:
82 self
.xmpp
.event('sent_presence')
83 self
.xmpp
.sentpresence
= True
87 def __getitem__(self
, key
):
89 Return the roster node for a JID.
91 A new roster node will be created if one
92 does not already exist.
95 key -- Return the roster for this JID.
98 key
= self
.xmpp
.boundjid
99 if not isinstance(key
, JID
):
103 if key
not in self
._rosters
:
105 self
._rosters
[key
].auto_authorize
= self
.auto_authorize
106 self
._rosters
[key
].auto_subscribe
= self
.auto_subscribe
107 return self
._rosters
[key
]
110 """Return the JIDs managed by the roster."""
111 return self
._rosters
.keys()
114 """Iterate over the roster nodes."""
115 return self
._rosters
.__iter
__()
119 Add a new roster node for the given JID.
122 node -- The JID for the new roster node.
124 if not isinstance(node
, JID
):
128 if node
not in self
._rosters
:
129 self
._rosters
[node
] = RosterNode(self
.xmpp
, node
, self
.db
)
131 def set_backend(self
, db
=None, save
=True):
133 Set the datastore interface object for the roster.
136 db -- The new datastore interface.
137 save -- If True, save the existing state to the new
138 backend datastore. Defaults to True.
141 existing_entries
= set(self
._rosters
)
142 new_entries
= set(self
.db
.entries(None, {}))
144 for node
in existing_entries
:
145 self
._rosters
[node
].set_backend(db
, save
)
146 for node
in new_entries
- existing_entries
:
151 Reset the state of the roster to forget any current
152 presence information. Useful after a disconnection occurs.
157 def send_presence(self
, **kwargs
):
159 Create, initialize, and send a Presence stanza.
161 If no recipient is specified, send the presence immediately.
162 Otherwise, forward the send request to the recipient's roster
163 entry for processing.
166 pshow -- The presence's show value.
167 pstatus -- The presence's status message.
168 ppriority -- This connections' priority.
169 pto -- The recipient of a directed presence.
170 pfrom -- The sender of a directed presence, which should
171 be the owner JID plus resource.
172 ptype -- The type of presence, such as 'subscribe'.
173 pnick -- Optional nickname of the presence's sender.
175 if self
.xmpp
.is_component
and not kwargs
.get('pfrom', ''):
176 kwargs
['pfrom'] = self
.jid
177 self
.xmpp
.send_presence(**kwargs
)
180 def auto_authorize(self
):
182 Auto accept or deny subscription requests.
184 If True, auto accept subscription requests.
185 If False, auto deny subscription requests.
186 If None, don't automatically respond.
188 return self
._auto
_authorize
190 @auto_authorize.setter
191 def auto_authorize(self
, value
):
193 Auto accept or deny subscription requests.
195 If True, auto accept subscription requests.
196 If False, auto deny subscription requests.
197 If None, don't automatically respond.
199 self
._auto
_authorize
= value
200 for node
in self
._rosters
:
201 self
._rosters
[node
].auto_authorize
= value
204 def auto_subscribe(self
):
206 Auto send requests for mutual subscriptions.
208 If True, auto send mutual subscription requests.
210 return self
._auto
_subscribe
212 @auto_subscribe.setter
213 def auto_subscribe(self
, value
):
215 Auto send requests for mutual subscriptions.
217 If True, auto send mutual subscription requests.
219 self
._auto
_subscribe
= value
220 for node
in self
._rosters
:
221 self
._rosters
[node
].auto_subscribe
= value
224 return repr(self
._rosters
)