📄 x7499.htm
字号:
print "subscribe request from %s" % (who)
con.send(Jabber.Presence(to=who, type='subscribed'))
con.send(Jabber.Presence(to=who, type='subscribe'))
# unsubscription request:
# - accept their unsubscription
# - send request for unsubscription to their presence
elif type == 'unsubscribe':
print "unsubscribe request from %s" % (who)
con.send(Jabber.Presence(to=who, type='unsubscribed'))
con.send(Jabber.Presence(to=who, type='unsubscribe'))
elif type == 'subscribed':
print "we are now subscribed to %s" % (who)
elif type == 'unsubscribed':
print "we are now unsubscribed to %s" % (who)
elif type == 'available':
print "%s is available (%s/%s)" % (who, prs.getShow(), prs.getStatus())
if prs.getShow() != 'dnd' and who == cvsuser:
con.send(Jabber.Message(cvsuser, message, subject="CVS Watch Alarm"))
elif type == 'unavailable':
print "%s is unavailable" % (who) </PRE
></P
><P
>Phew! Let's take it a bit at at time.
The first thing to note is what's specified in the subroutine declaration:</P
><P
><PRE
CLASS="SCREEN"
>def presenceCB(con, prs):</PRE
></P
><P
>As a handler, the subroutine <TT
CLASS="LITERAL"
>presenceCB()</TT
> will be
passed the <I
CLASS="EMPHASIS"
>connection object</I
> in <TT
CLASS="LITERAL"
>con</TT
>
and the <I
CLASS="EMPHASIS"
>presence node</I
> in <TT
CLASS="LITERAL"
>prs</TT
>.
<TT
CLASS="LITERAL"
>con</TT
> is the same connection object that is created
later in the script (<TT
CLASS="LITERAL"
>con = Jabber.Connection(host=Server)</TT
>)
and is passed in for convenience, as it's quite likely we're going
to want to use it, say, to send something back over the stream.</P
></DIV
><DIV
CLASS="SECT3"
><H3
CLASS="SECT3"
><A
NAME="JABTDG-CH-7-SECT-3.2.2"
>Presence nodes</A
></H3
><P
>The presence node in <TT
CLASS="LITERAL"
>prs</TT
> is an object representation
of the XML fragment that came in over the stream and was parsed into
its component parts. The object is an instance of the
<TT
CLASS="LITERAL"
>Jabber.Presence</TT
> class, which is simply a specialization
of the more generic <TT
CLASS="LITERAL"
>Jabber.Protocol</TT
> class, as are the
other classes
that represent the other two Jabber protocol elements that are to
be expected: <TT
CLASS="LITERAL"
>Jabber.Message</TT
> and
<TT
CLASS="LITERAL"
>Jabber.Iq</TT
>. The <TT
CLASS="LITERAL"
>Jabber.Protocol</TT
>
class represents protocol elements in general.</P
><P
>As such, there are a number of <TT
CLASS="LITERAL"
><presence/></TT
>
element-specific methods we can call on the <TT
CLASS="LITERAL"
>prs</TT
>
object, such as <TT
CLASS="FUNCTION"
>getShow()</TT
> and
<TT
CLASS="FUNCTION"
>getStatus()</TT
> (which return the values of the
<TT
CLASS="LITERAL"
><show/></TT
> and
<TT
CLASS="LITERAL"
><status/></TT
> tags—children of the
<TT
CLASS="LITERAL"
><presence/></TT
> element—respectively),
and general element
methods such as <TT
CLASS="FUNCTION"
>getID</TT
>, which returns the value of
any <TT
CLASS="LITERAL"
>id</TT
> attribute assigned to the element, and
<TT
CLASS="FUNCTION"
>setTo()</TT
> which can be used to address the
element—to set the value of the <TT
CLASS="LITERAL"
>to</TT
> attribute.</P
><P
>The first thing the handler does is to call a few of these element methods
to determine the <I
CLASS="EMPHASIS"
>type</I
> of
<TT
CLASS="LITERAL"
><presence/></TT
> element (presence types are
described in <A
HREF="x4089.htm#JABTDG-CH-5-SECT-5.4.2"
>the section called <I
>The Presence Element</I
> in Chapter 5</A
>),
and who it's coming from:</P
><P
><PRE
CLASS="SCREEN"
> type = prs.getType()
parts = split(prs.getFrom(), '/')
who = parts[0] </PRE
></P
><P
>When the notification script is called, the JID found in the CVS
<TT
CLASS="FILENAME"
>users</TT
> file is substituted for the <TT
CLASS="LITERAL"
>%s</TT
>
in the formula contained in the CVS <TT
CLASS="FILENAME"
>notify</TT
> file.
So if the user <I
CLASS="EMPHASIS"
>dj</I
> were to be notified, the JID
passed to the script would be <TT
CLASS="LITERAL"
>dj@gnu.pipetree.com</TT
>.</P
><P
>The way JIDs are passed around <I
CLASS="EMPHASIS"
>independently</I
> of
the context of a Jabber session is usually in the simpler form:
<TT
CLASS="LITERAL"
>username@hostname</TT
>. That is, without the resource suffix:
<TT
CLASS="LITERAL"
>username@hostname/resource</TT
>. As described in
<A
HREF="c3612.htm"
>Chapter 5</A
>, the resource is primarily used to
distinguish individual sessions belonging to one Jabber user. </P
><P
>But when our Jabber library—and subsequently a handler subroutine
in our script—receives an element, it contains a
<TT
CLASS="LITERAL"
>from</TT
> attribute whose value has been stamped
by the Jabber server as it passes through.
<A
NAME="AEN7668"
HREF="#FTN.AEN7668"
>[3]</A
>
The value represents the session, the <I
CLASS="EMPHASIS"
>connection</I
>,
from which the <TT
CLASS="LITERAL"
><presence/></TT
> element was
sent, and as such, includes a resource suffix. So in order to properly
match up the source JID for any incoming
<TT
CLASS="LITERAL"
><presence/></TT
>
element with the JID specified when the script was invoked (contained
in the <TT
CLASS="LITERAL"
>cvsuser</TT
> variable), we need to strip off this
resource suffix. The remaining <TT
CLASS="LITERAL"
>username@hostname</TT
>
part is captured in the <TT
CLASS="LITERAL"
>who</TT
> variable.</P
><P
>There's one more step to determine the presence type. The
<TT
CLASS="LITERAL"
>type</TT
> attribute is <I
CLASS="EMPHASIS"
>optional</I
>, and
its absence signifies the default presence type, which is "available".
So we effect this default substitution here to make the subsequent code
clearer:</P
><P
><PRE
CLASS="SCREEN"
> if type == None: type = 'available' </PRE
></P
></DIV
><DIV
CLASS="SECT3"
><H3
CLASS="SECT3"
><A
NAME="JABTDG-CH-7-SECT-3.2.3"
>Presence subscription</A
></H3
><P
>At this stage, we want to take different actions depending on what
sort of presence information has arrived. Recalling the sequence of
events in the reciprocal presence subscription exchange described
earlier in this chapter, one of the activities is for a potential
notification recipient to subscribe to the presence of the script's
JID.</P
><P
><I
CLASS="EMPHASIS"
>Request to subscribe</I
></P
><P
>This subscription request is carried in a
<TT
CLASS="LITERAL"
><presence/></TT
> element, with a type of
"<I
CLASS="EMPHASIS"
>subscribe</I
>". <A
HREF="x7499.htm#JABTDG-CH-7-EX-5"
>Example 7-5</A
>
shows what a typical subscription request would look like.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="JABTDG-CH-7-EX-5"
></A
><P
><B
>Example 7-5. A presence subscription request from
<I
CLASS="EMPHASIS"
>dj@gnu.pipetree.com</I
></B
></P
><P
><PRE
CLASS="SCREEN"
><presence type='subscribe' to='cvsmsg@gnu.pipetree.com'
from='dj@gnu.pipetree.com/work'/></PRE
></P
></DIV
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
>Pause:</DT
><DD
><P
>At this stage, <I
CLASS="EMPHASIS"
>dj@gnu.pipetree.com</I
> has
just sent a request to subscribe to the script's presence. The
subscription relationship between the two parties is nondescript, and
this is reflected in the details of the item in <I
CLASS="EMPHASIS"
>dj</I
>'s
roster that relates to the script's JID:</P
><P
><PRE
CLASS="SCREEN"
><item jid='cvsmsg@gnu.pipetree.com' subscription='none' ask='subscribe'/></PRE
></P
><P
>The relationship itself is reflected in the <TT
CLASS="LITERAL"
>subscription</TT
>
attribute, and the current state of the relationship is reflected in the
<TT
CLASS="LITERAL"
>ask</TT
> attribute. </P
></DD
></DL
></DIV
><P
>If one of these is received, we want
the script to respond by accepting their subscription request and
requesting a subscription to <I
CLASS="EMPHASIS"
>their</I
> presence
in return.</P
><P
>This incoming subscription request is handled here:</P
><P
><PRE
CLASS="SCREEN"
> # subscription request:
# - accept their subscription
# - send request for subscription to their presence
if type == 'subscribe':
print "subscribe request from %s" % (who)
con.send(Jabber.Presence(to=who, type='subscribed'))
con.send(Jabber.Presence(to=who, type='subscribe')) </PRE
></P
><P
>Each call to the <TT
CLASS="LITERAL"
>Jabber.Presence</TT
> class constructor
creates a node representing a <TT
CLASS="LITERAL"
><presence/></TT
>
element. The two parameters passed in the call are fairly self-explanatory:
we specify <I
CLASS="EMPHASIS"
>to whom</I
> the
<TT
CLASS="LITERAL"
><presence/></TT
>
element should be sent, and the <I
CLASS="EMPHASIS"
>type</I
>.</P
><P
>If the presence subscription request came in from the JID
<I
CLASS="EMPHASIS"
>dj@gnu.pipetree.com</I
>, then the XML represented
by the node created in the first call here (specifying a presence
type of "subscribed") would look something like
that in <A
HREF="x7499.htm#JABTDG-CH-7-EX-6"
>Example 7-6</A
>.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="JABTDG-CH-7-EX-6"
></A
><P
><B
>Example 7-6. Acceptance of a presence subscription request from <I
CLASS="EMPHASIS"
>dj@gnu.pipetree.com</I
></B
></P
><P
><PRE
CLASS="SCREEN"
><presence type='subscribed' to='dj@gnu.pipetree.com'/></PRE
></P
></DIV
><TABLE
CLASS="SIDEBAR"
BORDER="1"
CELLPADDING="5"
><TR
><TD
><DIV
CLASS="SIDEBAR"
><A
NAME="AEN7726"
></A
><P
><B
>Addressing <TT
CLASS="LITERAL"
><presence/></TT
> elements</B
></P
><P
>It's worth pointing out here that there's a subtle difference between
sending <TT
CLASS="LITERAL"
><presence/></TT
> elements in a presence
subscription conversation, and sending general "availability"
<TT
CLASS="LITERAL"
><presence/></TT
> elements.</P
><P
>In the first case, we use a <TT
CLASS="LITERAL"
>to</TT
>
attribute, because our conversation is one-to-one. In the second, we don't;
Our unaddressed availability information is caught by the server and in
turn sent on to those entities that are subscribed to your presence.</P
><P
>Although you <I
CLASS="EMPHASIS"
>can</I
>
send <TT
CLASS="LITERAL"
><presence/></TT
> elements that convey
availability information directly <I
CLASS="EMPHASIS"
>to</I
> a JID, it's not
normal. However, explicitly addressing the elements in a subscription
scenario is essential.</P
><P
>There's another situation in which such "directed" (explicitly addressed)
<TT
CLASS="LITERAL"
><presence/></TT
> elements are used - to
partake of the services of the Availability Tracker. This is described in the
"<I
CLASS="EMPHASIS"
>Availability Tracker</I
>" sidebar in
<A
HREF="x4089.htm#JABTDG-CH-5-SECT-5.4.2.1"
>the section called <I
>Presence Attributes</I
> in Chapter 5</A
>.</P
></DIV
></TD
></TR
></TABLE
><P
>Once constructed, each of the <TT
CLASS="LITERAL"
>Jabber.Presence</TT
> nodes
are sent back along the stream with the <TT
CLASS="LITERAL"
>con.send()</TT
>
calls.</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
>Pause:</DT
><DD
><P
>Now the script has accepted <I
CLASS="EMPHASIS"
>dj</I
>'s
subscription request, <I
CLASS="EMPHASIS"
>dj</I
>'s roster item for the
script now reflects the new relationship:</P
><P
><PRE
CLASS="SCREEN"
><item jid='cvsmsg@gnu.pipetree.com' subscription='to'/></PRE
></P
><P
><TT
CLASS="LITERAL"
>subscription='to'</TT
> denotes that the subscription
relationship is currently one way—<I
CLASS="EMPHASIS"
>dj</I
> has
a subscription to the script. There's no <TT
CLASS="LITERAL"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -