add MUC disco#items handler, fix children including text DOM nodes

This commit is contained in:
eta 2020-07-07 21:27:21 +01:00
parent 7e457266f8
commit 5ce6d47266
7 changed files with 38 additions and 11 deletions

View file

@ -232,7 +232,10 @@
(defun handle-iq-get (comp id from stanza) (defun handle-iq-get (comp id from stanza)
"Handles an IQ-get STANZA for component COMP." "Handles an IQ-get STANZA for component COMP."
(let* ((first-child (elt (dom:child-nodes stanza) 0)) (let* ((children (child-elements stanza))
(first-child (if (> (length children) 0)
(elt children 0)
(return-from handle-iq-get)))
(tag-name (dom:tag-name first-child)) (tag-name (dom:tag-name first-child))
(to (dom:get-attribute stanza "to")) (to (dom:get-attribute stanza "to"))
(xmlns (dom:get-attribute first-child "xmlns")) (xmlns (dom:get-attribute first-child "xmlns"))

View file

@ -124,3 +124,12 @@
(loop (loop
while (sqlite:step-statement get-stmt) while (sqlite:step-statement get-stmt)
collect (with-bound-columns (localpart) get-stmt localpart)))) collect (with-bound-columns (localpart) get-stmt localpart))))
(defun get-user-groupchats (uid)
"Get a list of groupchat info (cons pairs of LOCALPART . SUBJECT) for the user with ID UID."
(with-prepared-statements
((get-stmt "SELECT wa_jid, subject FROM user_chats WHERE user_id = ?"))
(bind-parameters get-stmt uid)
(loop
while (sqlite:step-statement get-stmt)
collect (with-bound-columns (localpart subject) get-stmt (cons localpart subject)))))

View file

@ -4,7 +4,7 @@ let
in in
pkgs.dockerTools.buildLayeredImage { pkgs.dockerTools.buildLayeredImage {
name = "eu.gcr.io/etainfra/whatsxmpp"; name = "eu.gcr.io/etainfra/whatsxmpp";
tag = "nix"; tag = "latest";
contents = [ whatsxmpp ]; contents = [ whatsxmpp ];
config.Entrypoint = [ "${whatsxmpp}/bin/whatsxmpp" ]; config.Entrypoint = [ "${whatsxmpp}/bin/whatsxmpp" ];
config.Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ]; config.Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ];

View file

@ -40,6 +40,7 @@
(cond (cond
((equal to (component-name comp)) ((equal to (component-name comp))
`((disco-identity "whatsxmpp bridge" "xmpp" "gateway") `((disco-identity "whatsxmpp bridge" "xmpp" "gateway")
(disco-feature ,+disco-items-ns+)
(disco-feature ,+muc-ns+))) (disco-feature ,+muc-ns+)))
((and user-name (not to-resource)) ((and user-name (not to-resource))
`((disco-identity ,user-name "registered" "account"))) `((disco-identity ,user-name "registered" "account")))
@ -56,12 +57,22 @@
(disco-feature "muc_nonanonymous"))) (disco-feature "muc_nonanonymous")))
(t nil)))))))) (t nil))))))))
(defun disco-items-handler (comp &key to &allow-other-keys) (defun disco-items-handler (comp &key to from &allow-other-keys)
"Handles XEP-0030 disco#items requests." "Handles XEP-0030 disco#items requests."
(format *debug-io* "~&disco#items: ~A~%" to) (format *debug-io* "~&disco#items: ~A from ~A~%" to from)
(with-component-data-lock (comp) (with-component-data-lock (comp)
`((cxml:with-element "query" `((cxml:with-element "query"
(cxml:attribute "xmlns" ,+disco-info-ns+))))) (cxml:attribute "xmlns" ,+disco-items-ns+)
,@(when (equal to (component-name comp))
(let ((uid (get-user-id (strip-resource from))))
(format *debug-io* "~&muc list disco#items for ~A~%" (strip-resource from))
(loop
for (localpart . subject) in (get-user-groupchats uid)
collect `(cxml:with-element "item"
(cxml:attribute "jid" ,(concatenate 'string
localpart "@"
(component-name comp)))
(cxml:attribute "name" ,subject)))))))))
(defun admin-jid (comp) (defun admin-jid (comp)
"Get the admin JID for COMP. You need the lock to be taken out for this one." "Get the admin JID for COMP. You need the lock to be taken out for this one."
@ -1115,7 +1126,7 @@ Returns three values: avatar data (as two values), and a generalized boolean spe
(let* ((stripped (strip-resource from)) (let* ((stripped (strip-resource from))
(conn (gethash stripped (component-whatsapps comp))) (conn (gethash stripped (component-whatsapps comp)))
(uid (get-user-id stripped)) (uid (get-user-id stripped))
(x-element (get-node-with-xmlns (dom:child-nodes stanza) +muc-ns+))) (x-element (get-node-with-xmlns (child-elements stanza) +muc-ns+)))
(cond (cond
(x-element (x-element
(handler-case (handler-case

View file

@ -12,3 +12,7 @@
(defun sha1-hex (str) (defun sha1-hex (str)
"Returns the SHA1 of STR, a string, in lowercase hex." "Returns the SHA1 of STR, a string, in lowercase hex."
(sha1-octets (babel:string-to-octets str))) (sha1-octets (babel:string-to-octets str)))
(defun child-elements (node)
"Returns the child elements (excluding text nodes) of the CXML DOM node NODE."
(remove-if-not #'dom:element-p (dom:child-nodes node)))

View file

@ -13,7 +13,7 @@
(unless query-node (unless query-node
(error "Malformed disco#info response: no <query/>")) (error "Malformed disco#info response: no <query/>"))
(loop (loop
for node across (dom:child-nodes query-node) for node across (child-elements query-node)
do (let ((name (dom:tag-name node))) do (let ((name (dom:tag-name node)))
(when (equal name "feature") (when (equal name "feature")
(setf features (cons (dom:get-attribute node "var") features))))) (setf features (cons (dom:get-attribute node "var") features)))))
@ -31,7 +31,7 @@
(unless query-node (unless query-node
(error "Malformed disco#items response: no <query/>")) (error "Malformed disco#items response: no <query/>"))
(loop (loop
for node across (dom:child-nodes query-node) for node across (child-elements query-node)
do (let ((name (dom:tag-name node))) do (let ((name (dom:tag-name node)))
(when (equal name "item") (when (equal name "item")
(setf items (cons (setf items (cons

View file

@ -14,18 +14,18 @@
(let ((slot-node (get-node-named results "slot"))) (let ((slot-node (get-node-named results "slot")))
(unless slot-node (unless slot-node
(error "Malformed XEP-0363 response: no <slot/>")) (error "Malformed XEP-0363 response: no <slot/>"))
(let* ((children (dom:child-nodes slot-node)) (let* ((children (child-elements slot-node))
(put-node (get-node-named children "put")) (put-node (get-node-named children "put"))
(get-node (get-node-named children "get")) (get-node (get-node-named children "get"))
(headers '())) (headers '()))
(unless (and put-node get-node) (unless (and put-node get-node)
(error "Malformed XEP-0363 response: PUT or GET nodes missing")) (error "Malformed XEP-0363 response: PUT or GET nodes missing"))
(loop (loop
for node across (dom:child-nodes put-node) for node across (child-elements put-node)
do (let ((name (dom:tag-name node))) do (let ((name (dom:tag-name node)))
(when (equal name "header") (when (equal name "header")
(setf headers (cons (setf headers (cons
(cons (dom:get-attribute node "name") (cons (dom:get-attribute node "name")
(dom:node-value (elt (dom:child-nodes node) 0))) (dom:node-value (elt (child-elements node) 0)))
headers))))) headers)))))
`((,(dom:get-attribute put-node "url") . ,headers) ,(dom:get-attribute get-node "url"))))))) `((,(dom:get-attribute put-node "url") . ,headers) ,(dom:get-attribute get-node "url")))))))