1 ;;; jabber-newdisco.el --- caching disco API
3 ;; Copyright (C) 2005, 2008 Magnus Henoch
5 ;; Author: Magnus Henoch <mange@freemail.hu>
7 ;; This file is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; This file is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU Emacs; see the file COPYING. If not, write to
19 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
23 ;; Keys are ("jid" . "node"), where "node" is nil if appropriate.
24 ;; Values are (identities features), where each identity is ["name"
25 ;; "category" "type"], and each feature is a string.
26 (defvar jabber-disco-info-cache
(make-hash-table :test
'equal
))
28 ;; Keys are ("jid" . "node"). Values are (items), where each
29 ;; item is ["name" "jid" "node"] (some values may be nil).
30 (defvar jabber-disco-items-cache
(make-hash-table :test
'equal
))
34 (defun jabber-disco-get-info (jc jid node callback closure-data
&optional force
)
35 "Get disco info for JID and NODE, using connection JC.
36 Call CALLBACK with JC and CLOSURE-DATA as first and second
37 arguments and result as third argument when result is available.
38 On success, result is (IDENTITIES FEATURES), where each identity is [\"name\"
39 \"category\" \"type\"], and each feature is a string.
40 On error, result is the error node, recognizable by (eq (car result) 'error).
42 If CALLBACK is nil, just fetch data. If FORCE is non-nil,
43 invalidate cache and get fresh data."
45 (remhash (cons jid node
) jabber-disco-info-cache
))
46 (let ((result (gethash (cons jid node
) jabber-disco-info-cache
)))
48 (and callback
(run-with-timer 0 nil callback jc closure-data result
))
49 (jabber-send-iq jc jid
51 `(query ((xmlns .
"http://jabber.org/protocol/disco#info")
52 ,(when node
`(node .
,node
))))
53 #'jabber-disco-got-info
(cons callback closure-data
)
54 (lambda (jc xml-data callback-data
)
55 (when (car callback-data
)
56 (funcall (car callback-data
) jc
(cdr callback-data
) (jabber-iq-error xml-data
))))
57 (cons callback closure-data
)))))
59 (defun jabber-disco-got-info (jc xml-data callback-data
)
60 (let ((jid (jabber-xml-get-attribute xml-data
'from
))
61 (node (jabber-xml-get-attribute (jabber-iq-query xml-data
)
67 (vector (jabber-xml-get-attribute id
'name
)
68 (jabber-xml-get-attribute id
'category
)
69 (jabber-xml-get-attribute id
'type
)))
70 (jabber-xml-get-children (jabber-iq-query xml-data
) 'identity
))
73 (jabber-xml-get-attribute feature
'var
))
74 (jabber-xml-get-children (jabber-iq-query xml-data
) 'feature
)))))
75 (puthash (cons jid node
) result jabber-disco-info-cache
)
76 (when (car callback-data
)
77 (funcall (car callback-data
) jc
(cdr callback-data
) result
))))
79 (defun jabber-disco-get-info-immediately (jid node
)
80 "Get cached disco info for JID and NODE.
81 Return nil if no info available.
83 Fill the cache with `jabber-disco-get-info'."
84 (gethash (cons jid node
) jabber-disco-info-cache
))
88 (defun jabber-disco-get-items (jc jid node callback closure-data
&optional force
)
89 "Get disco items for JID and NODE, using connection JC.
90 Call CALLBACK with JC and CLOSURE-DATA as first and second
91 arguments and items result as third argument when result is
93 On success, result is a list of items, where each
94 item is [\"name\" \"jid\" \"node\"] (some values may be nil).
95 On error, result is the error node, recognizable by (eq (car result) 'error).
97 If CALLBACK is nil, just fetch data. If FORCE is non-nil,
98 invalidate cache and get fresh data."
100 (remhash (cons jid node
) jabber-disco-items-cache
))
101 (let ((result (gethash (cons jid node
) jabber-disco-items-cache
)))
103 (and callback
(run-with-timer 0 nil callback jc closure-data result
))
104 (jabber-send-iq jc jid
106 `(query ((xmlns .
"http://jabber.org/protocol/disco#items")
107 ,(when node
`(node .
,node
))))
108 #'jabber-disco-got-items
(cons callback closure-data
)
109 (lambda (jc xml-data callback-data
)
110 (when (car callback-data
)
111 (funcall (car callback-data
) jc
(cdr callback-data
) (jabber-iq-error xml-data
))))
112 (cons callback closure-data
)))))
114 (defun jabber-disco-got-items (jc xml-data callback-data
)
115 (let ((jid (jabber-xml-get-attribute xml-data
'from
))
116 (node (jabber-xml-get-attribute (jabber-iq-query xml-data
)
122 (jabber-xml-get-attribute item
'name
)
123 (jabber-xml-get-attribute item
'jid
)
124 (jabber-xml-get-attribute item
'node
)))
125 (jabber-xml-get-children (jabber-iq-query xml-data
) 'item
))))
126 (puthash (cons jid node
) result jabber-disco-items-cache
)
127 (when (car callback-data
)
128 (funcall (car callback-data
) jc
(cdr callback-data
) result
))))
130 (defun jabber-disco-get-items-immediately (jid node
)
131 (gethash (cons jid node
) jabber-disco-items-cache
))
135 (defun jabber-disco-publish (jc node item-name item-jid item-node
)
136 "Publish the given item under disco node NODE."
137 (jabber-send-iq jc nil
139 `(query ((xmlns .
"http://jabber.org/protocol/disco#items")
140 ,(when node
`(node .
,node
)))
141 (item ((action .
"update")
144 `(name .
,item-name
))
146 `(node .
,item-node
)))))
147 'jabber-report-success
"Disco publish"
148 'jabber-report-success
"Disco publish"))
150 (defun jabber-disco-publish-remove (jc node item-jid item-node
)
151 "Remove the given item from published disco items."
152 (jabber-send-iq jc nil
154 `(query ((xmlns .
"http://jabber.org/protocol/disco#items")
155 ,(when node
`(node .
,node
)))
156 (item ((action .
"remove")
159 `(node .
,item-node
)))))
160 'jabber-report-success
"Disco removal"
161 'jabber-report-success
"Disco removal"))
163 (provide 'jabber-newdisco
)
165 ;; arch-tag: b47c06aa-cae6-11d9-b1c0-000a95c2fcd0