a02c0fdc79
- We now handle the :chat-modified event from whatscl, and re-fetch group metadata when we receive it. - Of course, this doesn't actually help for resources which are in the MUC at update time; they'll need to reconnect until we have code to handle message stubs properly. - Chat metadata reception now generates a message to the user, both for ease of debugging, and also to let them know that something happened to a groupchat they're in which they would otherwise not be aware of at all. (A handy link is also provided, if you missed the invite and want to join a MUC you're not in.) - The new `refresh-chats` admin command forces a refresh of all group metadata in one big go. (Also, the help text now displays the current version.)
136 lines
5.8 KiB
Common Lisp
136 lines
5.8 KiB
Common Lisp
(in-package :whatsxmpp)
|
|
|
|
(defun get-user-id (jid)
|
|
"Get the user ID of JID, or NIL if none exists."
|
|
(with-prepared-statement
|
|
(get-user "SELECT id FROM users WHERE jid = ?")
|
|
(let ((stripped (strip-resource jid)))
|
|
(bind-parameters get-user stripped)
|
|
(when (sqlite:step-statement get-user)
|
|
(first (column-values get-user))))))
|
|
|
|
(defun get-user-contact-localparts (uid)
|
|
"Returns a list of all contact localparts for UID."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT wa_jid FROM user_contacts WHERE user_id = ?"))
|
|
(bind-parameters get-stmt uid)
|
|
(loop
|
|
while (sqlite:step-statement get-stmt)
|
|
collect (sqlite:statement-column-value get-stmt 0))))
|
|
|
|
(defun get-user-chat-id (uid localpart)
|
|
"Get the user chat ID of LOCALPART for UID, or NIL if none exists."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT id FROM user_chats WHERE user_id = ? AND wa_jid = ?"))
|
|
(bind-parameters get-stmt uid localpart)
|
|
(when (sqlite:step-statement get-stmt)
|
|
(with-bound-columns (id) get-stmt
|
|
id))))
|
|
|
|
(defun get-user-chat-subject (uid localpart)
|
|
"Get the user chat subject of LOCALPART for UID, or NIL if none exists."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT subject FROM user_chats WHERE user_id = ? AND wa_jid = ?"))
|
|
(bind-parameters get-stmt uid localpart)
|
|
(when (sqlite:step-statement get-stmt)
|
|
(with-bound-columns (subject) get-stmt
|
|
subject))))
|
|
|
|
(defun get-user-chat-resource (uid localpart)
|
|
"Get the user chat resource of LOCALPART for UID, or NIL if none exists."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT user_resource FROM user_chats WHERE user_id = ? AND wa_jid = ?"))
|
|
(bind-parameters get-stmt uid localpart)
|
|
(when (sqlite:step-statement get-stmt)
|
|
(with-bound-columns (resource) get-stmt
|
|
(when (and resource (> (length resource) 0))
|
|
resource)))))
|
|
|
|
(defun get-participant-resource (chat-id localpart)
|
|
"Get the participant resource for LOCALPART in CHAT-ID, or NIL if none exists."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT resource FROM user_chat_members WHERE chat_id = ? AND wa_jid = ?"))
|
|
(bind-parameters get-stmt chat-id localpart)
|
|
(when (sqlite:step-statement get-stmt)
|
|
(with-bound-columns (resource) get-stmt
|
|
(when (and resource (> (length resource) 0))
|
|
resource)))))
|
|
|
|
(defun get-user-chat-joined (uid localpart)
|
|
"Get the user chat resource of LOCALPART for UID, or NIL if none exists."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT ucj.jid FROM user_chats AS uc, user_chat_joined AS ucj WHERE uc.user_id = ? AND uc.wa_jid = ? AND uc.id = ucj.chat_id"))
|
|
(bind-parameters get-stmt uid localpart)
|
|
(loop
|
|
while (sqlite:step-statement get-stmt)
|
|
append (column-values get-stmt))))
|
|
|
|
(defun get-contact-name (uid localpart)
|
|
"Get a name for LOCALPART, a possible contact for the user with ID UID."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT name, notify FROM user_contacts WHERE user_id = ? AND wa_jid = ?"))
|
|
(bind-parameters get-stmt uid localpart)
|
|
(when (sqlite:step-statement get-stmt)
|
|
(with-bound-columns (name notify) get-stmt
|
|
(or name notify (substitute #\+ #\u localpart))))))
|
|
|
|
(defun get-contact-status (uid localpart)
|
|
"Get the contact status text for LOCALPART, a possible contact for the user with ID UID."
|
|
(declare (type integer uid) (type string localpart))
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT status FROM user_contacts WHERE user_id = ? AND wa_jid = ?"))
|
|
(bind-parameters get-stmt uid localpart)
|
|
(when (sqlite:step-statement get-stmt)
|
|
(with-bound-columns (status) get-stmt
|
|
status))))
|
|
|
|
(defun insert-user-message (uid xmpp-id wa-id)
|
|
"Inserts a mapping between the message IDs XMPP-ID and WA-ID for the user UID."
|
|
(with-prepared-statements
|
|
((insert-stmt "INSERT INTO user_messages (user_id, xmpp_id, wa_id) VALUES (?, ?, ?)"))
|
|
(bind-parameters insert-stmt uid xmpp-id wa-id)
|
|
(sqlite:step-statement insert-stmt)))
|
|
|
|
(defun insert-user-chat (uid wa-id)
|
|
"Inserts a user chat with localpart WA-ID into the database for the user with UID."
|
|
(with-prepared-statements
|
|
((insert-stmt "INSERT INTO user_chats (user_id, wa_jid) VALUES (?, ?) ON CONFLICT DO NOTHING"))
|
|
(bind-parameters insert-stmt uid wa-id)
|
|
(sqlite:step-statement insert-stmt)))
|
|
|
|
(defun lookup-wa-msgid (uid wa-msgid)
|
|
"Look up the XMPP ID for the WhatsApp message ID WA-MSGID, when received for the user UID."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT xmpp_id FROM user_messages WHERE user_id = ? AND wa_id = ?"))
|
|
(bind-parameters get-stmt uid wa-msgid)
|
|
(when (sqlite:step-statement get-stmt)
|
|
(with-bound-columns (xid) get-stmt
|
|
xid))))
|
|
|
|
(defun lookup-xmpp-msgid (uid xmpp-msgid)
|
|
"Look up the WhatsApp message ID for the XMPP message ID XMPP-MSGID, when received for the user UID."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT wa_id FROM user_messages WHERE user_id = ? AND xmpp_id = ?"))
|
|
(bind-parameters get-stmt uid xmpp-msgid)
|
|
(when (sqlite:step-statement get-stmt)
|
|
(with-bound-columns (wid) get-stmt
|
|
wid))))
|
|
|
|
(defun get-contact-localparts (uid)
|
|
"Get a list of contact localparts for the user with ID UID."
|
|
(with-prepared-statements
|
|
((get-stmt "SELECT wa_jid FROM user_contacts WHERE user_id = ?"))
|
|
(bind-parameters get-stmt uid)
|
|
(loop
|
|
while (sqlite:step-statement get-stmt)
|
|
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)))))
|