2022-05-22 12:00:26 +01:00
|
|
|
;;; mattermost.el --- An Emacs Mattermost Chat Client
|
|
|
|
|
|
|
|
;; ToDo: LICENSE HERE
|
|
|
|
|
|
|
|
;; Author: Miguel de la Cruz (mgdelacroix@gmail.com)
|
|
|
|
;; Version: 0.1
|
|
|
|
;; Package-Requires: ((websocket))
|
|
|
|
;; Keywords: Mattermost, chat, client, Internet
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
(defgroup mattermost nil
|
|
|
|
"Mattermost chat client"
|
|
|
|
:prefix "mattermost-"
|
|
|
|
:group 'applications)
|
|
|
|
|
|
|
|
(defcustom mattermost-server-url ""
|
|
|
|
"The URL of the Mattermost server"
|
|
|
|
:group 'mattermost
|
|
|
|
:type 'string)
|
|
|
|
|
2022-05-22 19:10:00 +01:00
|
|
|
;; ToDo: internal variables should be prefixed with mattermost--
|
|
|
|
;; instead?
|
2022-05-22 19:09:12 +01:00
|
|
|
(defvar mattermost-users-plist '()
|
|
|
|
"A plist with the server users by id")
|
|
|
|
|
|
|
|
(defvar mattermost-token nil
|
|
|
|
"The user token to access the server")
|
|
|
|
|
|
|
|
(defvar mattermost-user-id nil
|
|
|
|
"The ID of the authenticated user")
|
|
|
|
|
2022-05-22 12:00:26 +01:00
|
|
|
(setq mattermost-server-url "https://chat.ctrlz.es")
|
|
|
|
|
2022-05-22 17:02:11 +01:00
|
|
|
;; ToDo: probably not the best way to get a keyword from a string
|
|
|
|
(defun mattermost-string->keyword (str)
|
|
|
|
"Returns a keyword from a string"
|
|
|
|
(read (concat ":" str)))
|
|
|
|
|
2022-05-22 12:00:26 +01:00
|
|
|
(defun mattermost-parse-json ()
|
|
|
|
"Parses the JSON in the current buffer after a url-request"
|
|
|
|
(let ((json-object-type 'plist)
|
|
|
|
(json-array-type 'list)
|
|
|
|
(json-key-type 'keyword))
|
|
|
|
(goto-char url-http-end-of-headers)
|
|
|
|
(json-read)))
|
|
|
|
|
2022-05-22 19:09:12 +01:00
|
|
|
(defun mattermost-print-post (post)
|
|
|
|
"Prints the post in the current buffer"
|
|
|
|
(let* ((msg (plist-get post :message))
|
|
|
|
;; ToDo: convert to a readable date
|
|
|
|
;; (update-at (plist-get post :update_at))
|
|
|
|
(user-id (plist-get post :user_id))
|
|
|
|
(user (mattermost--get-user user-id))
|
|
|
|
(username (plist-get user :username)))
|
|
|
|
(insert (format "[%s] %s\n" username msg))))
|
|
|
|
|
|
|
|
(defun mattermost--get-user (user-id)
|
2022-05-22 19:10:41 +01:00
|
|
|
"Returns the user from the internal cache and fills the cache
|
|
|
|
if the user is not present"
|
2022-05-22 19:09:12 +01:00
|
|
|
(let* ((user-id-keyword (mattermost-string->keyword user-id))
|
|
|
|
(user (plist-get mattermost-users-plist user-id-keyword)))
|
|
|
|
(if (not user)
|
|
|
|
(let ((user (mattermost-get-user user-id)))
|
|
|
|
(setq mattermost-users-plist (plist-put mattermost-users-plist user-id-keyword user)))
|
|
|
|
user)))
|
|
|
|
|
2022-05-22 12:00:26 +01:00
|
|
|
;; 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
|
|
|
|
;; token)
|
|
|
|
(defun mattermost-login (username password)
|
|
|
|
"Log into the Mattermost Server"
|
|
|
|
(let ((url-request-method "POST")
|
2022-05-22 17:12:46 +01:00
|
|
|
(url-request-extra-headers '(("Content-Type" . "application/json")))
|
2022-05-22 19:11:46 +01:00
|
|
|
(url-request-data (json-serialize `(:login_id ,username :password ,password))))
|
2022-05-22 12:00:26 +01:00
|
|
|
(with-current-buffer (url-retrieve-synchronously (concat mattermost-server-url "/api/v4/users/login"))
|
|
|
|
(beginning-of-buffer)
|
|
|
|
(search-forward "Token: ")
|
|
|
|
(let ((token (word-at-point))
|
|
|
|
(response (mattermost-parse-json)))
|
|
|
|
(setq mattermost-token token)
|
|
|
|
(setq mattermost-user-id (plist-get response :id))
|
|
|
|
token))))
|
|
|
|
|
|
|
|
;; ToDo: update to parse headers as well
|
|
|
|
(defun mattermost-request (method url &optional body)
|
2022-05-22 17:13:39 +01:00
|
|
|
"Builds a Mattermost request and returns the JSON response"
|
2022-05-22 12:00:26 +01:00
|
|
|
(let ((url-request-method method)
|
|
|
|
(url-request-extra-headers `(("Content-Type" . "application/json")))
|
|
|
|
(url-request-data (if body (json-serialize body))))
|
|
|
|
(if mattermost-token
|
2022-05-22 17:12:46 +01:00
|
|
|
(add-to-list 'url-request-extra-headers `("Authorization" . ,(concat "Bearer " mattermost-token))))
|
2022-05-22 12:00:26 +01:00
|
|
|
(with-current-buffer (url-retrieve-synchronously (concat mattermost-server-url "/api/v4" url) t)
|
|
|
|
(mattermost-parse-json))))
|
|
|
|
|
2022-05-22 19:09:12 +01:00
|
|
|
(defun mattermost-get-user (user-id)
|
|
|
|
"Returns the user information"
|
|
|
|
(mattermost-request "GET" (format "/users/%s" user-id)))
|
|
|
|
|
2022-05-22 12:00:26 +01:00
|
|
|
(defun mattermost-get-teams ()
|
|
|
|
"Returns the user's team list"
|
|
|
|
(mattermost-request "GET" "/teams"))
|
|
|
|
|
|
|
|
(defun mattermost-get-channels (team-id)
|
|
|
|
"Returns the user's channel for a given team"
|
|
|
|
(let ((url (format "/users/%s/teams/%s/channels" mattermost-user-id team-id)))
|
|
|
|
(message "Channels url: %s" url)
|
|
|
|
(mattermost-request "GET" url)))
|
|
|
|
|
2022-05-22 17:02:11 +01:00
|
|
|
(defun mattermost-get-channel-messages (channel-id &optional page per-page)
|
|
|
|
"Returns a list of posts for a given channel"
|
|
|
|
(let ((url (format "/channels/%s/posts" channel-id)))
|
|
|
|
(mattermost-request "GET" url)))
|
|
|
|
|
2022-05-22 12:00:26 +01:00
|
|
|
(with-current-buffer (get-buffer-create "*Mattermost Teams*")
|
|
|
|
(let ((teams (mattermost-get-teams)))
|
|
|
|
(erase-buffer)
|
|
|
|
(dolist (team teams)
|
|
|
|
(let* ((team-id (plist-get team :id))
|
|
|
|
(team-display-name (plist-get team :display_name))
|
|
|
|
(channels (mattermost-get-channels team-id)))
|
|
|
|
(insert (format "%s\n" team-display-name))
|
|
|
|
(dolist (channel channels)
|
|
|
|
(let ((channel-id (plist-get channel :id))
|
|
|
|
(channel-display-name (plist-get channel :display_name))
|
|
|
|
(channel-name (plist-get channel :name)))
|
2022-05-22 17:02:11 +01:00
|
|
|
(insert (format "> [%s] %s\n" channel-id (if (string= channel-display-name "")
|
|
|
|
channel-name
|
|
|
|
channel-display-name)))))))))
|
|
|
|
|
2022-05-22 19:09:12 +01:00
|
|
|
;; ToDo: remove
|
2022-05-22 17:02:11 +01:00
|
|
|
(setq msgs (mattermost-get-channel-messages "68w17u1da7yg7enayudjjqqwse"))
|
|
|
|
(car (plist-get msgs :posts))
|
|
|
|
|
|
|
|
(with-current-buffer (get-buffer-create "*Town Square*")
|
|
|
|
(erase-buffer)
|
2022-05-22 19:09:12 +01:00
|
|
|
(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)))))
|
2022-05-22 12:00:26 +01:00
|
|
|
|
|
|
|
(provide 'mattermost)
|
|
|
|
;;; mattermost.el ends here
|