Make sico work with the new matrix-api

master
Ryan Rix 2016-06-30 00:03:33 -07:00
parent 1cefe5b105
commit 941b0aa867
1 changed files with 78 additions and 32 deletions

110
sico.el
View File

@ -63,6 +63,10 @@ Matrix/Emacs robot butler."
:type '(repeat string)
:group 'sico)
(defcustom sico-username nil
"What is the username of sico"
:type 'string :group 'sico)
(defcustom sico-capture-note-regexp "^!note\\b\\(.*\\)"
"Regular expression defining how to capture notes.
@ -93,56 +97,95 @@ single argument."
"Hello, my name is Sico and I am pleased to be of service."
"The message the bot says upon joining each room.")
(defvar sico-current-end-token nil)
(defvar sico-running nil)
(defvar sico-active-connection nil)
(defclass sico-connection (matrix-connection)
((running :initarg :running
:initform nil
:documentation "BOOL specifiying if the event listener is currently running.")
(rooms :initarg :rooms
:initform nil
:documentation "List of matrix-room objects")
(end-token :initarg :end-token)))
(defun sico-start ()
"Start Assitant and connect it to the Matrix homeserver."
(interactive)
(unless matrix-token
(matrix-client-login))
(unless sico-active-connection
(setq sico-active-connection (sico-connection matrix-homeserver-base-url :base-url matrix-homeserver-base-url))
(sico-login sico-active-connection sico-username))
(sico-join-rooms)
(sico-start-polling)
(setq sico-running t))
(defmethod sico-login ((con sico-connection) username)
(let* ((auth-source-creation-prompts
'((username . "Matrix identity: ")
(secret . "Matrix password for %u (homeserver: %h): ")))
(found (nth 0 (auth-source-search :max 1
:host (oref con :base-url)
:user username
:require '(:user :secret)
:create t))))
(when (and
found
(matrix-login-with-password con
(plist-get found :user)
(let ((secret (plist-get found :secret)))
(if (functionp secret)
(funcall secret)
secret)))
(let ((save-func (plist-get found :save-function)))
(when save-func (funcall save-func)))))))
(defun sico-stop ()
"Tell sico to stop polling."
(setq sico-running nil))
(interactive)
(oset sico-active-connection :running nil)
(setq sico-active-connection nil))
(defun sico-start-polling ()
"Begin polling for events with the [`sico-poll-callback'] as the handler."
(matrix-event-poll sico-current-end-token
10
'sico-poll-callback))
(let* ((con sico-active-connection)
(next (and (slot-boundp con :end-token)
(oref con :end-token))))
(matrix-sync con next (if next nil t) 10
(apply-partially #'sico-sync-handler con))))
(defun sico-join-rooms ()
"Join the rooms that Sico is configured to be in."
(dolist (room sico-rooms)
(matrix-join-room room)
(matrix-send-message room sico-connection-string)))
(matrix-join-room sico-active-connection room)
(when (> (length sico-connection-string) 0)
(matrix-send-message sico-active-connection room sico-connection-string))))
(defun sico-poll-callback (data)
"The callback triggered by [`matrix-event-poll'].
(defmethod sico-sync-handler ((con sico-connection) data)
(mapc
(lambda (room-data)
(let* ((room-id (symbol-name (car room-data)))
(room-events (cdr room-data))
(handler (lambda (item)
(dolist (cell sico-listeners)
(let ((content (matrix-get 'content item))
(type (matrix-get 'type item)))
(when (and content
(string= type "m.room.message")
(string-match (car cell)
(matrix-get 'body content)))
(message "match %s: %s" content cell)
(funcall (cdr cell) con room-id item)))))))
(mapc handler
(matrix-get 'events (matrix-get 'state room-events)))
(mapc handler
(matrix-get 'events (matrix-get 'timeline room-events)))))
(matrix-get 'join (matrix-get 'rooms data)))
(let ((next (matrix-get 'next_batch data)))
(oset con :end-token next)
(when (and (slot-boundp con :running)
(oref con :running))
(sico-start-polling))))
DATA comes directly from the Matrix homeserver, massaged in to a
sexp by [`json-parse']"
(if (eq (car data) 'error)
(message "%s" data)
(let* ((chunk (matrix-get 'chunk data)))
(setq sico-current-end-token (matrix-get 'end data))
(mapc (lambda (item)
(dolist (cell sico-listeners)
(let ((content (matrix-get 'content item))
(type (matrix-get 'type item)))
(when (and content
(string= type "m.room.message")
(string-match (car cell)
(matrix-get 'body content)))
(funcall (cdr cell) item))))) chunk)))
(when sico-running
(sico-start-polling)))
(defun sico-capture-note (event)
(defun sico-capture-note (con room-id event)
"Capture a note from EVENT."
(let* ((content (matrix-get 'content event))
(body (matrix-get 'body content))
@ -150,11 +193,14 @@ sexp by [`json-parse']"
(match (match-string 1 body))
(user-id (matrix-get 'sender event))
(room-id (matrix-get 'room_id event)))
(message "matchdata: %s %s %s" body match sico-capture-note-regexp)
(when (member user-id sico-users)
(message "userid %s: %s" user-id sico-users)
(kill-new match)
(org-capture nil sico-capture-note-template)
(matrix-send-message room-id
(matrix-send-message sico-active-connection room-id
(format "I have captured: \"%s\"" match)))))
(provide 'sico)
;;; sico.el ends here