diff options
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-room.el')
-rw-r--r-- | configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-room.el | 501 |
1 files changed, 501 insertions, 0 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-room.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-room.el new file mode 100644 index 000000000000..b547fe4b7fb7 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-room.el @@ -0,0 +1,501 @@ +;;; slack-room.el --- slack generic room interface -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 南優也 + +;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> +;; Keywords: + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'lui) +(require 'slack-util) +(require 'slack-request) +(require 'slack-message) +(require 'slack-pinned-item) + +(defvar slack-buffer-function) +(defconst slack-room-pins-list-url "https://slack.com/api/pins.list") + +(defclass slack-room () + ((name :initarg :name :type (or null string) :initform nil) + (id :initarg :id) + (created :initarg :created) + (latest :initarg :latest) + (unread-count :initarg :unread_count :initform 0 :type integer) + (unread-count-display :initarg :unread_count_display :initform 0 :type integer) + (messages :initarg :messages :initform ()) + (team-id :initarg :team-id) + (last-read :initarg :last_read :type string :initform "0"))) + +(defgeneric slack-room-name (room)) +(defgeneric slack-room-history (room team &optional oldest after-success sync)) +(defgeneric slack-room-update-mark-url (room)) + +(defmethod slack-equalp ((this slack-room) other) + (string= (oref this id) + (oref other id))) + +(defmethod slack-merge ((this slack-room) other) + "except MESSAGES" + (oset this name (oref other name)) + (oset this id (oref other id)) + (oset this created (oref other created)) + (oset this latest (oref other latest)) + (oset this unread-count (oref other unread-count)) + (oset this unread-count-display (oref other unread-count-display)) + (oset this team-id (oref other team-id)) + (unless (string= "0" (oref other last-read)) + (oset this last-read (oref other last-read)))) + +(defun slack-room-create (payload team class) + (cl-labels + ((prepare (p) + (plist-put p :members + (append (plist-get p :members) nil)) + (plist-put p :team-id (oref team id)) + p)) + (let* ((attributes (slack-collect-slots class (prepare payload))) + (room (apply #'make-instance class attributes))) + (oset room latest (slack-message-create (plist-get payload :latest) team :room room)) + room))) + +(defmethod slack-room-subscribedp ((_room slack-room) _team) + nil) + +(defmethod slack-room-buffer-name ((room slack-room)) + (concat "*Slack*" + " : " + (slack-room-display-name room))) + +(cl-defmacro slack-select-from-list ((alist prompt &key initial) &body body) + "Bind candidates from selected." + (declare (indent 2) (debug t)) + (let ((key (cl-gensym))) + `(let* ((,key (let ((completion-ignore-case t)) + (funcall slack-completing-read-function (format "%s" ,prompt) + ,alist nil t ,initial))) + (selected (cdr (cl-assoc ,key ,alist :test #'string=)))) + ,@body + selected))) + +(defmethod slack-room-hidden-p ((room slack-room)) + (slack-room-hiddenp room)) + +(defun slack-room-hiddenp (room) + (or (not (slack-room-member-p room)) + (slack-room-archived-p room) + (not (slack-room-open-p room)))) + +(defmacro slack-room-names (rooms &optional filter) + `(cl-labels + ((latest-ts (room) + (with-slots (latest) room + (if latest (oref latest ts) "0"))) + (sort-rooms (rooms) + (nreverse + (cl-sort rooms #'string< + :key #'(lambda (name-with-room) (latest-ts (cdr name-with-room))))))) + (sort-rooms + (cl-loop for room in (if ,filter + (funcall ,filter ,rooms) + ,rooms) + collect (cons (slack-room-label room) room))))) + +(defun slack-room-select (rooms) + (let* ((alist (slack-room-names + rooms #'(lambda (rs) (cl-remove-if #'slack-room-hidden-p rs))))) + (slack-select-from-list (alist "Select Channel: ")))) + +(cl-defun slack-room-list-update (url success team &key (sync t)) + (slack-request + (slack-request-create + url + team + :success success))) + +(defun slack-room-find-message (room ts) + (cl-find-if #'(lambda (m) (string= ts (oref m ts))) + (oref room messages) + :from-end t)) + +(defun slack-room-find-thread-parent (room thread-message) + (slack-room-find-message room (oref thread-message thread-ts))) + +(defmethod slack-message-thread ((this slack-message) _room) + (oref this thread)) + +(defmethod slack-message-thread ((this slack-reply-broadcast-message) room) + (let ((message (slack-room-find-message room + (or (oref this broadcast-thread-ts) + (oref this thread-ts))))) + (slack-message-thread message room))) + +(defun slack-room-find-thread (room ts) + (let ((message (slack-room-find-message room ts))) + (when message + (slack-message-thread message room)))) + +(defmethod slack-room-team ((room slack-room)) + (slack-team-find (oref room team-id))) + +(defmethod slack-room-display-name ((room slack-room)) + (let ((room-name (slack-room-name room))) + (if slack-display-team-name + (format "%s - %s" + (oref (slack-room-team room) name) + room-name) + room-name))) + +(defmethod slack-room-label-prefix ((_room slack-room)) + " ") + +(defmethod slack-room-unread-count-str ((room slack-room)) + (with-slots (unread-count-display) room + (if (< 0 unread-count-display) + (concat " (" + (number-to-string unread-count-display) + ")") + ""))) + +(defmethod slack-room-label ((room slack-room)) + (format "%s%s%s" + (slack-room-label-prefix room) + (slack-room-display-name room) + (slack-room-unread-count-str room))) + +(defmethod slack-room-name ((room slack-room)) + (oref room name)) + +(defun slack-room-sort-messages (messages) + (cl-sort messages + #'string< + :key #'(lambda (m) (oref m ts)))) + +(defun slack-room-reject-thread-message (messages) + (cl-remove-if #'(lambda (m) (and (not (eq (eieio-object-class-name m) + 'slack-reply-broadcast-message)) + (slack-thread-message-p m))) + messages)) + +(defmethod slack-room-sorted-messages ((room slack-room)) + (with-slots (messages) room + (slack-room-sort-messages (copy-sequence messages)))) + +(defmethod slack-room-set-prev-messages ((room slack-room) prev-messages) + (slack-room-set-messages room + (append (oref room messages) + prev-messages))) + +(defmethod slack-room-append-messages ((room slack-room) messages) + (slack-room-set-messages room + (append messages (oref room messages)))) + +(defmethod slack-room-update-latest ((room slack-room) message) + (when (and message + (not (slack-thread-message-p message))) + (with-slots (latest) room + (if (or (null latest) + (string< (oref latest ts) (oref message ts))) + (setq latest message))))) + +(defmethod slack-room-push-message ((room slack-room) message) + (with-slots (messages) room + (setq messages + (cl-remove-if #'(lambda (n) (slack-message-equal message n)) + messages)) + (push message messages))) + +(defmethod slack-room-set-messages ((room slack-room) messages) + (let* ((sorted (slack-room-sort-messages + (cl-delete-duplicates messages + :test #'slack-message-equal))) + (oldest (car sorted)) + (latest (car (last sorted)))) + (oset room messages sorted) + (slack-room-update-latest room latest))) + +(defmethod slack-room-prev-messages ((room slack-room) from) + (with-slots (messages) room + (cl-remove-if #'(lambda (m) + (or (string< from (oref m ts)) + (string= from (oref m ts)))) + (slack-room-sort-messages (copy-sequence messages))))) + +(defmethod slack-room-update-mark ((room slack-room) team ts) + (cl-labels ((on-update-mark (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-room-update-mark")))) + (with-slots (id) room + (slack-request + (slack-request-create + (slack-room-update-mark-url room) + team + :type "POST" + :params (list (cons "channel" id) + (cons "ts" ts)) + :success #'on-update-mark))))) + +(defun slack-room-pins-list () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-display-pins-list buf))) + +(defun slack-select-rooms () + (interactive) + (let* ((team (slack-team-select)) + (room (slack-room-select + (cl-loop for team in (list team) + append (with-slots (groups ims channels) team + (append ims groups channels)))))) + (slack-room-display room team))) + +(defun slack-create-room (url team success) + (slack-request + (slack-request-create + url + team + :type "POST" + :params (list (cons "name" (read-from-minibuffer "Name: "))) + :success success))) + +(defun slack-room-rename (url room-alist-func) + (cl-labels + ((on-rename-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-room-rename")))) + (let* ((team (slack-team-select)) + (room-alist (funcall room-alist-func team)) + (room (slack-select-from-list + (room-alist "Select Channel: "))) + (name (read-from-minibuffer "New Name: "))) + (slack-request + (slack-request-create + url + team + :params (list (cons "channel" (oref room id)) + (cons "name" name)) + :success #'on-rename-success))))) + +(defmacro slack-current-room-or-select (room-alist-func &optional select) + `(if (and (not ,select) + (bound-and-true-p slack-current-buffer) + (slot-boundp slack-current-buffer 'room)) + (oref slack-current-buffer room) + (let* ((room-alist (funcall ,room-alist-func))) + (slack-select-from-list + (room-alist "Select Channel: "))))) + +(defmacro slack-room-invite (url room-alist-func) + `(cl-labels + ((on-group-invite (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-room-invite") + (if (plist-get data :already_in_group) + (message "User already in group") + (message "Invited!"))))) + (let* ((team (slack-team-select)) + (room (slack-current-room-or-select + #'(lambda () + (funcall ,room-alist-func team + #'(lambda (rooms) + (cl-remove-if #'slack-room-archived-p + rooms)))))) + (user-id (plist-get (slack-select-from-list + ((slack-user-names team) + "Select User: ")) :id))) + (slack-request + (slack-request-create + ,url + team + :params (list (cons "channel" (oref room id)) + (cons "user" user-id)) + :success #'on-group-invite))))) + +(defmethod slack-room-member-p ((_room slack-room)) t) + +(defmethod slack-room-archived-p ((_room slack-room)) nil) + +(defmethod slack-room-open-p ((_room slack-room)) t) + +(defmethod slack-room-equal-p ((room slack-room) other) + (string= (oref room id) (oref other id))) + +(defun slack-room-deleted (id team) + (let ((room (slack-room-find id team))) + (cond + ((object-of-class-p room 'slack-channel) + (with-slots (channels) team + (setq channels (cl-delete-if #'(lambda (c) (slack-room-equal-p room c)) + channels))) + (message "Channel: %s deleted" + (slack-room-display-name room)))))) + +(cl-defun slack-room-request-with-id (url id team success) + (slack-request + (slack-request-create + url + team + :params (list (cons "channel" id)) + :success success))) + +(defmethod slack-room-inc-unread-count ((room slack-room)) + (cl-incf (oref room unread-count-display))) + +(defun slack-room-find-by-name (name team) + (cl-labels + ((find-by-name (rooms name) + (cl-find-if #'(lambda (e) (string= name + (slack-room-name e))) + rooms))) + (or (find-by-name (oref team groups) name) + (find-by-name (oref team channels) name) + (find-by-name (oref team ims) name)))) + +(defmethod slack-room-info-request-params ((room slack-room)) + (list (cons "channel" (oref room id)))) + +(defmethod slack-room-create-info-request ((room slack-room) team) + (cl-labels + ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-room-info-request" + #'(lambda (e) + (if (not (string= e "user_disabled")) + (message "Failed to request slack-room-info-request: %s" e)))) + (slack-room-update-info room data team)))) + (slack-request-create + (slack-room-get-info-url room) + team + :params (slack-room-info-request-params room) + :success #'on-success))) + +(defmethod slack-room-info-request ((room slack-room) team) + (slack-request + (slack-room-create-info-request room team))) + +(defmethod slack-room-get-members ((room slack-room)) + (oref room members)) + +(defun slack-room-user-select () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-display-user-profile buf))) + +(defun slack-select-unread-rooms () + (interactive) + (let* ((team (slack-team-select)) + (room (slack-room-select + (cl-loop for team in (list team) + append (with-slots (groups ims channels) team + (cl-remove-if + #'(lambda (room) + (not (< 0 (oref room + unread-count-display)))) + (append ims groups channels))))))) + (slack-room-display room team))) + +(defmethod slack-user-find ((room slack-room) team) + (slack-user--find (oref room user) team)) + +(defun slack-room-find-file-comment-message (room comment-id) + (let ((messages (oref room messages))) + (cl-find-if #'(lambda (m) (and + (object-of-class-p m 'slack-file-message) + (or + (and (slack-file-share-message-p m) + (oref (oref m file) initial-comment) + (string= comment-id + (oref (oref + (oref m file) + initial-comment) + id))) + (and + (slot-exists-p m 'comment) + (slot-boundp m 'comment) + (string= comment-id (oref (oref m comment) id)))))) + messages))) + +(defun slack-room-find-file-share-message (room file-id) + (let ((messages (oref room messages))) + (cl-find-if #'(lambda (m) (and (slack-file-share-message-p m) + (slot-exists-p m 'file) + (slot-boundp m 'file) + (string= file-id (oref (oref m file) id)))) + messages))) + +(defun slack-room-display (room team) + (cl-labels + ((open (buf) + (slack-buffer-display buf))) + (let* ((buf (slack-buffer-find (or (and (eq (eieio-object-class-name room) + 'slack-file-room) + 'slack-file-list-buffer) + 'slack-message-buffer) + room team))) + (if buf (open buf) + (message "No Message in %s, fetching from server..." (slack-room-name room)) + (slack-room-history-request + room team + :after-success #'(lambda (&rest _ignore) + (open (slack-create-message-buffer room team)))))))) + +(defmethod slack-room-update-buffer ((this slack-room) team message replace) + (slack-if-let* ((buffer (slack-buffer-find 'slack-message-buffer this team))) + (slack-buffer-update buffer message :replace replace) + (and slack-buffer-create-on-notify + (slack-room-history-request + this team + :after-success #'(lambda (&rest _ignore) + (tracking-add-buffer + (slack-buffer-buffer + (slack-create-message-buffer this team)))))))) + +(cl-defmethod slack-room-history-request ((room slack-room) team &key oldest latest count after-success async) + (cl-labels + ((on-request-update + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-room-request-update") + (let ((messages + (cl-loop for message in (plist-get data :messages) + collect (slack-message-create message team :room room))) + (has-more (not (eq :json-false (plist-get data :has_more))))) + (if oldest (slack-room-set-prev-messages room messages) + (if latest (slack-room-append-messages room messages) + (slack-room-set-messages room messages))) + (if (and after-success (functionp after-success)) + (funcall after-success has-more)))))) + (slack-request + (slack-request-create + (slack-room-history-url room) + team + :params (list (cons "channel" (oref room id)) + (if oldest (cons "latest" oldest)) + (if latest (cons "oldest" latest)) + (cons "count" (number-to-string (or count 100)))) + :success #'on-request-update)))) + +(defmethod slack-room-member-p ((this slack-room)) + t) + +(provide 'slack-room) +;;; slack-room.el ends here |