Adding WS and managing the state better
This commit is contained in:
parent
39e77a80e9
commit
23c1d56799
1 changed files with 81 additions and 33 deletions
|
@ -9,13 +9,20 @@
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'websocket)
|
||||||
|
|
||||||
(defgroup mattermost nil
|
(defgroup mattermost nil
|
||||||
"Mattermost chat client"
|
"Mattermost chat client"
|
||||||
:prefix "mattermost-"
|
:prefix "mattermost-"
|
||||||
:group 'applications)
|
:group 'applications)
|
||||||
|
|
||||||
(defcustom mattermost-server-url ""
|
(defcustom mattermost-login-id ""
|
||||||
"The URL of the Mattermost server"
|
"The username or email to log in the Mattermost server"
|
||||||
|
:group 'mattermost
|
||||||
|
:type 'string)
|
||||||
|
|
||||||
|
(defcustom mattermost-host ""
|
||||||
|
"The hostname of the Mattermost server"
|
||||||
:group 'mattermost
|
:group 'mattermost
|
||||||
:type 'string)
|
:type 'string)
|
||||||
|
|
||||||
|
@ -30,6 +37,9 @@
|
||||||
(defvar mattermost-user-id nil
|
(defvar mattermost-user-id nil
|
||||||
"The ID of the authenticated user")
|
"The ID of the authenticated user")
|
||||||
|
|
||||||
|
(defvar mattermost-websocket nil
|
||||||
|
"The websocket connected to the server")
|
||||||
|
|
||||||
;; ToDo: probably not the best way to get a keyword from a string
|
;; ToDo: probably not the best way to get a keyword from a string
|
||||||
(defun mattermost-string->keyword (str)
|
(defun mattermost-string->keyword (str)
|
||||||
"Returns a keyword from a string"
|
"Returns a keyword from a string"
|
||||||
|
@ -40,9 +50,20 @@
|
||||||
(let ((json-object-type 'plist)
|
(let ((json-object-type 'plist)
|
||||||
(json-array-type 'list)
|
(json-array-type 'list)
|
||||||
(json-key-type 'keyword))
|
(json-key-type 'keyword))
|
||||||
|
(with-current-buffer (get-buffer-create "asdf")
|
||||||
|
(insert (format "%s" (buffer-string))))
|
||||||
(goto-char url-http-end-of-headers)
|
(goto-char url-http-end-of-headers)
|
||||||
(json-read)))
|
(json-read)))
|
||||||
|
|
||||||
|
(defun mattermost-read-password ()
|
||||||
|
"Reads the password from the auth-source"
|
||||||
|
(let ((res (auth-source-search :max 1 :host mattermost-host :user mattermost-login-id)))
|
||||||
|
(if (and (listp res) (= (length res) 1))
|
||||||
|
(let ((secret (plist-get (car res) :secret)))
|
||||||
|
(if (functionp secret)
|
||||||
|
(funcall secret)
|
||||||
|
secret)))))
|
||||||
|
|
||||||
(defun mattermost-print-post (post)
|
(defun mattermost-print-post (post)
|
||||||
"Prints the post in the current buffer"
|
"Prints the post in the current buffer"
|
||||||
(let* ((msg (plist-get post :message))
|
(let* ((msg (plist-get post :message))
|
||||||
|
@ -51,7 +72,7 @@
|
||||||
(user-id (plist-get post :user_id))
|
(user-id (plist-get post :user_id))
|
||||||
(user (mattermost--get-user user-id))
|
(user (mattermost--get-user user-id))
|
||||||
(username (plist-get user :username)))
|
(username (plist-get user :username)))
|
||||||
(insert (format "[%s] %s\n" username msg))))
|
(insert (format "[%s] %s\n" username (encode-coding-string msg 'utf-8)))))
|
||||||
|
|
||||||
(defun mattermost--get-user (user-id)
|
(defun mattermost--get-user (user-id)
|
||||||
"Returns the user from the internal cache and fills the cache
|
"Returns the user from the internal cache and fills the cache
|
||||||
|
@ -64,6 +85,25 @@ if the user is not present"
|
||||||
user)
|
user)
|
||||||
user)))
|
user)))
|
||||||
|
|
||||||
|
(defun mattermost--get-auth-challenge ()
|
||||||
|
"Returns the JSON representation of the websocket authentication challenge"
|
||||||
|
(json-encode `(:seq 1
|
||||||
|
:action "authentication_challenge"
|
||||||
|
:data (:token ,mattermost-token))))
|
||||||
|
|
||||||
|
(defun mattermost--connect-websocket ()
|
||||||
|
"Returns a websocket configured to connect to the Mattermost
|
||||||
|
host and to dispatch and process the incoming messages"
|
||||||
|
(websocket-open (format "wss://%s/api/v4/websocket" mattermost-host)
|
||||||
|
:on-open (lambda (ws)
|
||||||
|
(websocket-send-text ws (mattermost--get-auth-challenge)))
|
||||||
|
:on-message (lambda (ws frame)
|
||||||
|
(let* ((text (websocket-frame-text frame))
|
||||||
|
(msg (json-parse-string text)))
|
||||||
|
(message "INCOMING> %s" msg)))
|
||||||
|
:on-close (lambda (ws)
|
||||||
|
(lwarn 'mattermost :error "websocket connection closed"))))
|
||||||
|
|
||||||
;; ToDo: once mattermost-request parses headers, use it to fetch both
|
;; ToDo: once mattermost-request parses headers, use it to fetch both
|
||||||
;; the user (set the id to a local var) and the headers (set the
|
;; the user (set the id to a local var) and the headers (set the
|
||||||
;; token)
|
;; token)
|
||||||
|
@ -79,6 +119,7 @@ if the user is not present"
|
||||||
(response (mattermost-parse-json)))
|
(response (mattermost-parse-json)))
|
||||||
(setq mattermost-token token)
|
(setq mattermost-token token)
|
||||||
(setq mattermost-user-id (plist-get response :id))
|
(setq mattermost-user-id (plist-get response :id))
|
||||||
|
(mattermost--connect-websocket)
|
||||||
token))))
|
token))))
|
||||||
|
|
||||||
;; ToDo: update to parse headers as well
|
;; ToDo: update to parse headers as well
|
||||||
|
@ -103,7 +144,6 @@ if the user is not present"
|
||||||
(defun mattermost-get-channels (team-id)
|
(defun mattermost-get-channels (team-id)
|
||||||
"Returns the user's channel for a given team"
|
"Returns the user's channel for a given team"
|
||||||
(let ((url (format "/users/%s/teams/%s/channels" mattermost-user-id team-id)))
|
(let ((url (format "/users/%s/teams/%s/channels" mattermost-user-id team-id)))
|
||||||
(message "Channels url: %s" url)
|
|
||||||
(mattermost-request "GET" url)))
|
(mattermost-request "GET" url)))
|
||||||
|
|
||||||
(defun mattermost-get-channel-messages (channel-id &optional page per-page)
|
(defun mattermost-get-channel-messages (channel-id &optional page per-page)
|
||||||
|
@ -111,7 +151,17 @@ if the user is not present"
|
||||||
(let ((url (format "/channels/%s/posts" channel-id)))
|
(let ((url (format "/channels/%s/posts" channel-id)))
|
||||||
(mattermost-request "GET" url)))
|
(mattermost-request "GET" url)))
|
||||||
|
|
||||||
(with-current-buffer (get-buffer-create "*Mattermost Teams*")
|
;; ToDo: define this better
|
||||||
|
(defvar mattermost-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(define-key map (kbd "C-c f") '(lambda () (interactive) (message "keyyyy")))
|
||||||
|
map)
|
||||||
|
"The keymap for mattermost-mode")
|
||||||
|
|
||||||
|
(defun show-root ()
|
||||||
|
(interactive)
|
||||||
|
(let ((rootb (get-buffer-create "*Mattermost Root*")))
|
||||||
|
(with-current-buffer rootb
|
||||||
(let ((teams (mattermost-get-teams)))
|
(let ((teams (mattermost-get-teams)))
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(dolist (team teams)
|
(dolist (team teams)
|
||||||
|
@ -126,34 +176,32 @@ if the user is not present"
|
||||||
(insert (format "> [%s] %s\n" channel-id (if (string= channel-display-name "")
|
(insert (format "> [%s] %s\n" channel-id (if (string= channel-display-name "")
|
||||||
channel-name
|
channel-name
|
||||||
channel-display-name)))))))))
|
channel-display-name)))))))))
|
||||||
;; ToDo: define this better
|
(set-buffer rootb)))
|
||||||
(defvar mattermost-mode-map
|
|
||||||
(let ((map (make-sparse-keymap)))
|
|
||||||
(define-key map (kbd "C-c f") '(lambda () (interactive) (message "keyyyy")))
|
|
||||||
map)
|
|
||||||
"The keymap for mattermost-mode")
|
|
||||||
|
|
||||||
(define-derived-mode mattermost-mode fundamental-mode "Mattermost"
|
(define-derived-mode mattermost-root-mode fundamental-mode "Mattermost Root"
|
||||||
"Mode to list the Mattermost teams and channels to allow the
|
"Mode to list the Mattermost teams and channels to allow the
|
||||||
user to check their status and select between them")
|
user to check their status and select between them")
|
||||||
|
|
||||||
(defun mattermost ()
|
(defun mattermost ()
|
||||||
"Connect to a Mattermost instance"
|
"Connect to a Mattermost instance"
|
||||||
(interactive)
|
(interactive)
|
||||||
)
|
(if (string-empty-p mattermost-login-id)
|
||||||
|
;; ToDo: throw error here
|
||||||
|
(lwarn 'mattermost :error "`mattermost-login-id` cannot be empty"))
|
||||||
|
(if (string-empty-p mattermost-host)
|
||||||
|
;; ToDo: throw error here
|
||||||
|
(lwarn 'mattermost :error "`mattermost-host` cannot be empty"))
|
||||||
|
(mattermost-close)
|
||||||
|
(let ((password (mattermost-read-password)))
|
||||||
|
(mattermost-login mattermost-login-id password))
|
||||||
|
(show-root))
|
||||||
|
|
||||||
;; ToDo: remove
|
(defun mattermost-close ()
|
||||||
(setq msgs (mattermost-get-channel-messages "68w17u1da7yg7enayudjjqqwse"))
|
"Closes the connection with the Mattermost server"
|
||||||
(car (plist-get msgs :posts))
|
(unless (null mattermost-websocket)
|
||||||
|
(websocket-close mattermost-websocket))
|
||||||
(with-current-buffer (get-buffer-create "*Town Square*")
|
(setq mattermost-token nil
|
||||||
(erase-buffer)
|
mattermost-user-id nil))
|
||||||
(let ((posts (plist-get msgs :posts))
|
|
||||||
(order (plist-get msgs :order)))
|
|
||||||
(dolist (msgid order)
|
|
||||||
(let* ((msgid-keyword (mattermost-string->keyword msgid))
|
|
||||||
(post (plist-get posts msgid-keyword)))
|
|
||||||
(mattermost-print-post post)))))
|
|
||||||
|
|
||||||
(provide 'mattermost)
|
(provide 'mattermost)
|
||||||
;;; mattermost.el ends here
|
;;; mattermost.el ends here
|
||||||
|
|
Loading…
Reference in a new issue